The relay code behavior appears to have changed when we updated the cRio firmware from v19 to v20.
The relay is set into forward only mode. When a joystick button is pushed, the relay is turned “on” (sets it to kOn). Our code then sleeps for 500 ms, then turns the relay off (sets it to kOff).
Before the update to v20, this worked as expected. The relay light would turn green for half a second, then turn back to amber. Now, it only stays green for maybe a tenth of a second. We increased the sleep time to several seconds, but it is having no effect. It seems like the relay code is turning itself off. Any ideas about what could have happened?
99.99999999% of the time, programmers will correlate mysterious bugs with things like Windows updates, daylight savings time, tacos at lunch, and updating the cRio to v20. In actuality, the program was changed at around the same time and now it doesn’t work. Post your code and we can fix it regardless of what version your cRio is running. :]
Without seeing your code, though, I might suggest that you use a timer to control time sensitive actions. It’s not a good idea to pause your robot code. Imagine if you just passed out for .5 seconds then woke up. You would be confused. It is better practice to let your code cycle so that all the sensor and user input can be processed and acted upon. So for your relay, you would start the timer when the button is pushed, set the relay to kOn until the timer reaches your setpoint, then kOff.
To elaborate on the previous post, the last update to WPILibJ enables the watchdog by default and sets the timeout to 0.1 seconds. Since your user program is sleeping the watchdog is not being fed and the output is disabled after the tenth of a second as described. I would recommend to use a timer or a separate thread for this rather than pause all of your code.
OK, I think the light bulb over my head is beginning to make buzzing noises and glow dimly.
We have not tried this yet (and please correct me if I am wrong), but it appears that the *user *watchdog is set to timeout after .1 seconds, and since our user code is sleeping for .5 seconds, nobody is kicking the dog, and it is therefore zapping us.
First, this evening we are going to try just disabling the user watchdog during init to see if that corrects the issue(?) Based on the results of that test, we will investigate changing the structure of our code to put some kind of dog-kicking mechanism into a separate thread, or setting the timeout on the watchdog to 1 second, or leave it disabled. (If leaving it disabled is verboten, PLEASE let me know!)
Assuming we are now merrily on our way, thanks for the input!
Sounds like you have it figured out. The best way to deal with this is to do your delaying asynchronously via a timer, thus letting your Watchdog get fed (not kicked! :)) by your main thread of execution. But turning off the Watchdog or setting the timeout to something longer than your delay would also be technically correct (if a bit more unsafe). Making a separate thread to feed your Watchdog is not something that I would not recommend (having a safety mechanism in place that does nothing to ensure safety is arguably worse than having none at all).
I agree with Jared that you should apply a timer to your timed functions (as mentioned previously). Your idea of starting another thread for the watchdog is interesting, but I’m not sure if it will work as the watchdog is attached to your RobotBase which is extended by IterativeRobot and SimpleRobot. It is, in general, ok to disable the watchdog to test problems, but the robot should be up on blocks. You cannot disable a runaway robot that is no longer listening to controls, which is the reason why the watchdog is there. Here is how we handle our kick timer (in stripped down code)
public class IRobot extends IterativeRobot
Timer robotTime = new Timer();
Joystick js_right = new Joystick(1);
Joystick js_left = new Joystick(2);
Solenoid latch = new Solenoid(1);
Solenoid unlatch = new Solenoid(2);
Solenoid kick1 = new Solenoid(3);
Solenoid unkick1 = new Solenoid(4);
public void robotInit()
public void disabledPeriodic()
* This function is called periodically during operator control
public void teleopPeriodic()
if (!kicking && js_left.getTrigger())
kicking = true;
public boolean kickTimer()
if (robotTime.get() == 0)
} else if (robotTime.get() >= 0.5)
if (robotTime.get() >= 4)
// GET READY TO KICK AGAIN
kicking = false;
It should be noted that the Timer object here is the one defined by the WPI library and NOT the one defined by java.util.