I hope somebody can shed some light on this problem. I've researched the internet and forums and noticed that others have experienced similar problems.
This sketch runs fine for a couple of hours...it activates a relay approximately every hour, has a 10 second loop for an LED flash and then enters sleep mode. The watchdog timer is set to 8 seconds and wakes it up from sleep. I don't know why it works for a couple of hours and then gets caught into some sort of loop with the LED flashing rapidly. The requirements for disabling and resetting the watchdog might be the problem but I just don't know where to go next. I have seen a few discussions on memory leakage but not sure what that means or how to check for it. I also wonder if need to add any short delays after resets, etc. Additionally, when I press the reset button it has no effect on restarting the sketch. The sketch is running on a breadboard atMega328p-pu. Any help would be greatly appreciated.
ps. in the preview I noticed the # statements are not shown. They are the following libraries: avr/sleep.h, avr/power.h, avr/wdt.h
// In this sketch, the LED's flash every 10 seconds, then at each approximately 1 hour period, the relay is activated
// for 12 seconds. It uses the WDT at its maximum 8 second delay to wakeup the circuit from low power sleep.
// Source: citizen-sensing.org/2013/07/arduino-watchdog/
// Check this out for good explanation on the Watchdog timer and code.
// http://www.leonardomiliani.com/en/2013/impariamo-ad-usare-il-watchdog-2/
// SEE NOTE at the end on known WDT reset issue
#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/wdt.h>
int j = 1; // Elapsed time multiplication factor
int j2 = 0; // previous j value
float tCumm = 0.0; // Cummulative time
float hSet = 1.0; // Set relay activation once per hour
float hSet2 = 0.0; // Previous hSet value
// Create sleepNow function
void sleepNow() {
wdt_reset();
wdt_disable();
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Selecting the lowest power setting
// Set watchdog parameters
MCUSR &= ~(1<<WDRF); // reset status flag
WDTCSR |= (1<<WDCE) | (1<<WDE); // required to enable configuration changes
WDTCSR = (1<<WDP0) | (1<<WDP3); // set the pre-scalar for 10, ie 8 seconds delay
WDTCSR |= (1<<WDIE); // enable interrupt mode
// Disable the ADC
ADCSRA &= ~(1<<ADEN); // Set bit 7 in ADC register to 1 to disable the ADC
// Ready for sleep
sleep_enable(); // Enable sleep function
sleep_mode(); // Go to sleep. Will wake up upon interrupt via Watchdog timer in this sketch.
// disable sleep after waking up
sleep_disable(); // Disable sleep for now after Watchdog timer interrupt activation
}
void setup() {
pinMode(4, OUTPUT); // set pin 4 as output for LED
pinMode(7, OUTPUT); // set pin 7 as output for relay
}
void loop() {
// 10 second LED flashing + sleep loop
for (int i = 0; i < 2; i++) {
digitalWrite(4, HIGH); // turn the LED on (HIGH is the voltage level)
delay(200); // wait for 0.2 sec
digitalWrite(4, LOW); // turn the LED off by making the voltage LOW
delay(200); // wait for 0.2 second
}
// Add delay for total approx 2 sec
delay(1200);
// Start sleep / Low power / Watchdog interrupt
sleepNow();
// Cummulative time in increments of 10 seconds
tCumm = ((2.0 + 8.0)*j)/3600.;
// Time multiplication factor. Used to increment tCumm. Never resets to zero.
j2 = j;
j = j2 + 1;
// Check to see if tCumm exceeds the user defined period (hSet) before activating relay
if (tCumm > hSet) {
// Activate relay for 12 seconds
digitalWrite(7, HIGH);
delay(12000);
digitalWrite(7,LOW);
// Reset hSet for next relay activation time
hSet2 = hSet;
hSet = hSet2 + 1.0;
}
}
ISR (WDT_vect) {
}
NOTE from an online discussion: The problem is that a RESET does not turn off the watchdog timer once it has been turned on, and neither does the bootloader. So you set things up to have the watchdog cause a reset in 15ms, and the reset occurs. Now the bootloader starts up, and starts its LED-flashing, and OOPS another 15ms has gone by with no one feeding the watchdog, and it resets again. This repeats until a power cycle turns off the watchdog.
(This behavior is explicitly described in the ATmega datasheet...)
wdt_disable();
at the end ofsleepNow
. It doesn't make much sense to disable it right before setting it. I always put a distinct blinking pattern in thesetup
function, so I can detect when the Arduino is reset.