long watchdogAuthor: Dave Date: 05.21.15 - 5:33am the Arduino comes with a watchdog that can reset it if the chip is hung. The maximum timeout built in is an eight second delay. for some uses this is not long enough. One such configuration that requires a longer timeout is the use of the Adafruit cc3000 wi-fi board. This board is fairly reliable but is also prone to occasional hangs. I have been using one for about eight months now as part of my iot Web-enabled humidor project. I would probably have to reset it once a week or so when I saw it hung. I tested using the eight second delay watchdog, and I could tell that it was not a long enough delay but more or less it was working for me because even if it resets my project will automatically upload on reboot. For one of my users however the delay simply was not enough and he had to find code for the long watchdog reset. Special thanks goes out to Philip Allagas for researching this and finding the solution. the following code is from Dave Evans and is worth mirroring below. Another option would be to use an external hardware watchdog. The premade circuit I purchased for bypassing the mc60 soft start should have worked for this scenario, but I didn't want to require another component for my build. thanks again to Dave and Philip! #include <avr/wdt.h> // for watchdog timer volatile int counter; // Count number of times ISR is called. volatile int countmax = 3; // Arbitrarily selected 3 for this example. // Timer expires after about 24 secs if // 8 sec interval is selected below. void setup() { // Initialize Serial.begin(115200); } void loop() { Serial.println("**** starting loop ****"); // should see this approx every xx secs watchdogEnable(); // set up watchdog timer in interrupt-only mode while (true); // Whoops...in an infinite loop! For testing only. // For production, this would be useful // code that normally takes less than xx sec to process // but occasionally hangs. wdt_disable(); } void watchdogEnable() { counter=0; cli(); // disable interrupts MCUSR = 0; // reset status register flags // Put timer in interrupt-only mode: WDTCSR |= 0b00011000; // Set WDCE (5th from left) and WDE (4th from left) to enter config mode, // using bitwise OR assignment (leaves other bits unchanged). WDTCSR = 0b01000000 | 0b100001; // set WDIE (interrupt enable...7th from left, on left side of bar) // clr WDE (reset enable...4th from left) // and set delay interval (right side of bar) to 8 seconds, // using bitwise OR operator. sei(); // re-enable interrupts //wdt_reset(); // this is not needed...timer starts without it // delay interval patterns: // 16 ms: 0b000000 // 500 ms: 0b000101 // 1 second: 0b000110 // 2 seconds: 0b000111 // 4 seconds: 0b100000 // 8 seconds: 0b100001 } ISR(WDT_vect) // watchdog timer interrupt service routine { counter+=1; if (counter < countmax) { wdt_reset(); // start timer again (still in interrupt-only mode) } else // then change timer to reset-only mode with short (16 ms) fuse { MCUSR = 0; // reset flags // Put timer in reset-only mode: WDTCSR |= 0b00011000; // Enter config mode. WDTCSR = 0b00001000 | 0b000000; // clr WDIE (interrupt enable...7th from left) // set WDE (reset enable...4th from left), and set delay interval // reset system in 16 ms... // unless wdt_disable() in loop() is reached first //wdt_reset(); // not needed } } Comments: (2)On 01.28.19 - 8:53am Dave wrote:
On 09.11.20 - 3:41am akhil wrote:
|
About Me More Blogs Main Site |
||