Hoping someone can point out where I'm misinterpreting or making an error here. I was innocently reading the datasheet when I realized that some code I had previously written shouldn't work.
From the following sections of the datasheet, my interpretation is that an external interrupt (INT0 or 1, I'm using INT1) will only wake the MCU from power-down mode when configured for a level-based interrupt, not a falling or rising edge. And here's the problem, my code had INT1 configured for a falling edge and it was working. See the test code below, it works either for a low-level interrupt (ISC11=ISC10=0) or for falling edge (ISC11=1, ISC10=0).
Thanks in advance. Not sure which is worse, something that should work but doesn't, or something that shouldn't work but does
Notice Note (3):
Note that edge-triggered interrupts require clkIO, which is inactive in power-down mode:
/*----------------------------------------------------------------------*
* Sleep demo for ATmega328P. *
* Wire a button from pin D2 (INT0) to ground. *
* Wire an LED with an appropriate dropping resistor from pin D13 to *
* ground. *
* Pushing the button wakes the MCU. *
* After waking, the MCU flashes the LED, then waits 10 seconds before *
* going back to sleep. *
* *
* Jack Christensen 07May2013 *
* *
* Developed with Arduino 1.0.4 and an Arduino Uno. *
* Test conditions for all results below: *
* 5V regulated power supply, fed to the Vin pin *
* 16MHz system clock *
* Fuse bytes (L/H/E): 0xFF / 0xDE / 0x05 *
* Optiboot bootloader *
* *
* Uno R1 *
* 38mA active, 26mA with MCU in power-down mode. *
* *
* Uno SMD edition *
* 42mA active, 31mA power-down. *
* *
* Adafruit Boarduino *
* Power select jumper set to "USB", USB (FTDI) not connected. *
* 15mA active, 3mA power-down. *
* *
* Adafruit Boarduino without power LED *
* 12mA active, 0.1µA power-down. *
* *
* Breadboarded ATmega328P-PU *
* 12mA active, 0.1µA power-down. *
* *
* This work is licensed under the Creative Commons Attribution- *
* ShareAlike 3.0 Unported License. To view a copy of this license, *
* visit http://creativecommons.org/licenses/by-sa/3.0/ or send a *
* letter to Creative Commons, 171 Second Street, Suite 300, *
* San Francisco, California, 94105, USA. *
*----------------------------------------------------------------------*/
#include <avr/sleep.h>
#define LED LED_BUILTIN //LED on pin 13
#define KEEP_RUNNING 10000 //milliseconds
void setup(void)
{
//to minimize power consumption while sleeping, output pins must not source
//or sink any current. input pins must have a defined level; a good way to
//ensure this is to enable the internal pullup resistors.
for (byte i=0; i<20; i++) { //make all pins inputs with pullups enabled
pinMode(i, INPUT_PULLUP);
}
pinMode(LED, OUTPUT); //make the led pin an output
digitalWrite(LED, LOW); //drive it low so it doesn't source current
}
void loop(void)
{
goToSleep();
for (byte i=0; i<5; i++) { //flash the LED
digitalWrite(LED, HIGH);
delay(100);
digitalWrite(LED, LOW);
delay(100);
}
delay(KEEP_RUNNING); //opportunity to measure active supply current
}
void goToSleep(void)
{
byte adcsra, mcucr1, mcucr2;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
// >>>--> either of the following two lines work!
EICRA = _BV(ISC11); //interrupt on falling edge
// EICRA = 0x00; //interrupt on low level
EIFR = _BV(INTF1); //ensure interrupt flag is cleared (setting ISCnn can cause an interrupt)
EIMSK = _BV(INT1); //enable INT1
adcsra = ADCSRA; //save the ADC Control and Status Register A
ADCSRA = 0; //disable ADC
cli(); //stop interrupts to ensure the BOD timed sequence executes as required
mcucr1 = MCUCR | _BV(BODS) | _BV(BODSE); //turn off the brown-out detector while sleeping
mcucr2 = mcucr1 & ~_BV(BODSE);
MCUCR = mcucr1; //timed sequence
MCUCR = mcucr2; //BODS stays active for 3 cycles, sleep instruction must be executed while it's active
sei(); //ensure interrupts enabled so we can wake up again
sleep_cpu(); //go to sleep
sleep_disable(); //wake up here
ADCSRA = adcsra; //restore ADCSRA
}
//external interrupt 1 wakes the MCU
ISR(INT1_vect)
{
EIMSK = 0; //disable external interrupts (only need one to wake up)
}