I just made a small change to the Optiboot bootloader, which allows sketches to detect the source of a reset. This means the reset button can be used as a control input.
Because of the way Optiboot works there are limitations: it's not possible to distinguish an external reset (pushing the reset button) from a watchdog reset. But it does allow a sketch to distinguish a power-on event from other reset sources.
The change is to optiboot.c, and consumes an extra 4 bytes of bootloader memory. With v4.5 compiled for an ATmega328 this still fits in the 512 bytes available, with 2 bytes free:
342c342
< MCUSR = 0;
---
> MCUSR &= ~(1<<WDRF | 1<<EXTRF);
And an example sketch looks like this:
void setup() {
int startup = MCUSR;
MCUSR=0;
pinMode(13, OUTPUT);
delay(1000);
if (startup == 0) {
// ----- flash LED twice quickly after external reset
digitalWrite(13, HIGH); delay(100); digitalWrite(13, LOW);
delay(100);
digitalWrite(13, HIGH); delay(100); digitalWrite(13, LOW);
} else {
// ----- flash LED once slowly after power-up
digitalWrite(13, HIGH); delay(1000); digitalWrite(13, LOW);
}
}
void loop() {
}