Sleep & Wake in dual button mode (hold)

Hello I am new to programming I recently started a project and I need some help with a control feature I want to add and having an issue.
What I want to achieve is the control style of a mobile power button.
When power button is hold down device goes to sleep or wake if it is already in sleep mode.
Also one single button click have another function. But so far, once I put it into sleep, I cannot wake it up, only by resetting.
This is my try so far.

#include <avr/sleep.h>
#include <avr/interrupt.h>
#include <Bounce2.h>

int controlButton = 2; // button
int pwr1 = 10; // 7 segment display common kathode
int pwr2 = 11; // 7 segment display common kathode
int pwr3 = 12; // 7 segment display common kathode
int pwr4 = 13; // 7 led user interface common kathode
int ledHeat = A2; // PID output
int lastButtonStateControl;
int currentButtonStateControl;
unsigned long pwrDnTime; // to keep track of hold down time
boolean Control = 0;  // this is the var that changes in simple click
Bounce  debouncerControl  = Bounce();
#define holdTime 3000



void setup ()
{
  digitalWrite(controlButton , HIGH);
  debouncerControl.attach(controlButton);
  debouncerControl.interval(5);
}



void sleepNow()
{
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  attachInterrupt (0, wakeUpNow, CHANGE);
  digitalWrite (pwr1, LOW);
  digitalWrite (pwr2, LOW);
  digitalWrite (pwr3, LOW);
  digitalWrite (pwr4, LOW);
  digitalWrite (ledHeat, LOW);
  sleep_mode();
  sleep_cpu();
}



void wakeUpNow()
{
  sleep_disable();
  detachInterrupt(0);
}



void loop()
{
  currentButtonStateControl = debouncerControl.read(); // debounce library analog read

  if (currentButtonStateControl == HIGH && lastButtonStateControl == LOW)
    pwrDnTime = millis();
  
  if (currentButtonStateControl == LOW && lastButtonStateControl == HIGH)
    Control = !(Control);
  

  if (currentButtonStateControl == HIGH && (millis() - pwrDnTime) > holdTime)
    sleepNow();
  
  lastButtonStateControl = currentButtonStateControl;
}
Bounce  debouncerControl  = Bounce();

This is crap.

Bounce  debouncerControl;

THIS is correct.

boolean Control = 0;  // this is the var that changes in simple click

boolean variables are SUPPOSED to be assigned true or false.

  attachInterrupt (0, wakeUpNow, CHANGE);

Have you read what modes can be used to wake up?

Thank you for your fast reply. I made the changes you told me. And yes I have read the interrupt s and sleep examples and reference. I also watched some videos about interrupt and google it. But still can’t figure what I am doing wrong. I can make it sleep (I think) at least the segment is turned off.

Since you don't specify which Arduino you use, I will assume an Uno. In other words, a 328P processor. I will refer you to the datahseet: http://www.mouser.com/ds/2/36/Atmel-8271-8-bit-AVR-Microcontroller-ATmega48A-48P-259144.pdf

Specifically, I refer you to Table 10-1 on page 38 in teh Power Management and Sleep Modes section. Look at that table, specifically the Wake Up Sorces part, and see if you can figure out why your procssor won't wake up.

Yes I have an Arduino UNO 328 R3.

I did read the power management it says I can wake up from (SLEEP_MODE_PWR_DOWN) with pin change INT1, INT0. TWI Address Match & Watchdog Timer.

From Datasheet “An external level interrupt on INT0 or INT1, or a pin change interrupt can wake up the MCU”

INT0 is D2 Pin at least that’s what I understood, and that’s where I have connected the button.
So I guess I will have to disable TWI Address Match & Watchdog Timer for more power efficiency since I only need pin change. On the other hand I need this to wake up on button hold. So I will need Watchdog Timer enable?

Sorry for doing n00bish questions.

I did read the power management it says I can wake up from (SLEEP_MODE_PWR_DOWN) with pin change INT1, INT0. TWI Address Match & Watchdog Timer.

Did you see the little 3 and the footnote that went with it?

Yes. I tryed it with Falling Mode. And it will turn on on a single click.

void sleepNow()
{
  sleep_enable();
  attachInterrupt(0, wakeUpNow, FALLING);
  /* 0, 1, or many lines of code here */
  digitalWrite (pwr1, LOW);
  digitalWrite (pwr2, LOW);
  digitalWrite (pwr3, LOW);
  digitalWrite (pwr4, LOW);
  digitalWrite (ledHeat, LOW);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  cli();
  //sleep_bod_disable();
  sei();
  sleep_cpu();
  /* wake up here */
  sleep_disable();
  detachInterrupt(0);
}

void wakeUpNow()
{
}

  if (currentButtonStateControl == HIGH && lastButtonStateControl == LOW)
  {
    pwrDnTime = millis();
  }
void loop ()
{
  if (currentButtonStateControl == HIGH && (millis() - pwrDnTime) > holdTime)
  {
    sleepNow();
  }
}

Is there any way to make it wake up again after a button hold and not a single click?

  1. For INT1 and INT0, only level interrupt.

That means not RISING, not FALLING, and not CHANGE. That leaves only HIGH (which doesn't exist) and LOW.

Is there any way to make it wake up again after a button hold and not a single click?

How is the Arduino supposed to know that the button was held? It needs to wake up as soon as the interrupt happens.

What it does after it wakes up is up to you. But, not, you can not make it wake up only after the switch has been held down a while.

Ok now I think I start to understand. However in attachInterrupt(0, wakeUpNow, LOW); when it turns off after 3 sec and I take my finger from the button it wakes up again.

So i will have to make it wake up on single click and "look like it is off (digital/analogWrite LOW)".
If the button is held down for less than 3 sec then it will go to sleep again and if button is held down for more than 3 sec will wake.

PaulS:
make it wake up only after the switch has been held down a while.

I suppose you could connect an external RC circuit that took time to being the input level up far enough to trigger the interrupt.