The Arduino watchdog timer, on an Uno with a button that hangs it
Beginner
Or see every lesson.
- 455parts on the bench
- 43boards running now
- 1.00xreal time, on every board
The watchdog is a timer of its own inside the chip that restarts the board unless the sketch says "still alive" in time. Turn it on with wdt_enable(WDTO_2S) from <avr/wdt.h> and call wdt_reset() in loop(). As long as loop() keeps coming around, nothing happens. If the sketch hangs, in a loop that never ends or waiting on a sensor that never answers, two seconds pass with no reset and the watchdog restarts it from the top.
The circuit above is a button on pin 2 and an LED on an Uno. Paste the first sketch below into it and press Run. The serial monitor prints "started". Press the button and the sketch prints "stuck!" and hangs in a while (true), and about two seconds later it prints "started" again: the watchdog reset it.
Below is that sketch, how to tell a watchdog reset from a power-on, the timeouts, the endless reset loop and how to avoid it, and the watchdog as a slow interrupt, each run on an Uno with what it printed.
A sketch that resets itself
Here is the sketch. setup() turns the watchdog on last, after everything slow is done. loop() pats it first thing every time around. The button stands in for a real hang, a sensor read that waits for ever, say: it prints "stuck!" and goes into a loop with no way out, and no more pats. It printed "started", "stuck!" and then "started" again.
The restart is a real reset: every variable starts again from its first value and setup() runs again. The watchdog does not fix the bug that hung the sketch. It gets a device that runs on its own back to work, and a sketch should log or count the reset so the bug can be found.
#include <avr/wdt.h>
void setup() {
Serial.begin(9600);
pinMode(2, INPUT_PULLUP);
Serial.println("started");
wdt_enable(WDTO_2S);
}
void loop() {
wdt_reset();
if (digitalRead(2) == LOW) {
Serial.println("stuck!");
while (true) {
}
}
delay(100);
}The timeouts
The watchdog counts its own 128 kHz oscillator, not the 16 MHz crystal, so its times are rough and do not change with the clock. The choices are WDTO_15MS, WDTO_30MS, WDTO_60MS, WDTO_120MS, WDTO_250MS, WDTO_500MS, WDTO_1S, WDTO_2S, WDTO_4S and WDTO_8S; 8 seconds is the longest. Pick one comfortably longer than the slowest normal pass through loop().
A long delay counts as a hang. With a 2 second watchdog, delay(3000) in loop() reset the board before the wait was over: in 7 seconds it printed "started" four times and "done waiting" never. Break long waits into short ones with a wdt_reset() in between, or better, time them with millis().
Was that the watchdog?
The chip keeps the reason for the last reset in MCUSR, and the WDRF bit is set after a watchdog reset. The sketch below reads it first thing in setup(), then clears it. It printed "power on", and after the button hung it, "reset by the watchdog".
Clearing MCUSR and calling wdt_disable() at the very top of setup() matter for another reason, below. On a stock Uno, the Optiboot bootloader reads and clears these flags and turns the watchdog off before your sketch starts, so on that board setup() usually finds MCUSR already empty. Mokxi runs the sketch with no bootloader in front of it, like a chip programmed through its ICSP header, so the flags reach setup() as they are.
#include <avr/wdt.h>
void setup() {
byte cause = MCUSR;
MCUSR = 0;
wdt_disable();
Serial.begin(9600);
pinMode(2, INPUT_PULLUP);
if (cause & (1 << WDRF)) {
Serial.println("reset by the watchdog");
} else {
Serial.println("power on");
}
wdt_enable(WDTO_1S);
}
void loop() {
wdt_reset();
if (digitalRead(2) == LOW) {
while (true) {
}
}
}The endless reset loop
After a watchdog reset, while WDRF is set, the chip keeps the watchdog on at its shortest time, about 16 milliseconds. A sketch that starts slowly never gets the chance to set its own timeout. With delay(100) in setup() before wdt_enable(WDTO_1S), one press of the button left the board restarting every few milliseconds: it printed "started" more than a hundred times in the next two seconds.
The fix is the first three lines of the sketch above: read MCUSR, clear it, wdt_disable(), before anything else. On real boards the bootloader decides much of this. Optiboot on an Uno turns the watchdog off for you, but the older bootloader on many Nano boards does not, and a watchdog reset can leave such a board stuck restarting until it is unplugged or given a new bootloader.
The watchdog as a slow interrupt
Set its WDIE bit instead of WDE and the watchdog calls ISR(WDT_vect) instead of resetting. The sketch below asks for one second; the handler ran at 1024, 2048, 3072 and 4096 ms, a second by the watchdog’s own oscillator. Changing WDTCSR takes two writes in a row, the first setting WDCE and WDE, as the data sheet asks. This is the timer that wakes a battery sketch from sleep, because it keeps running when everything else is stopped.
#include <avr/wdt.h>
volatile int barks = 0;
ISR(WDT_vect) {
barks++;
}
void setup() {
Serial.begin(9600);
noInterrupts();
wdt_reset();
WDTCSR = (1 << WDCE) | (1 << WDE);
WDTCSR = (1 << WDIE) | (1 << WDP2) | (1 << WDP1);
interrupts();
}
void loop() {
static int shown = 0;
if (barks != shown) {
shown = barks;
Serial.print("bark ");
Serial.print(shown);
Serial.print(" at ");
Serial.println(millis());
}
}Questions
What is the watchdog timer on an Arduino?
A separate timer in the chip that resets the board unless the sketch calls wdt_reset() before it runs out. It gets a hung sketch going again without anyone pressing reset.
How do I use the watchdog timer on an Arduino Uno?
Include <avr/wdt.h>, call wdt_enable(WDTO_2S) at the end of setup() and wdt_reset() once every time around loop(). Choose a timeout longer than loop()’s slowest normal pass.
Why does my Arduino keep resetting with the watchdog?
Something in loop() takes longer than the timeout, often a long delay(), or the sketch starts too slowly after a watchdog reset, when the chip keeps a 16 ms timeout until MCUSR is cleared. Clear MCUSR and call wdt_disable() first thing in setup().
What is the longest watchdog timeout?
About 8 seconds, WDTO_8S. For longer, use the watchdog interrupt and count several of them before deciding the sketch is stuck.
Does the watchdog work on a Nano?
The chip is the same, so the code is the same. Older Nano boards carry a bootloader that does not switch the watchdog off after it fires, which can leave the board resetting until a new bootloader is burned.
Keep going
Where the facts on this page come from
Build this for real
Open the editor, change a value and watch the number move with it. Nothing to install, and no account needed.