Tutorial: Basic Watchdog Timer Setup

For those of you looking for a basic understanding of the watchdog timer I have written a simple guide on how to go about setting one up…

let me know if there are any errors/typos or improvements to be made.

enjoy

Watchdog20110611.pdf (145 KB)

The example code included on the next page is quite stable and as such wont need the watchdog for about a month or more (the time it takes for “millis()” to overflow).

The watchdog will never fire in the example code. The millis overflow is irrelevant.

ISR(WDT_vect) { Serial.println("Watchdog Interrupt - Restarting"); // you can include any code here. With the reset disabled you could perform an action here every time // the watchdog times out... }

The watchdog not only provides a recovery path from failed software it also provides a recovery path from failed hardware. It is always a bad idea to call blocking functions like Serial.println in the context of an interrupt service routine. It is an especially bad idea to call a blocking function in the watchdog interrupt service routine. If the USART has stopped working correctly, the call to Serial.println may never return; the processor may never reset.

I think your article is well written. Thank you.

Thanks very much for your feedback!

The serial.println was there merely for debugging purposes but you are quite correct - I should have pointed that out or removed it.

[quote author=Coding Badly link=topic=63651.msg462836#msg462836 date=1307734993]

The watchdog will never fire in the example code. The millis overflow is irrelevant.

[/quote]

I obviously stand to be corrected here but does the millis overflow not cause the arduino to freeze? I cant say ive left any arduino on for more than 3 days, I was led to believe it encountered an error after 49 odd not days?

Nope, it wont fire unless you remove the wtd_reset(), the code was really more of a blank template than a functional example.... I guess I could create a series of growing loops that would eventually cause a time-out. At the time of writing I just thought it simplest to leave things relatively blank for people to fill in the dots

I will correct the PDF when I get back to my desktop in the morning.

za_nic: I obviously stand to be corrected here but does the millis overflow not cause the arduino to freeze?

Nope.

I cant say ive left any arduino on for more than 3 days, I was led to believe it encountered an error after 49 odd not days?

Nope. millis overflows. That's it. Any problems are solely the result of a coding mistake in the user's Sketch.

I guess I could create a series of growing loops that would eventually cause a time-out.

Sounds like a good example to me.

The millis() overflow can be neatly handled like this:

// static variable
unsigned long lastFiredTime;

...

// in loop or some such place
unsigned long now = millis ();
unsigned long interval = now - lastFiredTime;
lastFiredTime = now;

Because of the way unsigned integers overflow, the variable "interval" will be correct, regardless of whether millis() has overflowed or not. That is, unless the interval itself exceeds 49.7 days (because that is all that will fit in it).

Certainly nothing freezes if it overflows, it is just an integer arithmetic overflow. They happen all the time.

Thanks for the corrections - didn't think I would be the one learning from this XD

updated copy with a new example now online.

Hi,

just wondering whether I could use this on my Arduino Mega 1280 board? Dont know what kinda bootloader it has. Also, did I understand it right that this is a pure software Watchdog without external ICs like a 555?

Thx Thorsten

did I understand it right that this is a pure software Watchdog without external ICs like a 555?

You understood correctly that it doesn't use external hardware, but it is not a software solution - the hardware for the timer is internal to the processor.

Thx. But can I use it with my Mega board or is that not compatible?

currymuetze: Thx. But can I use it with my Mega board or is that not compatible?

Run the example code and then you can tell us:-) the mega 1280 probably has a slightly older boot loader than the UNO so won't be able to say for sure but the physical device itself is capable of operating a watchdog timer.

Jimxbob correctly pointed out to me a few oversights of mine so FYI:

I may be wrong here as this is something hew to me, but one thing you might want to consider in your guide is to alter the example code fractionally to move the watchdogSetup(); line to the top of the setup() function.

I think you're actually relying on code in the bootloader to disable the watchdog before you enable it here.

I was having issues because I was not using a bootloader. Once the WDT fires, it's left enabled at restart, but the duration is set to the minimum time (I think - read it somewhere & it seems to fit my experience). It then fires again within the delay(500), and your locked in to an infinite loop.

With the watchdogSetup() at the top of the setup() the code will work fine with or without a bootloader (though it'll still fail for a bootloader that doesn't handle the WDT properly).

Yep, thats all correct - I was relying in my code on the boot loader to reset back to all the defaults.

Currently the mega2560 will lock up and need to be powered down if you use the watchdog timer. The bootloader on it has the same problem the older bootloaders had. You might mention that in the file just to avoid the mails and questions that may be coming your way.

za_nic, thanks for the description. As the post above may have indicated, I've been avoiding the wdt on the mega 2560 board because the bootloader doesn't initialize it properly. The board would hang up in a loop, requiring a power cycle to recover. That meant that I had to fake a watchdog using timer 3 on the board. That was not a very satisfactory solution especially since the watchdog should be able to do this job.

Well, your description got me to thinking and I came up with a solution that uses the watchdog AND allows me to have a much longer watchdog timer. This is exactly the solution I needed to free up timer three and put the job back on the watchdog like it should be. I still can't use WDE, but that problem is easy to work around. Here's the code if you want to include it at some point or just to expand your example.

Nice job.

include

unsigned long resetTime = 0;

define TIMEOUTPERIOD 10000 // You can make this time as long as you want,

// it's not limited to 8 seconds like the normal // watchdog

define doggieTickle() resetTime = millis(); // This macro will reset the timer

void(* resetFunc) (void) = 0; //declare reset function @ address 0

void watchdogSetup() { cli(); // disable all interrupts wdt_reset(); // reset the WDT timer MCUSR &= ~(1<

ISR(WDT_vect) // Watchdog timer interrupt. { if(millis() - resetTime > TIMEOUTPERIOD){ Serial.println("This is where it would have rebooted"); // just here for testing doggieTickle(); // take these lines out // resetFunc(); // This will call location zero and cause a reboot. } else // these lines should Serial.println("Howdy"); // be removed also }

void setup(){ watchdogSetup(); Serial.begin(57600); Serial.println("Hello, in setup"); }

int firstTime = true;

void loop() { if (firstTime){ firstTime = false; Serial.println("In loop waiting for Watchdog"); } if(millis() - resetTime > 2000){ //doggieTickle(); // if you uncomment this line, it will keep resetting the timer. } }

Thanks very much for the feedback draythomp- Ive only got UNOs sitting on my desktop at home which is why I haven't encountered any of the problems you guys are bringing up. I may update the tutorial at some stage or another but for now the forum thread is short enough for someone to be able to skim and make changes at a glance - great timer work-around! :)

I presume you only added the Serial in the WDT interrupt to debug and get some sort of feedback - Ive never encountered any problems but just be aware if serial happened to be the function that caused the board to malfunction and prompt a WDT interrupt, It may cause the interrupt to hang if you bring up serial in the interrupt and you will never get around to resetting the board.

Thanks again for the feedback! Such contributions are what make forums such great mediums :)

Hi za_nic,

A very good writeup about the watchdog timer... thank you

How can I use a watchdog timer greater than 8000ms ??

Any examples codes for this ?

Thanks

Hi Stanley,

I've never tried but I presume it would be fairly easy to just count the number of reset interrupts with the WDE set to 0 (reset off), there may be a conflict if your board freezes and cant alter the count value but its a theoretical guess. I don't have access to a board right now so I cant test it but I presume the code logic would work somewhat like this:

Run the example code. Change the WDT setup so the that board will not restart (WDE = 0; //reset off) Now the board will no longer reset and the WDT will keep calling an interrupt at whatever period of time it is set up Insert a variable (say wdt_counter = 0) that will increment up when the WDT interrupt is called. At however many loops or increments you decide (minus one) you will need to arm the WDT to reset (WDE = 1, reset on) Now if the interrupt is called the board will reset. If the WDT is reset or fed you will need to reset the counter and WDT back to zeros to reset the whole loop cycle.

Out of interest what need do you have for doing this?

Hope this helps! Its morning where I am but if your still having problems in 10+ hours let me know and Ill try write some proper example code.

Nic

Hi Nic,

I'm planning to use the watchdog timer for a COSM feed updates for my sensors. At times, the COSM will not return a value and timeout... and the timeout is more than 8 secs, so the WDT will kick in and reset the board first before the timeout from the COSM server..

So I kinda need a longer timeout value more than 8 secs

Is this a good application/example to use the WDT ??

My codes below for the main loop...

  ... put sensor values into arrays feed and call the comsclient.put function...

  cosmReturn = cosmclient.put(feed,cosmKey);   // Send feed to cosm
  Serial.print("Cosmclient returned value : "); // Get return code, similar to HTTP code
  Serial.println(cosmReturn);

  wdt_reset();  // Reset WDT timer 

  delay(2000); // Put a delay before the next updates to Cosm

Apologies for late reply!

As I mentioned in my previous post, it would be possible to extend the 8s timer to something longer by applying the WDE to 1 on the second iteration of the WDT interrupt but there is still a small risk that the board could potentially freeze or encounter an error when reconfiguring the WDT fuses. I believe the likely hood to be quite low but it still exists and if encountered would cause your board to hang indefinitely or until a hardware reset is performed.

I've modified the example code to include this step. I feel I should stress once again that this does make the WDT quite vulnerable to flaws. If your looking for a more serious solution, look at implementing a second arduino or ATtiny chipset (you'll need a super basic one...) to monitor and hard reset the main board in the event of a fault or error.

*note: I don't have a board at hand to test this code on so your going to have to guinea pig it for me

#include  

int loop_count = 0;
int wdt_counter = 0;

void setup() {

  Serial.begin(9600); 
  Serial.println("Starting up..."); 
  pinMode(13,OUTPUT); 
  digitalWrite(13,HIGH);
  delay (500);
  watchdogStart(); 
}

void watchdogStart(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<

@za_nic, really informative. I ran the test code, and it worked perfect, right out of the box. Thanks, Jack

Great tutorial, I was wondering for more power saving I read that I can upload the 8Mhz bootloader to the ATMEGA328P instead of the default 16Mhz setting. Makes sense. But I read that this will mess with timers. Would this change make a difference? Save Power?

-Nick