Arduino Uno R3 - Sleep Mode Power Down and Awake via Button on Pin2 (INT0)

Hi @ all, i´ve a question.

I have an arduino uno r3, and i want to program the arduino with a push button at digital pin2 (interrupt 0) for switching on (sleep_disable) and off (Sleep Mode Power Down) the mcu.

so that when the button once pressed, should save a power state var (when the mcu is alive - change powerstate var from powerstate 1 to powerstate 0) and then go to sleep mode power down.

then attach awake interrupt for int0 button so that, when the button pressed once again, the mcu goes alive and change the power state var from powerstate 0 to powerstate 1. and then again attach power down interrupt for int0 button.

I'm a few days it failed and get it absolutely not out. Is there anyone who can help me detailed or with code example to get this out?

many thanks for all efforts
just4fun78

I was looking in Arduino.cc Reference, have played and tested with many Code Examples, but this all was not much pretty helpful for me.

Can anyone help me please, to figure this out?

regards
just4fun78

#include <avr/sleep.h>

int SL_Pin = 2; // sleep pin - int0 button
int B_Led = 12; // blinkled
int P_Led = 13; // powerled

void sleepNow()
{
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();

digitalWrite(B_Led, LOW); // turn off the blinkled
digitalWrite(P_Led, LOW); // turn off the powerled
sleep_mode(); // here the mcu is power down
sleep_disable();
}

void wakeUpNow()
{
digitalWrite(P_Led, HIGH); // turn on the powerled
}

void setup()
{
pinMode(SL_Pin, INPUT); // int0 button - 10k pulldown to gnd
pinMode(P_Led, OUTPUT); // set pin 13 led as output
digitalWrite(P_Led, HIGH); // turn on the powerled
pinMode(B_Led, OUTPUT); // set pin 12 as output

attachInterrupt(0, sleepNow, RISING); // attach int0 to sleepNow function by rising the sleep pin
}

void blinkled()
{
digitalWrite(B_Led, HIGH);
delay(500);
digitalWrite(B_Led, LOW);
delay(500);
}

void loop()
{
blinkled();
}

I dont get it out, how can i make the wakeupnow function attached to interrupt 0 before power down, so that mcu wakeupnow with pressing once again the button on pin 2?

can really nobody help me please? :frowning:

I haven't done it with INT0/INT1 (I use PCINTs)...

It looks to me though like the code you've attached to that interrupt is calling sleepNow() which would imply that it wakes up and immediately goes back to sleep.

There have got to be examples of this around; this is a very common use case.

Hi thanks for your reply.

The code so is still good working, for the sleepnow function. This is, i think so, absolutely correct.

My Problem is, to use the interrupt 0 for the wakeupnow attaching, the interrupt 0 must be detached... so i have done in the sleepnow function not here in sample code, and then before the mcu is power down, attached the interrupt 0 again to the wakeupnow function by rising the interrupt 0 pin.

but it doesnt work, and i don't no why... *why sleepnow detaching of interrupt 0 ... and new attaching to wakeupnow function in sleepnow function, is not working.

Will it even wake up if it's put to sleep with interrupts disabled?

I dont now :frowning:

I try for several days but i found no destination for my problem.

With PinchangeInterrupts i haven't work yet, i hoped so many, to get working via my example.

It shouldn't really matter whether it's pin change or external interrupts. In either case you'll get bounces from the button that could generate interrupts. Since you're using one button you'll have to wait for it to be released and debounced before putting the processor to sleep.

Maybe something like this:

void setup() {
  attachInterrupt(0, buttonISR(), RISING);
}

bool buttonPressed = false;

void buttonISR() { buttonPressed = true; }

void loop() {
  if (buttonPressed) {
    delay(10);     // debounce button press
    while (digitalRead(button)) {}    // wait for it to be released
    delay(10);     // debounce button release
    buttonPressed = false;

    gotoSleep();    // function to put the processor to sleep; a button press will wake it up

    delay(10);     // debounce button press
    while (digitalRead(button)) {}    // wait for it to be released
    delay(10);     // debounce button release
  }
}

