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

Watchdog timer is clocked with separate 128kHz oscillator. It is a low power oscillator which isn’t accurate enough for precise timing operations. Upon special MCU fuse settings this clock also can serve as system clock, then watchdog becomes synchronous with main clock. But this is a special case we won’t consider. To be more flexible, 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

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

And there is a special case where watchdog can generate both: interrupt and system reset. By using this feature you may have ability to preserve valuable parameters before 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 is 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. In order 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 own clock source while debugged program runs much slower than normally. You don’t want your program to be reset during any debugging step.

Read

Bookmark the permalink.

4 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.

Add Comment Register



Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>