I'm writing a program for an ATtiny85. I want to use the watchdog to wake up from power down in certain intervals. It all works fine as long as the intervals for a watch dog event don't change within the program (i.e. I don't change bits WDP0-3 after they're set once).
As soon as I change the timeout of the watchdog, it does an unwanted reset. I don't have the WDTON fusebit enabled, so the whactdog is not always on but rather has to be enabled by software. (In fact the fuse bits are: Low=0xe2, High=0xdf and Extended= 0xff make the controller run at 8 Mhz from the internal oscillator).
Here is a snipplet of my code:
#include <avr/wdt.h>
#include <avr/power.h>
#include <avr/sleep.h>
#include <avr/interrupt.h>
void Config_wdt(uint8_t timeout) {
cli();
wdt_reset(); // reset watchdog timer
MCUSR &= ~(1<<WDRF); // clear reset flag
WDTCR = (1<<WDE) | (1<<WDCE); // enable watchdog
WDTCR = (1<<WDIE) | timeout; // watchdog interrupt instead of reset
//+reset, timeout can be 15,30,60,120,250,500ms or 1,2,4,8s
sei();
}
EMPTY_INTERRUPT(WDT_vect)
void Sleep_now(uint8_t i, uint8_t timeout) {
Config_wdt(timeout);
for(i=i; i>0; --i) {
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // set type of sleepmode
power_all_disable(); // disable unneeded loads
wdt_reset(); // timer should start at zero
sleep_enable(); // approach sleep mode
sleep_mode(); // enter sleep mode (confirm)
sleep_disable(); // entrance point when woken up
// Another Config_wdt(timeout); here or re-enabling WDIE doesn't help either
power_all_enable(); // re-enable the loads
}
}
int main() {
Config_wdt(WDTO_500MS);
Do_some_stuff();
Sleep_now(5, WDTO_500MS); // WORKS AS EXPECTED, SLEEPS 5 TIMES 500ms = 2.5s
while(1) {
Make_other_things();
Sleep_now(3, WDTO_30MS); // DOES AN UNWANTED RESET, ...
\\+I.E. STARTS FROM THE BEGINNING BEFORE "Do_some_sfuff()"...
\\+IF I REPLACE "WDTO_30MS" HERE by "WDTO_500MS" FROM ABOVE...
\\+THE CODE WORKS FINE.
}
}
The datasheet has this to say:
If WDE is set, WDIE is automatically cleared by hardware when a time-out occurs. This is useful for keeping the
Watchdog Reset security while using the interrupt. After the WDIE bit is cleared, the next time-out will generate a
reset. To avoid the Watchdog Reset, WDIE must be set after each interrupt.
But even if I set the WDIE bit immediately after waking up from sleep mode, it still does the unwanted reset.
So how do I change the watchdog timeout in my code, without the unwanted reset?
Best Answer
I am unable to reproduce this behavior. I am using an ATTINY85 with the fuse values given.
To test, I created Do_some_stuff() that blinks a white LED for 1 second, and Make_other_things() that blinks a red LED for 1 second.
On power-up...
Here is a scope view after powerup...
Yellow trace=White LED
Purple trace=Red LED
Code I am using is here...
...which I think is identical you yours except for the extra functions.
Can you try this code and see if you get unexpected results? If so, then can you think of any differences introduced by your code that could explain the different behavior?