Pages: [1] 2   Go Down
Author Topic: Tutorial: Basic Watchdog Timer Setup  (Read 12904 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 1
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 (144.91 KB - downloaded 1782 times.)
« Last Edit: June 11, 2011, 02:31:44 am by za_nic » Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 209
Posts: 13027
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Quote
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.
Logged

Offline Offline
Newbie
*
Karma: 1
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.


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


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.



Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 209
Posts: 13027
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Nope.

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

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

Sounds like a good example to me.
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 498
Posts: 19065
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Code:
// 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.
Logged


Offline Offline
Newbie
*
Karma: 1
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

updated copy with a new example now online.
Logged

Offline Offline
God Member
*****
Karma: 6
Posts: 717
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 309
Posts: 26489
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

 
Quote
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.
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Offline Offline
God Member
*****
Karma: 6
Posts: 717
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Offline Offline
Newbie
*
Karma: 1
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Offline Offline
Newbie
*
Karma: 1
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Quote
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.
Logged

New River, Arizona
Offline Offline
God Member
*****
Karma: 19
Posts: 936
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Trying to keep my house under control http://www.desert-home.com/

New River, Arizona
Offline Offline
God Member
*****
Karma: 19
Posts: 936
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.

Quote
#include <avr/wdt.h>

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<<WDRF);  // because the data sheet said to
/*
WDTCSR configuration:
WDIE = 1 :Interrupt Enable
WDE = 1  :Reset Enable - I won't be using this on the 2560
WDP3 = 0 :For 1000ms Time-out
WDP2 = 1 :bit pattern is
WDP1 = 1 :0110  change this for a different
WDP0 = 0 :timeout period.
*/
// Enter Watchdog Configuration mode:
WDTCSR = (1<<WDCE) | (1<<WDE);
// Set Watchdog settings: interrupte enable, 0110 for timer
WDTCSR = (1<<WDIE) | (0<<WDP3) | (1<<WDP2) | (1<<WDP1) | (0<<WDP0);
sei();
Serial.println("finished watchdog setup");  // just here for testing
}


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.
  }
}
Logged

Trying to keep my house under control http://www.desert-home.com/

Offline Offline
Newbie
*
Karma: 1
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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! smiley

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 smiley
Logged

Kuala Lumpur, Malaysia
Offline Offline
Full Member
***
Karma: 4
Posts: 204
Anything is possible
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Logged


Pages: [1] 2   Go Up
Jump to: