Basic Watchdog Timer: (Arduino Uno/Atmega328) by Nicolas Larsen
Basic Watchdog Timer: (Arduino Uno/Atmega328) by Nicolas Larsen
Basic Watchdog Timer: (Arduino Uno/Atmega328) by Nicolas Larsen
The watchdog timer is a very useful feature for WDP0/WDP1/WDP2/WDP3 - These four bits
projects that are intended to run for extended determine how long the timer will count for before
periods of time or contain unstable loops of code. resetting. The exact time is set by setting
The watchdog is essentially a small timer that will combinations of the 4 bits in such a pattern.
force a full system restart should it not receive a
“system ok” signal from the microcontroller within a WDP WDP WDP WDP Time-out
preset time. Should in any application the micro- 3 2 1 0 (ms)
controller freeze, hang, stall or crash the watchdog 0 0 0 0 16
will time out and force a reset to the same effect as 0 0 0 1 32
pressing the reset button on your board. 0 0 1 0 64
0 0 1 1 125
0 1 0 0 250
Begin by importing the watchdog timer into your 0 1 0 1 500
code. 0 1 1 0 1000
0 1 1 1 2000
#include <avr/wdt.h>
1 0 0 0 4000
1 0 0 1 8000
Youʼll now need to configure your watchdog timer
through one of the registers known as WDTCSR.
A register is a byte or several in the systemʼs
So you can see the watchdog can be set anywhere
memory that is reserved for saving
between 16ms and 8 seconds. To let the watchdog
system settings (in lay-mans
timer know that everything is running ok and that it
terms). Every feature will have a Bit Name
neednʼt panic or take any action your going to have
register allocated to it. The 7 WDIF
to keep reseting the timer within your main loop.
microcontroller knows where to go 6 WDIE This is done by periodically entering in:
in its memory to get these 5 WDP3
registers. The watchdog is no 4 WDCE wdt_reset();
different. The watchdog register,
3 WDE
composed of one byte, thus has 8
2 WDP2 Remember: the watchdog is a timer, if you donʼt
bits in on/off settings. A ʻ1ʼ
indicates ʻONʼ and a ʻ0ʼ indicates 1 WDP1 reset it regularly it will time-out, prompting the reset
ʻOFFʼ. By default everything is set 0 WDP0 and or interrupt.
to ʻOFFʼ so we only need to set the
# 1
# 11 June 2011
Now you know the basic setting we are going to included that so you can quickly modify the time-
create a function that sets up the watchdog timer to settings should you wish to make changes.
include interrupts, a reset and time-out after
1000ms. It is good practice to comment in what you // Set Watchdog settings:
are setting each of the bits to for later reference. WDTCSR = (1<<WDIE) | (1<<WDE) |
(0<<WDP3) | (1<<WDP2) | (1<<WDP1) |
void watchdogSetup(void) (0<<WDP0);
{
cli(); If you are unfamiliar with bitwise and compound
operations the syntax may appear a bit odd to you.
wdt_reset(); I suggest you have a look on the Arduino
Reference Page for better understanding. The
/* same settings could just have easily been applied
WDTCSR configuration: in binary by:
WDIE = 1: Interrupt Enable
WDE = 1 :Reset Enable // Enter Watchdog Configuration mode:
See table for time-out variations: WDTCSR |= B00011000;
WDP3 = 0 :For 1000ms Time-out // Set Watchdog settings:
WDP2 = 1 :For 1000ms Time-out WDTCSR = B01001110;
WDP1 = 1 :For 1000ms Time-out
WDP0 = 0 :For 1000ms Time-out
*/
Now that your done with the setup you can re-
enable interrupts by typing “sei()”. The watchdog
// Enter Watchdog Configuration mode:
includes interrupts so be sure to re-enable this.
WDTCSR |= (1<<WDCE) | (1<<WDE);
The only thing left to insert in your code is the
// Set Watchdog settings:
interrupt, should you have chosen to include it.
WDTCSR = (1<<WDIE) | (1<<WDE) |
Note that the interrupt, like all interrupts cannot
(0<<WDP3) | (1<<WDP2) | (1<<WDP1) |
make use of the “delay()” function. It is also poor
(0<<WDP0);
practice to call functions such as “Serial.println()”
in the interrupt as any error in the function may
sei();
cause the microcontroller to hang in the interrupt
}
preventing the watchdog from restarting.
# 2
# 11 June 2011
/*
Watchdog Timer Basic Example
10 June 2011
Nicolas Larsen
*/
#include <avr/wdt.h>
int loop_count = 0;
void setup()
{
Serial.begin(9600);
Serial.println("Starting up...");
pinMode(13,OUTPUT);
digitalWrite(13,HIGH);
delay (500);
watchdogSetup();
}
void watchdogSetup(void)
{
cli(); # # // disable all interrupts
wdt_reset();# // reset the WDT timer
/*
WDTCSR configuration:
WDIE = 1: Interrupt Enable
WDE = 1 :Reset Enable
WDP3 = 0 :For 2000ms Time-out
WDP2 = 1 :For 2000ms Time-out
WDP1 = 1 :For 2000ms Time-out
WDP0 = 1 :For 2000ms Time-out
*/
// Enter Watchdog Configuration mode:
WDTCSR |= (1<<WDCE) | (1<<WDE);
// Set Watchdog settings:
WDTCSR = (1<<WDIE) | (1<<WDE) | (0<<WDP3) | (1<<WDP2) | (1<<WDP1) | (1<<WDP0);
sei();
}
void loop()
{
for (int i = 0; i <= loop_count;i++){
digitalWrite(13,HIGH);
delay(100);
digitalWrite(13,LOW);
delay(100);
}
loop_count++;
wdt_reset();
Serial.print(loop_count);
Serial.print(". Watchdog fed in approx. ");
Serial.print(loop_count*200);
Serial.println(" milliseconds.");
}
# 3