Table of Contents
- What Is a Watchdog Timer?
- How the ATMega328P Watchdog Works
- Basic Watchdog Implementation
- Timeout Values and Configuration
- Watchdog Interrupt Mode for Periodic Wake-Up
- Practical Applications: Network Recovery and Sensor Nodes
- The Bootloader Issue: Why Some Boards Reboot Loop
- Frequently Asked Questions
- Conclusion
What Is a Watchdog Timer?
The arduino watchdog timer is a hardware safety mechanism built into the ATMega328P that automatically resets the microcontroller if your program freezes, crashes, or gets stuck in an infinite loop. It works like a dead man’s switch — your code must periodically signal the watchdog (“pet” it or “kick” it), and if the signal stops coming, the watchdog assumes the program has crashed and forces a reset.
In production Arduino systems — weather stations, industrial controllers, home automation hubs, and remote sensor nodes — software crashes are inevitable. A cosmic ray bit-flip, a corrupted variable, a library bug, or a communication timeout can all cause your program to hang. Without a watchdog, a frozen Arduino stays frozen until someone physically presses the reset button or power-cycles it. With a watchdog, the system recovers automatically within seconds.
Every serious embedded system uses a watchdog timer. It is not a sign of poor programming — it is a sign of robust engineering. Even NASA spacecraft use watchdog timers on their flight computers. For Indian makers building remote deployments (rooftop weather stations, agricultural monitors, street light controllers), the watchdog is essential for unattended reliability.
How the ATMega328P Watchdog Works
The watchdog timer is a separate oscillator (128 kHz internal RC oscillator) that runs independently from the main system clock. It counts up continuously and resets the MCU when it overflows. Your program prevents the overflow by resetting the counter periodically using the wdt_reset() function.
The sequence is simple:
- Enable the watchdog with a timeout period (e.g., 2 seconds)
- In your main loop, call
wdt_reset()at least once per timeout period - If the code hangs and
wdt_reset()is not called within 2 seconds, the watchdog forces a system reset - After reset, the program starts from the beginning of
setup(), just like pressing the reset button
Basic Watchdog Implementation
#include <avr/wdt.h>
void setup() {
Serial.begin(9600);
Serial.println("System starting...");
// Enable watchdog with 2-second timeout
wdt_enable(WDTO_2S);
// Your initialisation code
Serial.println("Watchdog enabled (2s timeout)");
}
void loop() {
// Reset watchdog at the start of each loop iteration
wdt_reset();
// Your normal code
readSensors();
updateDisplay();
checkNetwork();
// If any function above takes longer than 2 seconds
// or hangs, the watchdog will reset the board
}
void readSensors() {
// Simulate sensor reading
int value = analogRead(A0);
Serial.println(value);
}
void updateDisplay() {
// Update OLED or LCD
delay(100);
}
void checkNetwork() {
// Communicate with WiFi/Ethernet module
// If the module hangs, watchdog rescues us
}
Key Rules:
- Call
wdt_reset()frequently in your main loop — at least once per timeout period - Do not put
wdt_reset()inside an interrupt — this defeats the purpose because interrupts fire even when the main code is stuck - Place
wdt_reset()at strategic points where your code should be executing, not in a separate timer ISR - Be careful with
delay()— adelay(3000)with a 2-second watchdog will trigger a reset
Timeout Values and Configuration
The ATMega328P watchdog supports these timeout values:
| Constant | Timeout | Use Case |
|---|---|---|
| WDTO_15MS | 15 ms | Ultra-tight timing loops |
| WDTO_30MS | 30 ms | Real-time control |
| WDTO_60MS | 60 ms | Motor control loops |
| WDTO_120MS | 120 ms | Fast sensor polling |
| WDTO_250MS | 250 ms | Display refresh loops |
| WDTO_500MS | 500 ms | General purpose |
| WDTO_1S | 1 second | Most projects |
| WDTO_2S | 2 seconds | Network communication |
| WDTO_4S | 4 seconds | Slow operations |
| WDTO_8S | 8 seconds | Maximum timeout |
Choose a timeout that is longer than your longest expected loop iteration but short enough to detect real hangs quickly. For most projects, 2 or 4 seconds is a good balance. If your loop includes network communication (HTTP requests, MQTT publishes), use 4 or 8 seconds since network operations can take a while.
Watchdog Interrupt Mode for Periodic Wake-Up
The watchdog can also operate in interrupt mode instead of reset mode. In this configuration, the watchdog triggers an ISR instead of resetting the MCU. This is commonly used for low-power periodic wake-up from sleep mode.
#include <avr/wdt.h>
#include <avr/sleep.h>
volatile bool watchdogFired = false;
ISR(WDT_vect) {
watchdogFired = true;
}
void setupWatchdogInterrupt() {
noInterrupts();
MCUSR &= ~(1 << WDRF);
WDTCSR |= (1 << WDCE) | (1 << WDE);
WDTCSR = (1 << WDIE) | (1 << WDP2) | (1 << WDP1); // Interrupt mode, 1 second
interrupts();
}
void setup() {
Serial.begin(9600);
pinMode(LED_BUILTIN, OUTPUT);
setupWatchdogInterrupt();
}
void loop() {
if (watchdogFired) {
watchdogFired = false;
digitalWrite(LED_BUILTIN, HIGH);
Serial.println("Woke up from watchdog!");
// Do your periodic work here
int sensor = analogRead(A0);
Serial.println(sensor);
digitalWrite(LED_BUILTIN, LOW);
}
// Enter sleep mode until watchdog wakes us
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
sleep_cpu();
sleep_disable();
}
This pattern is ideal for battery-powered sensor nodes that need to wake up periodically, take a reading, and go back to sleep. The average current in power-down mode is approximately 5 uA, extending battery life to months or years.
Practical Applications: Network Recovery and Sensor Nodes
WiFi Recovery: When an ESP8266 or WiFi module loses its connection, the Arduino’s main loop may block waiting for a response that never comes. The watchdog resets the system, reinitialises the WiFi connection, and resumes normal operation.
#include <avr/wdt.h>
void setup() {
wdt_enable(WDTO_8S); // 8-second timeout for WiFi operations
Serial.begin(9600);
connectWiFi(); // May take several seconds
}
void loop() {
wdt_reset();
if (!isWiFiConnected()) {
Serial.println("WiFi lost, reconnecting...");
connectWiFi(); // Watchdog will reset if this hangs
}
wdt_reset();
sendSensorData(); // Watchdog will reset if server is unresponsive
wdt_reset();
delay(5000); // Less than 8-second watchdog timeout
}
Remote Sensor Node: For a weather station on a rooftop in India, the watchdog ensures the system recovers from any crash without manual intervention. Combined with solar charging, the system runs indefinitely.
The Bootloader Issue: Why Some Boards Reboot Loop
The old Arduino bootloader (used on some cheaper clone boards) does not disable the watchdog timer during the boot process. If the watchdog triggers a reset, the bootloader takes too long to run (more than the watchdog timeout), and the watchdog resets the board again — creating an infinite reboot loop.
Solutions:
- Use Optiboot bootloader: Modern Arduino boards (Rev3 and later) use Optiboot, which disables the watchdog immediately on boot. If your board has the old bootloader, burn Optiboot using an ISP programmer.
- Disable watchdog in setup(): Add
wdt_disable();as the very first line in setup(), before any other initialisation. With Optiboot, this is not strictly necessary but is a good safety practice. - Add a startup delay check: Set MCUSR to detect watchdog resets and add a short delay before re-enabling the watchdog.
#include <avr/wdt.h>
void setup() {
// FIRST LINE — disable watchdog immediately
wdt_disable();
MCUSR = 0; // Clear reset flags
Serial.begin(9600);
delay(1000); // Let bootloader finish
// Now safe to enable watchdog
wdt_enable(WDTO_2S);
}
Frequently Asked Questions
Does the watchdog work during delay()?
The watchdog timer runs independently of your code. If you call delay(5000) with a 2-second watchdog timeout, the watchdog will reset the board after 2 seconds — the delay() will not complete. Break long delays into smaller chunks with wdt_reset() between them, or use millis()-based timing.
Can I detect if the Arduino was reset by the watchdog?
Yes, check the MCUSR register on startup. If bit WDRF is set, the last reset was triggered by the watchdog: if (MCUSR & (1 << WDRF)) Serial.println("Watchdog reset!"); Clear MCUSR after reading to avoid false positives on the next normal reset.
Can I change the watchdog timeout while running?
Yes, call wdt_enable() again with the new timeout value. The watchdog counter resets when you change the configuration.
Does the watchdog affect EEPROM data?
A watchdog reset is identical to pressing the reset button — EEPROM data is not affected. However, if the watchdog fires during an EEPROM write operation, the byte being written may be corrupted. Use eeprom_busy_wait() before critical operations.
Conclusion
The Arduino watchdog timer is a simple but essential reliability feature for any project that must run unattended. By adding just three lines of code — wdt_enable(), periodic wdt_reset(), and wdt_disable() in setup — you transform a fragile prototype into a self-recovering system. For remote installations, battery-powered nodes, and any project where manual reset is impractical, the watchdog is your safety net.
Add comment