Monday, June 6, 2011

Stupid Arduino 2560 Board

The Arduino mega2560 board is cool.  It has several rs232 ports and a ton of digital io ports to play with.  It has enough ram and rom to make a really nice little computer for coordinating other devices around the house and a really small footprint.  The problem is the boot loader is brand new and suffers from a couple of pretty severe bugs.  I left town for a few days and the device died.  No, I couldn't use the watchdog timer; a bug in the boot loader stopped me.  Seems that once you use the watchdog timer, you can't boot back up.  Sad.  I spent last night working up a timer interrupt to do basically the same thing by timing out and then checking a flag I keep resetting in the main loop.

Actually, this is a pretty elegant solution since I can decide within the timer interrupt service routine if I really want to reboot or not and set flags and such to act on when it comes back on line.  However, it is unfortunate that the darn boot loader hasn't been fixed yet.
Sketch to illustrate the Timer3 watch dog trick

#include <TimerThree.h>
// pick this library up at http://www.arduino.cc/playground/Code/Timer1
// scroll down the page to the Timer3 entry.

unsigned long resetTimer = 0;
unsigned long timerRate = 2000000;  // this is the MICRO seconds to wait between interrupts
int resetWait = 10000;                       // this variable is in MILLI seconds for how long to wait
                                                         // before resetting

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

void resetMe(){                                 // There are certain compiler items that this little trick
  resetFunc();                                     // can over come.  Like putting this in a callback.
}

void checkActive(){
  // this routine gets called every timerRate (see above)
  // and here I check resetWait to see if the device has been
  // hung up for resetWait number of milliseconds
  if(millis() - resetTimer > resetWait){
    Serial.println("Fake Watchdog Timer Reset..........");
    resetMe();
  }
//  Serial.print("Timer3 at "); // uncomment these two lines to watch what's
//  Serial.println(millis());   // going on
}

void setup()
{
  int errorCount = 0;
  Serial.begin(57600);
  Serial.println("Initializing..");
}

boolean firsttime = true;

void loop(){
  if(firsttime == true){
    Serial.print("First time through loop, set up timer");
    firsttime = false;
    resetTimer = millis();
    // set timer3 to expire in 2 seconds.  So, every 2 seconds the checkActive routine
    // will get called and it will check the resetTimer variable to see how long in
    // milliseconds it has been since the variable was last updated.
    Timer3.initialize(timerRate);  // This sets timer3 to expire in 2 seconds
    Timer3.attachInterrupt(checkActive);
    // Note that this could have been in the setup() routine above, but
    // I put it here because sometimes I have a LOT of stuff to do during
    // the setup() routine.
  }
  // to test this, comment out the line below and the board should reboot.
  resetTimer = millis(); // This keeps resetting the timer
}


Update 10/29/2011:  I found a way to use the watchdog timer and documented it here.  The solution uses the watchdog interrupt as a timer interrupt and works nicely.  A little bit more code, but it is actually pretty cool.

7 comments:

  1. Hi i have the same problem with Watchdog and Mega 2560 Board. How you have solved the Watchdog problem i'm not so expert on arduino so if you have some code to share i will thanks in advance.
    Dimitri

    ReplyDelete
  2. Sure Dimitri, be glad to share this. I edited the post above so it would be easier to read and other people that stumble across this can find the code more easily.

    Remember, this is only an example and there are probably a thousand other ways to do this, so modify it any way you need to to make it work for your code

    ReplyDelete
  3. Hi Dave
    Thanks very much, sorry for my late relpy i will test it!!
    Sincerely

    ReplyDelete
  4. Thanks for the advice.
    I think it's better to add to the "watchdogCheckActive":
    if( millis() < watchdogResetTimer )
    {
    watchdogResetTimer = millis();
    }

    Simply because "millis()" will overflow after approximately 50 days. http://www.arduino.cc/en/Reference/Millis

    ReplyDelete
  5. Good point rill, I don't bother because I reset the board every day at midnight. I want to clear out the trash left over by the huge number of libraries I have included. Since the arduino can reboot and get back on line in a few seconds, it works well for me. If I wasn't for this, your suggestion would save me a bunch of trouble.

    ReplyDelete
  6. This doesn't work because it requires the board to be running properly for it to work. Which means, this is only evaluated when its least likelt to ever function as a watchdog.

    ReplyDelete
  7. Yes it does. Like all software watchdogs, it depends on the chip itself working and the problem being in software (not hardware). This uses a timer interrupt that runs independently of the code to 'break in' at intervals to tell if the software is screwing up.

    If the hardware is broken, there's simply nothing that can be done. This code over comes things like ethernet failures and over running buffers. I had this code in place for several months and it did the job.

    ReplyDelete