Yes i understand, aber in this example is only too, the mcu get to sleep when pcint triggered.

The mcu go to sleep is working too like a charm in my code example.

My problem is the awake after go to sleep with the same button.

I want the mcu put to sleep mode power down by pressing once the button, and when mcu is power down, that mcu is awake by once again pressing the button.

Do you understand me right?

Yes, you want to push a button that puts the processor to sleep and then push the same button again to awaken it.

Here is some code that I just tried on an Uno and it works. I wired the button differently than you. I just have a wire go from pin 2 to the button and then the other leg of the button directly to ground.

#include <avr/sleep.h>

// connect a button between pin 2 and ground

const int buttonPin = 2;  // int 0 pin, connected to button
const int ledPin = 13;    // built-in LED on Uno board

bool buttonPressed = false;
bool ledState = LOW;
unsigned long ms;

void setup() {
  Serial.begin(115200);
  Serial.println("\nHello\n");
  
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);
  attachInterrupt(0, buttonISR, FALLING);
  
  ms = millis();
}

void buttonISR() { buttonPressed = true; }

void loop() {
  if (buttonPressed) {
    delay(10);     // debounce button press
    while (!digitalRead(buttonPin)) {}    // wait for it to be released
    delay(10);     // debounce button release
    digitalWrite(ledPin, LOW);    // turn off LED
    ledState = LOW;

    Serial.println("Going to sleep...");
    Serial.flush();
    gotoSleep();    // function to put the processor to sleep; a button press will wake it up

    delay(10);     // debounce button press
    while (!digitalRead(buttonPin)) {}    // wait for it to be released
    delay(10);     // debounce button release
    buttonPressed = false;
    Serial.println("Awake!");
    Serial.flush();
  }
  
  if ((millis() - ms) > 250) {    // when awake, toggle the LED every 250 ms
    ms = millis();
    if (ledState == LOW) {
      digitalWrite(ledPin, HIGH);
      ledState = HIGH;
    } else {
      digitalWrite(ledPin, LOW);
      ledState = LOW;
    }
  }
}

void gotoSleep()
{
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);
  noInterrupts();           // timed sequence follows
  sleep_enable();
  interrupts();             // guarantees next instruction executed
  sleep_cpu();              // nighty-night!
  sleep_disable();          // awake again -- cancel sleep as a precaution
}

I don’t really like this code that much though. The interrupt will happen probably dozens of times for each button press because the button bounces. It doesn’t matter for this example but it’s sloppy. It would be better to disable the interrupt until the button is debounced. But I don’t think detachInterrupt() code works properly to clear the interrupt flag so you can’t do it unless you address the registers directly. At least that’s my understanding.

Like DrAzzy I always end up using the pin change interrupts.

Hi jboyton, first many thanks for your efforts and for your time to introducing an arduino beginner. I’ve never programmed with mcu’s before, but a little php and so things. I can read and understand electrical circuits, and these are my first steps with mcu programming, and i know what are things like pullup resistor, pulldown resistor, bouncing and hardware or software debouncing. I have tested it with leds and buttons on my arduino. So i understand working code examples better still than reference descriptions.

I have tested your code and i see it is working, and i know the bouncing problem. I have put the code in my arduino learning folder.

In the arduino reference i’ve seen that pin change interrupt is possible for every arduino pin, but it has not yet managed to create a working example of me.

Can you figure out a working example with me for set to sleep and awake my arduino mcu via pin change interrupt method, so i understand how pcint works please?

Wish a nice day
regards
just4fun78

You can find an example here: Gammon Forum : Electronics : Microprocessors : Interrupts

Nick Gammon's other pages are also really good for learning and as a reference. The sleep code in the sketch I posted above is lifted from one of his examples.