1

I am working on a battery powered Arduino project, where I need to put a standalone Arduino in sleep mode (to save some battery).

My aim is to put Arduino in sleep mode by holding a button for 3 seconds or more on pin 2 (hardware interrupt) and wake it up by holding the same button by 3 seconds or more.

I can put the Arduino to sleep by holding button more than 3 seconds, but I can't wake it from it by holding the button for 3 seconds.

Below is my code:

#include <avr/sleep.h>
const int led1 = 44;
const int led2 = 45;
const int led3 = 46;
const int usbState = 12;
float pressLength = 0;
const int button = 2;
int optionOne = 100;
int optionTwo = 3000;

void setup() {
  pinMode(button, INPUT);
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(usbState, INPUT);
  Serial.begin(9600);
}

void loop() {
  while (digitalRead(button) == LOW) {
    delay(100);
    pressLength = pressLength + 100;
    Serial.print("ms-");
    Serial.println(pressLength);
  }
  if (pressLength >= optionTwo) {
    digitalWrite(led1, LOW);
    digitalWrite(led2, LOW);
    digitalWrite(led3, LOW);
    sleepNow();     // sleep function called here
  } else if (pressLength >= optionOne) {
    digitalWrite(led1, HIGH);
    digitalWrite(led2, HIGH);
    digitalWrite(led3, HIGH);
    while (1) {} //Keeps LEDS HIGH
  }
}

void sleepNow() {
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
  sleep_enable(); // enables the sleep bit in the mcucr register
  attachInterrupt(0, wakeUpNow, LOW); // use interrupt 0 (pin 2) and run function
  sleep_mode(); // here the device is actually put to sleep!!
  // THE PROGRAM CONTINUES FROM HERE AFTER WAKING UP
  while (digitalRead(button) == LOW) {
    delay(100);
    pressLength = pressLength + 100;
    Serial.print("ms-");
    Serial.println(pressLength);
  }
  if (pressLength >= optionTwo) {
    SleepNow(); //Back to sleep fucntion
  } else if (pressLength >= optionOne) {
    sleep_disable();
    // first thing after waking from sleep: disable sleep...
    resetFunc();//Resetting 
  }
}

void wakeUpNow() {
  // execute code here after wake-up before returning to the loop() function
  // timers and code using timers (serial.print and more...) will not work here.
  // we don't really need to execute any special functions here, since we
  // just want the thing to wake up
}
void(* resetFunc)(void) = 0;

Please help. Thanks.

  • 1
    with 2 resistors and a capacitor you can do that without code. – ratchet freak Aug 25 '17 at 12:38
  • ^How, where to attach cap and resistors and what values.? – Mudassir Hussain Aug 25 '17 at 12:40
4

You won't manage it without external circuitry.

The problem is the Arduino has to be awake to know you held the button for 3 seconds. You can only wake immediately you press the button. However you could then sleep again if the button is released within 3 seconds.

For external circuitry, you would need to arrange to charge (or discharge) a capacitor slowly through the button so that it reaches a threshold after 3 seconds and that threshold triggers the input to the Arduino. A HIGH input on the Arduino is 0.6×Vcc, so 3.3V for a 5V Arduino. If you arrange it that the capacitor reaches 3.3V after being charged for 3 seconds the input will see it at the right time.

schematic

simulate this circuit – Schematic created using CircuitLab

In this circuit, R1 and C1 form an RC network that charges the capacitor through the switch. C1 and R1+R2 form an RC network that discharges the capacitor all the time, so it is discharged when you release the button.

Discharge time will be slightly longer than charge time owing to the addition of R1 + R2.

To calculate the charge time, you can use T=RC which is how long (in seconds) it takes to charge the capacitor up to 63.2% of the supply voltage. That's fractionally over the 60% that the HIGH threshold is, so that's fine.

If you want T=RC to equal 3 seconds, you can rearrange the formula to suit your components. For instance if you have a 1000µF capacitor available you can rearrange to R=3/0.001 = 3kΩ. So a common 3.3kΩ resistor and 1000µF capacitor would give you (3300 × 0.001) 3.3 seconds.

R2 wants to be small enough that it doesn't slow down discharge too much, yet high enough that it doesn't draw too much current. Using about 10% of R1 is reasonable (330Ω), so with a 3.3 second charge time that resistor would increase the discharge time by 0.33 seconds.

This method is basically a very extreme form of debouncing.

  • There is no need at all for electronics here: you can perform all in software. When you press the button, check it after 3 seconds. If it's still pressed => set the wakeup interrupt and then sleep. Similarly. When you press the switch during sleep, you will wake up. Before doing anywhing, check after 3 seconds if the button is still pressed. Still pressed? => wake up (i.e. enable peripherals, etc), otherwise go to sleep. Using electronics when you have already a MCU is wasteful. – next-hack Aug 26 '17 at 9:51
  • @next-hack Read paragraph 2 of the answer. Anyway, waking the MCU for a few seconds may not be what is wanted since it will increase power consumption while the decision is being made - and this is only a couple of passives anyway, with zero idle current. – Majenko Aug 26 '17 at 10:06
  • @next-hack Anyway, you're second guessing the OPs requirements. Yes, as in many things, there are multiple ways of performing the same or similar task. However the OP asked specifically about waking the MCU after 3 seconds of button press, not waking the MCU immediately then 3 seconds later deciding whether or not to stay awake. Personally I wouldn't do either, but would use an external small XLP MCU (such as a PIC10LF320) as a power management controller. – Majenko Aug 26 '17 at 10:13
  • my fault, I missed the "However you could then sleep again if the button is released within 3 seconds.". About second guessing, you're right too, still, sometimes, suggestions can be useful, e.g. to make someone realize that 3 seconds in which the MCU is active (possibly in a lower power-state, using a lower clock frequency, with everything disabled), will not have any noticeable impact in most cases. – next-hack Aug 26 '17 at 10:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.