Arduino/Atmega328PU wake up with a long button press

Hello there,

I’m working on a new project. One important topic is to save power in standalone Atmega 328PU. The microcontroller is into a deep sleep mode and should only wake up after the button was pressed for over 3 seconds. I wrote the following two codes.

#define LED_PIN 13
void setup() {
// put your setup code here, to run once:
//Save Power by writing all Digital I0 LOW 
for(int i=0; i<20; i++){
  if(i != 2)//just because the button is hooked up to digital pin 2
    pinMode(i, OUTPUT);

  attachInterrupt(0, digitalInterrupt, FALLING); //interrupt for waking up

void loop() {
  // put your main code here, to run repeatedly:
digitalWrite(LED_PIN, HIGH);
digitalWrite(LED_PIN, LOW);

ADCSRA &= ~(1<<7);
SMCR |= (1<<2); //power down mode
SMCR |= 1; //enable sleep

MCUCR |=(3 << 5); //set both BODS and BODSE at the same time
MCUCR = (MCUCR & ~(1 << 5)) | (1<< 6); //then set the BODS bit and clear the BODS bit at the same time
__asm__ __volatile__("sleep");

void digitalInterrupt(){
  //needed for the digital input interrupt
int inPin = 2;  // the pin number for input (for me a push button)
int ledPin = 13; 

int current;         // Current state of the button
                     // (LOW is pressed b/c i'm using the pullup resistors)
long millis_held;    // How long the button was held (milliseconds)
long secs_held;      // How long the button was held (seconds)
byte previous = HIGH;
unsigned long firstTime; // how long since the button was first pressed 

void setup() {
  pinMode(ledPin, OUTPUT);
  digitalWrite(inPin, HIGH);  // Turn on 20k pullup resistors to simplify switch input

void loop() {
  current = digitalRead(inPin);

  // if the button state changes to pressed, remember the start time 
  if (current == LOW && previous == HIGH) {
    firstTime = millis();

  millis_held = (millis() - firstTime);
  secs_held = millis_held / 1000;

    if (current == LOW && previous == LOW) {

      // If the button was held for more then 3 seconds blink LED 1 time
      if (secs_held >= 3) {


  previous = current;


// Just a simple helper function to blink an led in various patterns
void ledblink(int times, int lengthms, int pinnum){
  for (int x=0; x<times;x++) {
    digitalWrite(pinnum, HIGH);
    delay (lengthms);
    digitalWrite(pinnum, LOW);

The first code is for the deep sleep mode and wakes the Atmega 328PU up after an external interrupt.
The second code is a normal code (without any power saving option) and reads the digital input and sets a timer if the button was pressed. If the timer is over 3 seconds and the button is still pressed something will happen (for example a LED will flash).

So now my question is how to combine them? Is there any way to do that?
I hope somebody can help me :slight_smile: I’m looking forward to your replies.

Best regards

Maurice W.

You could use the interrupt to wake the processor on the switch closure. Then set up a watchdog timer. The closest options are 2 seconds and 4 seconds. You would then change the interrupt to detect a switch open. Then find if the watchdog fired first, or the switch open fired first. If you really want 3 seconds have a watchdog of 2 seconds followed by a watchdog of 1 second.

Hello Nick, thanks for your quick reply. Your idea sounds good. But where do I have to set the watchdog timer in my code and how can I detect a switch open?

My link shows how to set up the watchdog timer. To detect a switch open you make an interrupt on RISING rather than FALLING (or vice-versa depending on how the switch is wired).