On an ATMega328p, I'm trying to setup a program that counts 1 second intervals via the watchdog timer, even when the chip is in sleep mode. A button interrupt puts the chip into sleep mode. The problem I'm having is that once in sleep mode, it seems that the watchdog vector is never being called. I think I have everything setup like it should be but cannot figure out what's wrong. Any thoughts?
#include <avr/interrupt.h>
#include <avr/power.h>
#include <avr/sleep.h>
#include <avr/wdt.h>
//#include <avr/io.h>
#define SLEEP_ENABLED MCUCR & _BV(SE)
void setup()
{
pinMode(2, INPUT);
digitalWrite(2, HIGH); //enable pullup
Serial.begin(115200);
MCUSR &= ~(1<<WDRF); //Clear WDT Reset Flag
/* In order to change WDE or the prescaler, we need to
* set WDCE (This will allow updates for 4 clock cycles).
*/
WDTCSR |= (1<<WDCE) | (1<<WDE);
/* set new watchdog timeout prescaler value */
WDTCSR = 1<<WDP2 | 1<<WDP1; /* 1.0 seconds */
//WDTCSR = 1<<WDP3 | 1<<WDP0; /* 8.0 seconds */
/* Enable the WD interrupt (note no reset). */
WDTCSR |= _BV(WDIE);
attachInterrupt (0, initSleep, LOW);
}
volatile uint32_t _count = 0;
volatile uint32_t _sleepCount = 0;
ISR(WDT_vect)
{
_count++;
//if(PIND & _BV(PIND2))
if(SLEEP_ENABLED)// && _count >= _sleepCount + 5)
{
wakeSleep();
}
}
volatile uint8_t _oldADC = ADCSRA;
void wakeSleep()
{
attachInterrupt (0, initSleep, LOW);
ADCSRA = _oldADC;
//setClock16();
sleep_disable();
}
inline void _doSleep()
{
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
//Do actual sleep
// turn off brown-out enable in software
MCUCR = bit (BODS) | bit (BODSE);
MCUCR = bit (BODS);
sleep_cpu();
/////////////////
}
void initSleep()
{
_sleepCount = _count;
detachInterrupt(0);
//setClock8();
//disable ADC to save power
_oldADC = ADCSRA;
ADCSRA = 0;
/////////////////////////////
_doSleep();
}
static uint8_t __clock_prescaler = (CLKPR & (_BV(CLKPS0) | _BV(CLKPS1) | _BV(CLKPS2) | _BV(CLKPS3)));
void setClock(uint8_t prescale) //Only call from within an interrup
{
// Disable interrupts.
uint8_t oldSREG = SREG;
//cli();
// Enable change.
CLKPR = _BV(CLKPCE); // write the CLKPCE bit to one and all the other to zero
// Change clock division.
CLKPR = prescale; // write the CLKPS0..3 bits while writing the CLKPE bit to zero
__clock_prescaler = prescale;
// Recopy interrupt register.
SREG = oldSREG;
//sei();
}
void setClock16() { setClock(0x0); }
void setClock8() { setClock(0x1); }
void loop()
{
static uint32_t lastCount = -1;
if(!SLEEP_ENABLED)
{
if(lastCount != _count)
{
Serial.println(_count, DEC);
lastCount = _count;
delay(100);
}
}
else
{
_doSleep();
}
}
#define
in parens. \$\endgroup\$