Using watchdog timer in your projects

All AVR microcontrollers have internal watchdog timer that can be successfully used in your projects. Atmega328 and other modern AVR microcontrollers have so-called Enhanced Watchdog Timer (WDT). It has few very useful features including: separate 128kHz clock source, ability to reset microcontroller and generate interrupt.

From hardware perspective watchdog timer is nothing more than simple counter that gives a pulse when it counts up. This pulse can be used either to generate interrupt or simply reset MCU (or do both). Watchdog timer can be reset to zero at any time with simple WDR command, and this is where fun begins. If you enabled watchdog timer, you have to take care and reset it before it fills up and resets MCU. Otherwise if your program hangs or sticks in some infinite loop without reset watchdog simply counts up and resets system. In this case we get pretty good program guardian who keeps an eye on program flow. In other special cases watchdog can serve as simple software-based MCU reset source.

Watchdog clock and prescaller

The watchdog timer is clocked with a separate 128kHz oscillator. It is a low power oscillator which isn’t accurate enough for precise timing operations. Upon individual MCU fuse settings this clock also can serve as the system clock, then watchdog becomes synchronous with the main clock. But this is a particular case we won’t consider. For better flexibility, the watchdog timer has a clock prescaller system, similar to other timers. Depending on WDP[3..0] settings in WDTCSR register watchdog can be set to timeout from 16ms up to 8s.

Watchdog Interrupt mode

The watchdog timer interrupt is a valuable source of an interrupt as it depends on a separate clock source. So it can be used to wake up MCU from sleep. You can construct a very efficient battery driven system which, for instance, needs to do some task every 8s and then get back to sleep. Or simply WDT interrupts can stop routines that take too long to execute. I bet, you can see more of uses here…

And there is a particular case where watchdog can generate both: interrupt and system reset. By using this feature, you may have the ability to preserve valuable parameters before the reset.

Programming AVR watchdog timer

There are two ways to set up watchdog timer: by programming WDTON fuse when flashing MCU and another is during program flow. If WDTON fuse is programmed, it cannot be disabled in software, and it only works in system reset mode (no interrupt available). This might be used to ensure system security. The only thing we can change here is a prescaller.

Software watchdog programming gives more flexibility and functionality. As we mentioned, you can use reset and interrupt modes. To start watchdog timer or change its prescaller, some programming sequence is needed. This helps to ensure secure program flow. These are:

  1. Disable interrupts;
  2. Reset watchdog timer with WDR command;
  3. Write logic one to WDCE and WDE bits of WDTCSR simultaneously;
  4. Then withing four cycles write logic one to enable (or zero to disable) watch dog timer, or change prescaller.

There are couple code examples in AVR datasheet how you can do straight forward. But there is better alternative in AVRGCC avrlibc. There is a special library wdt.h prepared to manipulate watchdog timer. In this case we can call any of three functions that will take care of proper execution sequence:

#define wdt_reset(); //resets watchdog timer

#define wdt_disable(); //disables watchdog timer

#define wdt_enable(timeout); //sets a watchdog prescaller

Depending on selected microcontroller prescallers may be set to one of following values:

#define WDTO_15MS 0

#define WDTO_30MS 1

#define WDTO_60MS 2

#define WDTO_120MS 3

#define WDTO_250MS 4

#define WDTO_500MS 5

#define WDTO_1S 6

#define WDTO_2S 7

#define WDTO_4S 8

#define WDTO_8S 9

Lets write a simple program that will use watchdog timer in interrupt and reset modes simultaneously. To do this we simply run program without resetting watchdog timer. In main routine we will blink LED with at approximately 0.5Hz and when watchdog interrupt occurs it will give a burst of five 0.1Hz signals. After reset LED will light for a half of second. These will give us a clue of ongoing processes. Keep in mind that after watchdog interrupt counter has to count up once more for a reset occur.

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <util/delay.h>
//Prepare LED pin
void PortInit(void)
{
    //Initlally LED ON
    PORTD|=(1<<PD2);
    //PD2 as output
    DDRD|=(1<<PD2);
}
//initialize watchdog
void WDT_Init(void)
{
//disable interrupts
cli();
//reset watchdog
wdt_reset();
//set up WDT interrupt
WDTCSR = (1<<WDCE)|(1<<WDE);
//Start watchdog timer with 4s prescaller
WDTCSR = (1<<WDIE)|(1<<WDE)|(1<<WDP3);
//Enable global interrupts
sei();
}
//Watchdog timeout ISR
ISR(WDT_vect)
{
    //Burst of fice 0.1Hz pulses
    for (uint8_t i=0;i<4;i++)
    {
        //LED ON
        PORTD|=(1<<PD2);
        //~0.1s delay
        _delay_ms(20);
        //LED OFF
        PORTD&=~(1<<PD2);
        _delay_ms(80);
    }
}
int main (void)
{
    //Initialize port
    PortInit();
    //initialize watchdog
    WDT_Init();
    //delay to detet reset
    _delay_ms(500);
    while(1)
    {
        //LED ON
    PORTD|=(1<<PD2);
    _delay_ms(20);
        //LED OFF
    PORTD&=~(1<<PD2);
        //~0.5s delay
    _delay_ms(500);
    }
}

You can test this program with standard Arduino Duemilanove or Uno board by plugging LED between Digital 2 and GND pins:

Or you can use any AVR development board with modern AVR.

As you can see we enabled watchdog reset and interrupt modes almost without wdt.h library usage, because it doesn’t support interrupt mode programming yet. So we had to initialize by ourselves while following the rules. There is another watchdog library version developed by Curt Van Maanen. It can be downloaded here in case you decide to give a try.

And finally, if you decide to debug your programs with hardware debugger, be sure to disable watchdog timer as it runs on its clock source while the debugged program runs much slower than normal. You don’t want your application to be reset during any debugging step.

Bookmark the permalink.

5 Comments

  1. Pingback: Electronics-Lab.com Blog » Blog Archive » Using watchdog timer in your projects

  2. Thank you for this. I was experiencing a lot of frustration until I saw this post.

  3. Hi,
    I have set the WDT very short time, so when arduino start it will reset agan and could not access it via usb any more…..

    what can i Do?????

    thanks

  4. @wesam

    use the following code

    #include

    void setup(){

    wdt_reset(); // First thing, turn it off
    wdt_disable();
    Serial.begin(57600);
    Serial.println(“Hello, in setup”);
    }

    void loop(){

    }

    have your adunio unpluged and start the upload. just before it finishes compiling plug it in.

    This is how I fixed that watchdog issue.

  5. in program above you have included wdt.h header file but you have written all function defination menually . By the way thanks for your tutorial .Really helpful to me 🙂

Leave a Reply