Hello folks,
We are tryiing to disable safety mode on the SparkMax Controllers.
The command to do this should be SparkMaxLeft -> SetSafetyEnabled(false) but when we compile this we get…
We tried, just
sparkMaxLeft->SetSafetyEnabled(false);
as well, (actually this is what we tried first), and while Intelisence suggests that it is valid via autocomplete, when we try to compile it, it fails.
We get the same message that SetSafetyEnabled is not a
is not a base of ‘rev::CANSparkMax’
…Subsystems\DriveSubsystem.cpp:54:19: error: ‘class rev::CANSparkMax’ has no member named ‘SetSafetyEnabled’
sparkMaxLeft->SetSafetyEnabled(false);
^~~~~~~~~~~~~~~~
Oh. That’s because it doesn’t inherit from MotorSafety and doesn’t implement that function itself. In that case, I don’t know how to disable it. Are you sure you need to?
Yes, unfortunately we absolutely have to disable it. We are using the PID functions of this controller, and so we are setting a reference position, and letting the motor hunt to that postion. During which time, the motor will not get updated in 100ms so the watchdog is kicking in and killing the operation of the action.
The general rule is that all outputs should be set to some value every calculation cycle. If their state has not changed, then the same output is sent to the motor. If you do not update the output value, then the motor safety watchdog assumes you forgot or your code crashed, and correctly disables the motor.
There’s no motor safety timeout to actually disable with the CANSparkMax. There’s a heartbeat that tells the controller the robot code is still alive, but there’s only one of those and it runs in a separate thread. Furthermore, the set calls have no effect on whether that heartbeat is sent. If the output is disabled, it must be from logic in the controller firmware rather than the roboRIO software.
As it relates Motors, we only have CANSparkMax, not PWM variants connected. I will double check to make sure we did not incorrectly invent a pwm constructor. (I just checked, only CANSparkMax exist).
Assuming that we have not errored, and we have only CANSparkMax motor objects defined, are you suggesting that simply, in a command based Execute() block that repeating the SetReference call with the desired position will NOT actually reset this "non existent " timer.
I will try Peter’s suggestion and report back on my progress.
Repeating the SetReference() call should be a successful workaround. What I’m saying is that CANSparkMax doesn’t have any timeouts built in, so any timeouts would have to occur in the spark firmware. That means the roboRIO would never print a message about it. If you saw a timeout message specifically referencing 100ms, that would be from a PWM motor controller instance rather than CANSparkMax.
We have a command that prints out the encoder values, and a command that will set the position 80 rotations forward from where we are at.
By setting the reference postion repeatly in execute, the command DOES work as expected, however during the run, we recieve a timeout related to the differental drive.
What we suspect is happening is that we have a side effect of having a differental drive that is running, but when we “take over” the motors, the differential drive class feels starved for attention.
when it times out, it has the effect of reseting the sparkmax encoders back to zero. The same effect if we reboot the rio.
We have just commented out our differential drive constructor and will report if this settles things down. If it does, we have to figure out why this is happening.
md
FRC: Robot radio detection times. NT: server: client CONNECTED: 10.7.72.223 port 54586
encoderL:0
encoderR:0
ERROR -6 A timeout has been exceeded: DifferentialDrive… Output not updated often enough. Check [MotorSafety.cpp:101]
Error at Check [MotorSafety.cpp:101]: A timeout has been exceeded: DifferentialDrive… Output not updated often enough.
at frc::MotorSafety::Check()
at frc::MotorSafety::CheckMotors()
at frc::DriverStation::Run()
at std::_State_impl<std::_Bind_simple<std::_Mem_fn<void (frc::DriverStation::)()> (frc::DriverStation)> >::_M_run()
at /usr/lib/libstdc++.so.6(+0x9c188) [0xb5d08188]
ERROR -6 A timeout has been exceeded: DifferentialDrive… Output not updated often enough. Check [MotorSafety.cpp:101]
Error at Check [MotorSafety.cpp:101]: A timeout has been exceeded: DifferentialDrive… Output not updated often enough.
at frc::MotorSafety::Check()
at frc::MotorSafety::CheckMotors()
at frc::DriverStation::Run()
at std::_State_impl<std::_Bind_simple<std::_Mem_fn<void (frc::DriverStation::)()> (frc::DriverStation)> >::_M_run()
at /usr/lib/libstdc++.so.6(+0x9c188) [0xb5d08188]
This can’t be the way that we should be doing this.
I think we have established that in this case this issue is not specifically a SparkMax issue, and if we were using Talons, or virtually any other motor controller we would likely have the same issue where the drive would want to be fed.
As a matter of review, the code has a drive subsystem, with a default command which is the command that reads a joystick and feeds these values to an arcade drive method.
Separately in the drivesubsystem, we have essentially move motor commands via a setreference that move the motors to the desired position.
When we don’t have a differential drive defined, we do not receive any timeouts. But if we have an active differential drive AND our other command that wants to move the motors, the drive gets starved and it complains with the errors shown above, and has the effect of also resetting the SparkMax integrated encoder back to zero.
Admittedly this is how it all started, but based on the docs, I got focused on SeteSafetyEnabled as a motor controller , and not related to the “top level” DifferentialDrive class.
So, I spinned my wheels a bit on this, but I have to thank each of you for assisting. We did solve the issues.
In short, yes, I just was able to set the SetSafetyEnabled(false) on the DifferentialDrive object and, providing some testing I am confident that this will work.