#include <avr/sleep.h> #include <PinChangeInt.h> const byte LED = 13, SW = 5; volatile unsigned char count = 0; unsigned char lastCount = 255; void handleSW() { // ISR count++; } void wake() { // ISR sleep_disable(); // first thing after waking PCintPort::detachInterrupt(SW); } void sleepNow() { PCintPort::detachInterrupt(SW); set_sleep_mode(SLEEP_MODE_PWR_DOWN); noInterrupts(); sleep_enable(); PCintPort::attachInterrupt(SW, wake, LOW); interrupts(); // interrupts ok now, next instruction WILL be executed sleep_cpu(); // here we go to sleep } byte led = LOW; void handleOtherStuff() { digitalWrite(LED, led); led ^= (HIGH^LOW); if (count != lastCount) { Serial.print("Count "); Serial.println(count); lastCount = count; } delay(300); if (count > 1) { Serial.print(F("Going to sleep now ... ")); digitalWrite(LED, LOW); Serial.flush(); sleepNow(); // this is where we sleep Serial.println(F(" I'm awake!")); PCintPort::attachInterrupt(SW, handleSW, CHANGE); count = 0; } } void setup() { //Start up the serial port Serial.begin(9600); while (!Serial); // for Leonardo Serial.println(F("Initialized example6")); // configure the pins pinMode(LED, OUTPUT); pinMode(SW, INPUT_PULLUP); PCintPort::attachInterrupt(SW, handleSW, CHANGE); } void loop() { handleOtherStuff(); }
In this example, we use a pin change interrupt to awaken the processor from deep sleep. We have to use a level interrupt (i.e. HIGH or LOW).