Hi,
seems im having some trouble with using a watch dog timer on my 2560.
When i test the sketch below on a Uno it works as expected > the sketch is loaded > WDT is set to fire an interrupt > the interrupt disables WDT, writes some values to EEPROM (i read it is bad practice to read/write to EEPROM both in main application and within interrupts but im not sure how else to do this...) then enables the watchdog system reset while im assuming the timeout flag is still set so the arduino immediately resets.
on a Uno you can see that the "cycles" variable starts from 0 and counts up, after a WD reset it starts from 0 and the process is repeated indefinitely. however on a Mega, after a reset the sketch doesnt start. im assuming the WDT is still set and the Mega's bootloader is not disabling or resetting it so it immediately bites before any instructions are processed.
my question is: am i doing this correctly and just hitting a stale mate due to hardware/software limitations (eg. wrong bootloader). or is there another more portable way to accomplish this behavior that i am not aware of?
i have tried using the line:
asm volatile (" jmp 0");
at the end of the ISR, though this seems to start the sketch over, it is by far not a true system reset.
#include <avr/wdt.h>
#include <EEPROMex.h>
int RED = 13; // the pin that the LED is attached to
int GREEN = 6; // the pin that the LED is attached to
int BLUE = 10; // the pin that the LED is attached to
unsigned long cycles = 0; //number of iteration cycles from start
const int maxResets = 5; //number of times the mcu can reset due to fault before led illuminates
const int error_code_address = 0;
byte error_code = EEPROM.read(error_code_address); //if WDT resets this will be = 1, if its a clean user reset the val = 0
const int reset_cnts_address = 1;
byte reset_cnts = EEPROM.read(reset_cnts_address); //number of contiguous WDT resets sinces last clean start
const int ctr_address = 2;
unsigned long nonvol_counter = 0; //nonvolatile counter, after WDT resets this counter will load its last value, or 0 if clean start
ISR (WDT_vect)
{
wdt_disable(); //disable the watchdog
EEPROM.write(error_code_address, 1); //there was an error and WDT needs to reset the system. so write 1 to EEPROM so arduino knows after it resets
EEPROM.updateLong(ctr_address, nonvol_counter); //since there was an error we dont want to loose this value so write it to EEPROM
reset_cnts = constrain(reset_cnts + 1, 0, 255 ); //one byte in EEPROM stores this var, but we also dont want it do rollover.
EEPROM.write(reset_cnts_address, reset_cnts); //wire the incrimented reset counts to EEPROM so arduino knows after it resets
digitalWrite(BLUE, 0);
digitalWrite(RED, 1);
//WDTCSR = bit (WDE); //"Watchdog System Reset Enable" THIS WORKS ON UNO BUT NOT ON MEGA
asm volatile (" jmp 0"); //THIS WORKS ON BOTH BUT IS NOT A FULL RESET
} // end
void setup()
{
pinMode(RED, OUTPUT);
pinMode(BLUE, OUTPUT);
pinMode(GREEN, OUTPUT);
digitalWrite(RED, 0);
digitalWrite(BLUE, 1);
digitalWrite(GREEN, 0);
// clear various "reset" flags
MCUSR = 0;
// allow changes, disable reset
WDTCSR = bit (WDCE) | bit (WDE);
// set interrupt mode and an interval
WDTCSR = bit (WDIE) | bit (WDP3) | bit (WDP0); // set WDIE, and 8 seconds delay
if (error_code != 0){ //if there was an error from last run
EEPROM.write(error_code_address, 0); //reset the error code and clean things up
nonvol_counter = EEPROM.readLong(ctr_address); //reload the counter since the arduino crashed
if (reset_cnts >= maxResets) { //check to see how many times in a row the arduino has crashed
digitalWrite(GREEN, 1); //if the arduino crash count exceeds the max allowed lets indicate this to user
}
} else { //clean system start, no errors from last run
nonvol_counter = 0; //start counter from 0/clean
EEPROM.write(reset_cnts_address, 0); //since this was clean, we reset the error counter
reset_cnts = 0; //and update the variable in SRAM
}
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
Serial.println("\n\n\nSETUP DONE!\n\n\n");
delay(500);
wdt_reset();
}
void loop()
{
nonvol_counter++;
Serial.print( "Sketch Cycles:" );
Serial.print( cycles );
Serial.print( " nonvolatile Counter:" );
Serial.print( nonvol_counter );
Serial.println();
delay(1);
//wdt_reset(); // pat the dog //for testing this is disabled
cycles++;
}
Please help ![]()