Quote:
Originally Posted by MaGiC_PiKaChU
Our team experienced the same delay when we reset our encoders value directly on the SRX, and also when changing profiles.
I assume you are CAN connected, and we figured out this is what causes the delays on our side.
Edit : delays are about 100ms maximum, and didn't occur when we had only 2 SRX on the CAN wires (we now have 14)
|
I don't really understand this. How did you measure 100ms? 100ms between what and what?
The frame rates for everything is fixed, so it doesn't matter how many Talons there are on the bus. That's the design. The GetPosition() value is updated over CAN every 20ms (default). If the change-in-signal-value is a problem, you can speed up that frame for that particular Talon (see section 20.5). That's also used in the example in this post. Just keep an eye on your bus utilization.
I just tested this to see if I can reproduce what you're describing but it seems okay to me. 16 Talon robot (with 20 software Talon objects) so bandwidth doesn't seem to be a problem. Code below.
I recommend presetting the gain values ahead of time and just selecting the profile when you switch modes. Setting gains requires extra and unnecessary framing, but switching between two profiles has zero-footprint on the CAN bus since it's a signal in the fixed-rate control frame. And it's synchronous with all other control signals.
Your main loop might be really slow for other unrelated reasons. Try toggling an IO in your main loop and oscop-ing it (great opportunity to learn about oscilloscopes). How fast should your loop be running versus how fast does it actually run?
You can also try speeding up the control frame to see how that impacts things. That might help you understand what exactly is causing your problem.
The symptom reported by the OP sounds a lot like the wrong set point was initially set, but without the entire project it's difficult to be sure.
Code:
#include "WPILib.h"
class Robot: public IterativeRobot
{
Joystick _joy0; //!< Just a single gamepad
CANSpeedController::ControlMode _md; //!< track what mode we want for our test talon
long _servoPos; //!< track our servo position for when we want to closed-loop
bool _btn1; //!< last state of btn1 for on-press detection
CANTalon * _tals[20]; //!< make a ton of talons. 16 of them are present on my test robot. ~78% percent bus utilization according to DS.
public:
Robot() : _joy0(0), _md(CANSpeedController::kPercentVbus), _servoPos(0), _btn1(false)
{
/* create 20 Talons, 16 of them are present on my robot */
for(int i=0;i<20;++i)
_tals[i] = new CANTalon(i);
_tals[1]->SetControlMode(_md); /* start in percent mode */
_tals[1]->SetSensorDirection(true); /* sensor and motor are out-of-phase, so flip the sensor */
/* speed up the CAN frame that reports sensor position, so calling GetPosition() is as fresh as possible */
_tals[1]->SetStatusFrameRateMs(CANTalon::StatusFrameRateFeedback,1); /* 72% => 78%, added 6% to CANBus Util*/
}
void TeleopInit()
{
/* empty */
}
void TeleopPeriodic()
{
/* grab joystick inputs */
double y = -1 * _joy0.GetY(); /* moving-axis-up should be positive now */
bool btn1 = _joy0.GetRawButton(1);
/* btn1 => servo pos1 */
if(!_btn1 && btn1){
/* change to position mode */
_md = CANSpeedController::kPosition;
_tals[1]->SetControlMode(_md);
/* calc where to servo to, say 5000 units from wherever we are now.
* An absolute value can be used too if that makes sense. */
_servoPos = _tals[1]->GetPosition() + 5000;
}else if((y > 0.05) || (y < -0.05)){
/* y axis is being used, change to throttle mode */
_md = CANSpeedController::kPercentVbus;
_tals[1]->SetControlMode(_md);
/* y axis is used below */
}else{
/* y axis is in the dead band. So servo to last known position */
if(_md == CANSpeedController::kPercentVbus){
/* we are in throttle mode, better go back to servo where we are */
_md = CANSpeedController::kPosition; /* change to pos mode */
_tals[1]->SetControlMode(_md);
/* calc where to servo to */
_servoPos = _tals[1]->GetPosition();
}else{
/* we are servo-ing to our last position */
}
}
/* based on selected mode, apply the correct target value. */
if(_md == CANSpeedController::kPercentVbus){
_tals[1]->Set(y);
}else if(_md == CANSpeedController::kPosition){
_tals[1]->Set(_servoPos);
}
/* save button state for detecting on-press */
_btn1 = btn1;
}
};
START_ROBOT_CLASS(Robot);