OK, rather to my surprise, it works!
Please see attached schematic, note that as I don't have an Arduino footprint in my KiCAD library, I've resorted to using a connector... The pin references to match the schematic are:
Pin 1: Connect to +5V
Pin 2: Connect to Digital Pin 10
Pin 3: Connect to Reset
Pin 4: Connect to Digital Pin 5
Pin 5: Connect to GND
Load the following code (I tested this on an Arduino Nano):
#include <avr/power.h>
#include <avr/sleep.h>
#define CANCEL_RESET 10 // Connect to J1 pin 2 on schematic
#define DO_STUFF 5 // Connect to J1 pin 4 on schematic
#define INDICATOR 13
void setup() {
// Set pin HIGH to hold reset HIGH, even when the button is pressed.
pinMode(CANCEL_RESET,OUTPUT);
digitalWrite(CANCEL_RESET,HIGH);
// Read the button on this pin
pinMode(DO_STUFF,INPUT);
digitalWrite(DO_STUFF,LOW);
// Indicate we did something
pinMode(INDICATOR,OUTPUT);
digitalWrite(INDICATOR,LOW);
Serial.begin(38400);
Serial.println("Ready.");
}
void loop() {
static unsigned long then = millis();
static byte counter = 0;
// put your main code here, to run repeatedly:
if(digitalRead(DO_STUFF) == HIGH) {
// Recognise the button, wait for it to be
// released
Serial.println("Button DOWN!");
counter = 0;
digitalWrite(INDICATOR,HIGH);
while(digitalRead(DO_STUFF)==HIGH) {
//Don't count time passing while the button's in.
then=millis();
}
digitalWrite(INDICATOR,LOW);
Serial.println("Button UP!");
}
unsigned long now = millis();
if (now-then > 1000) {
counter++;
then=now;
Serial.print("Pulse ");
Serial.println(counter);
}
if (counter >= 10) {
// 30 seconds have elapsed without the button
// being pressed. So go to sleep now
Serial.println("Feeling sleepy.....");
counter=0;
// First, tell the user we're doing this...
// by flashing the LED rapidly for 2 seconds
for(byte i=0;i<10;i++) {
digitalWrite(INDICATOR,HIGH);
delay(100);
digitalWrite(INDICATOR,LOW);
delay(100);
}
// Now sleepybo time
Serial.println("Zzzzz");
digitalWrite(CANCEL_RESET,LOW);
delay(100);
sleepNow();
Serial.println("Fast asleep now.");
}
}
void sleepNow()
{
// Choose our preferred sleep mode:
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
// Set sleep enable (SE) bit:
sleep_enable();
// Put the device to sleep:
sleep_mode();
// Upon waking up, sketch continues from this point.
sleep_disable();
}
Make sure the diode is the right way around (if it's wrong, your MCU will continually reset).
The code above will output a message to the serial port every second (handy for testing, as it flashes the Tx).
If you press the button while the machine is awake, you'll get the button down/button up messages & the timer will reset.
When the timer runs out (30s), it'll flash the LED a few times & fall asleep (proof: You never see the "Fast asleep now" message.
Next time you press the button, it will reset the Arduino, which powers back up.
Since I'm using a boggo Nano, I measured the current usage @ 5v to be approximately 23mA whilst running (maybe 26mA with the button pressed & the lamp lit); this dropped to about 6mA when asleep (I guess most of that is the power light & the regulator?)
Now... hopefully someone can come along & tell me why a) this is a terrible circuit, and b) why it can't work. Because, in all honesty, I'm a bit surprised it DOES work!