Watchdog Timers (WDT)

make your installations robust

[written by Tom, October 2015]

*Tested with an Industruino 1286 topboard 

Introduction

A watchdog timer is a timer that, if not interacted with for a certain period of time, will reset the microcontroller. In case the microcontroller gets stuck somewhere in its code, the watchdog timer will be triggered and the microcontroller will reset, and restart normal operation. This is the most basic implementation of a watchdog; it is also possible to attach an interrupt routine to the watchdog timer so a specific piece of code will be executed when the watchdog timer is triggered but we won’t cover that here.

There are 2 different ways to implement a watchdog timer: hardware and software.

HARDWARE watchdog timer

The AVR family of microcontrollers (including the Industruino topboards 32u4 and 1286) have a hardware watchdog timer built in that can be set to periods of 15 milliseconds up to 8 seconds. Be careful when setting the watchdog to very short periods: that might trigger the watchdog reset while you are trying to upload a new sketch. In this example we will only use periods of 1, 2, 4, 8 seconds.

Include the watchdog timer library avr/wdt.h    

In setup(), enable the watchdog timer with the desired period:

                        wdt_enable(WDTO_8S); // options: WDTO_1S, WDTO_2S, WDTO_4S, WDTO_8S
                      

In loop(), reset the watchdog timer before it reaches the set period

                        wdt_reset(); // confirm to watchdog timer that all is well
                      

This example sketch sets the watchdog timer to 4 seconds, and then in each loop increases the amount of time in a delay(), eventually triggering the watchdog timer and resetting the Industruino. Note that the watchdog timer is not exact, as described elsewhere. We usually got up to 10­20% longer than the set period before the watchdog timer was triggered.

Also see AVR documentation at

http://www.nongnu.org/avr­libc/user­manual/group__avr__watchdog.html

                      
// INDUSTRUINO basic example for hardware watchdog // with topboard 1286

#include <avr>#include <uc1701.h> </uc1701.h></avr><avr><uc1701.h>static UC1701 lcd;</uc1701.h></avr>int delay_time = 0; void setup() {

lcd.begin(); //sets the resolution of the LCD screen lcd.clear();
lcd.setCursor(2,2);
lcd.print("watchdog timer RESET");

pinMode(26, OUTPUT); for (int i=0;i<5;i++) {

digitalWrite(26, LOW); delay(500); digitalWrite(26, HIGH); delay(500);

} analogWrite(26,200); lcd.clear();

wdt_enable(WDTO_4S); // options: WDTO_1S, WDTO_2S, WDTO_4S, WDTO_8S }

void loop() {
wdt_reset(); // confirm to watchdog timer that all is well lcd.setCursor(2,2);
lcd.print("delay_time: ");
lcd.print(delay_time);
delay(delay_time);
delay_time += 100;

}

SOFTWARE watchdog timer

If you need a watchdog timer interval above 8 seconds, you cannot use the above hardware solution. But it’s rather easy to write a software watchdog timer based on the timers available on the microcontroller. To make this easy, you will need to install the TimerOne library from here http://code.google.com/p/arduino­timerone/downloads/list

We configure this timer to trigger a routine at 1 second intervals, and the routine checks if a certain period (variable timeout) has passed since the last reset. The reset time is kept in a variable lastUpdate, which we update regularly with m illis(). So the variable timeout has to be set in milliseconds. The structure of the code is very similar to the hardware timer, but a little longer, and more flexible.

Below example resets the microcontroller when the watchdog is not updated for 20 seconds. The code is based on the example at http://blog.frogslayer.com/creating­an­arduino­watchdog­timer/

and as mentioned there, this is not the equivalent of a hard reset so pins might keep their previous state.

// INDUSTRUINO basic example for software watchdog // with topboard 1286 
#include  
#include  
static UC1701 lcd;int delay_time = 0; long timeout = 20000; 
long lastUpdate; 

void setup() { 
lcd.begin(); //sets the resolution of the LCD screen lcd.clear();
lcd.setCursor(2,2);
lcd.print("watchdog timer RESET"); 
                        pinMode(26, OUTPUT); 
for (int i=0;i<5;i++) { 
                        digitalWrite(26, LOW); 
delay(500); 
digitalWrite(26, HIGH); 
delay(500); 
                        } 
analogWrite(26,200); 
lcd.clear(); 
                        lastUpdate = millis();

Timer1.initialize(1000000); 
Timer1.attachInterrupt(longWDT); //code to execute 
                        } 

void loop() { 
lcd.setCursor(2,2); 
lcd.print("delay_time: "); 
lcd.print(delay_time); 
delay(delay_time); 
delay_time += 1000; 
lastUpdate = millis(); 
                        }
void (*resetFunc)(void) = 0; 
void longWDT(void) 
                        //1 second pulses 
                        {
if((millis()­lastUpdate) > timeout) { 
                        Timer1.detachInterrupt(); 
                        resetFunc(); } 
                        }