/** * Copyright 2015, Matthijs Kooijman * * Permission is hereby granted, free of charge, to anyone * obtaining a copy of this document and accompanying files, to do * whatever they want with them without any restriction, including, but * not limited to, copying, modification and redistribution. * * NO WARRANTY OF ANY KIND IS PROVIDED. * * * This example shows a simple interrupt-based button-controlled blinky * led that sleeps pretty much all the time. * * When you press a button, the internal led will light up. After four * seconds, it turns off again. Everytime you press the button, this * timeout will reset and the led stays on for four more seconds. * * Additionally, this will put the microcontroller to sleep whenever the * led is off, to save power. * * To use this, connect a button between GND and pin 2. This pin needs * to support an external interrupt, but most Arduinos seem to do so * (see the documentation for attachInterrupt or your Arduino). * * This example does not do any debouncing of the button, so be sure to * add that if you expand on this example and bouncing becomes a * problem. * * This example is identical to HalfSleepBlinky.ino, but sleeps also * when waiting for the timeout. */ #include #include #include "wdt_interrupt.h" // Be careful: Only some pins support interrupts. const uint8_t BUTTON_PIN = 2; const uint8_t BUTTON_INT = digitalPinToInterrupt(BUTTON_PIN); #if __cplusplus >= 201103L // Requires Arduino 1.6.6 static_assert(BUTTON_INT != (uint8_t)NOT_AN_INTERRUPT, "Interrupt not supported on selected pin"); #endif // On a buttonpress: turn on led and record time void buttonPress() { digitalWrite(LED_BUILTIN, HIGH); wdt_reset(); enable_wdt_interrupt(WDTO_4S); } ISR(WDT_vect) { digitalWrite(LED_BUILTIN, LOW); wdt_disable(); } void setup () { // Set up button pinMode(BUTTON_PIN, INPUT_PULLUP); attachInterrupt(BUTTON_INT, buttonPress, FALLING); // Set up led pinMode(LED_BUILTIN, OUTPUT); } void doSleep() { // Use the deepest kind of sleep, power-down set_sleep_mode (SLEEP_MODE_PWR_DOWN); sleep_enable(); // Enable interrupts and sleep. AVR guarantees that no interrupts // trigger between these two, so no race condition interrupts(); sleep_cpu (); sleep_disable(); } void loop () { // Just sleep all the time, the interrupt handlers will do the work doSleep(); }