Pages: [1]   Go Down
Author Topic: How to wake up after sleep mode using the millis() function  (Read 881 times)
0 Members and 1 Guest are viewing this topic.
Greece
Offline Offline
Full Member
***
Karma: 2
Posts: 172
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello i use the millis() function to count a delay, and i want to have a switch for on - off, on time LOW the the millis should be start count, another one time LOW should be stop cound and go for sleep for save energy (because i use battery),

My problem is when the device start and blink the led i press the switch to LOW and the device going to sleep when i press it again then never wakeup, what i am doing wrong ? or what i miss it ?

Code:
#include <avr/sleep.h>

int led = 13;
int wakepin = 2;
boolean flag = false;

unsigned long time = 0;


void wakeupnow(){
flag = true;
}

void setup(){

pinMode(led,OUTPUT);
pinMode(wakepin,INPUT);
attachInterrupt(0,wakeupnow,LOW);
}

void sleepnow(){
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
attachInterrupt(0,wakeupnow,LOW);
sleep_mode();

sleep_disable();
//detachInterrupt(0);
delay(1000);
flag = false;
}

void loop(){
if (millis() - time > 1000){
time = millis();
digitalWrite(led,HIGH);
delay(500);
digitalWrite(led,LOW);
}

if (flag == true) {
sleepnow();
flag = false;
}
}

Thank you in advance.


Moderator edit: [code] [/code] tags added.
« Last Edit: January 21, 2012, 02:47:48 pm by Coding Badly » Logged

Grand Blanc, MI, USA
Offline Offline
Faraday Member
**
Karma: 95
Posts: 4086
CODE is a mass noun and should not be used in the plural or with an indefinite article.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Please post code between code tags using the # button.

One thing I notice is that pin 2 should have a pullup resistor. So I'd enable the internal pullup, unless there is an external pullup. In fact it's a good idea to do this on all unused pins to minimize power consumption (see code below). To reduce power consumption even further during sleep mode, consider turning off the analog-to-digital converter and the brown-out detector.

Code:
void makePinsInput()
{
    for (byte i=0; i<20; i++) {
        pinMode(i, INPUT);        //make all pins input pins
        digitalWrite(i, HIGH);    //with pullup resistors to minimize power consumption
    }
    pinMode(13, OUTPUT);          //except the LED pin
    digitalWrite(13, LOW);
}
Logged

MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

United Kingdom
Online Online
Tesla Member
***
Karma: 224
Posts: 6619
Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

It sort of works for me. I connected the switch between pin 2 and ground, with an external pullup resistor to +5v. It's hard to get it to sleep because I have to press the switch while the LED is on and release it before the LED goes off, otherwise pin 2 is still low when it enters sleep mode and it wakes up immediately. But when I do get it to sleep, pressing the button wakes it up again.
Logged

Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

Grand Blanc, MI, USA
Offline Offline
Faraday Member
**
Karma: 95
Posts: 4086
CODE is a mass noun and should not be used in the plural or with an indefinite article.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

@dc42, good point. A technique I use is to not enable the interrupt until just before going to sleep. While not sleeping, I just use ordinary techniques to read the switch. The ISR disables further interrupts from the switch.
Logged

MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

Greece
Offline Offline
Full Member
***
Karma: 2
Posts: 172
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I have test with the external resistor and the internal but no change does that @dc42 say,i have confuse my self i try so many changes and i am lost ...

Logged

Grand Blanc, MI, USA
Offline Offline
Faraday Member
**
Karma: 95
Posts: 4086
CODE is a mass noun and should not be used in the plural or with an indefinite article.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

This is another situation where delay() can cause trouble, specifically, it will delay the system's ability to respond to the pushbutton. You've got the basic technique to avoid using delay() here:

Code:
   if (millis() - time > 1000){
      time = millis();

It just needs to be made to operate to turn the LED both on and off.

Step back and rather than writing code, chart out what needs to be done, e.g.

loop() can just do something like:

Is the button pushed?
    If YES, then go to sleep.
    If NO, then is it time to turn the LED on or off?

Now have one function for blinking the LED, and one for going to sleep.

gotoSleep():

Wait for the button to be released.
Enable the interrupt.
Go to sleep.
(Wake up)
Disable the interrupt.

blinkLED():

...is left as an exercise for the reader smiley-lol
Logged

MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

Grand Blanc, MI, USA
Offline Offline
Faraday Member
**
Karma: 95
Posts: 4086
CODE is a mass noun and should not be used in the plural or with an indefinite article.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

PS: I didn't provide for any switch debouncing. Depending on the switch, YMMV. But in this case we can probably get away with a fairly crude approach. A small delay would be ok in this case, shorter than human perception time but long enough for the switch to stop bouncing, so:

gotoSleep():

Wait for the button to be released.
Delay ~20 ms, else a bounce may wake the MCU immediately after the interrupt is enabled.
Enable the interrupt.
Go to sleep.
(Wake up)
Disable the interrupt.
Logged

MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

Greece
Offline Offline
Full Member
***
Karma: 2
Posts: 172
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@Jack  I think you give me the light ;-)

I thing now it is working  smiley-small

Code:
#include <avr/sleep.h>

int led = 13;
int wakepin = 2;
boolean flag = false;

unsigned long time = 0;


void wakeupnow(){
flag = true;
}

void setup(){
pinMode(led,OUTPUT);
pinMode(wakepin,INPUT);
digitalWrite(wakepin,HIGH);
attachInterrupt(0,wakeupnow,LOW);

}

void sleepnow(){
while (digitalRead(wakepin) == LOW)
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
attachInterrupt(0,wakeupnow,LOW);
sleep_mode();

sleep_disable();
delay(1000);
//detachInterrupt(0);
flag = false;
}

void loop(){
//cli();
if (millis() - time > 1000){
time = millis();
digitalWrite(led,HIGH);
delay(500);
digitalWrite(led,LOW);
}

if (flag == true) {
sleepnow();
flag = false;
}
}


Moderator edit: [code] [/code] tags added.
« Last Edit: January 21, 2012, 02:48:24 pm by Coding Badly » Logged

Greece
Offline Offline
Full Member
***
Karma: 2
Posts: 172
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

After some test i do i see when i press the button when the led it is on the system it is not going always for sleep ...do i miss something ?

Do i have to disable the interrupts ? or do i must use the digitalRead function to check for the pin ?
Logged

United Kingdom
Online Online
Tesla Member
***
Karma: 224
Posts: 6619
Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

After some test i do i see when i press the button when the led it is on the system it is not going always for sleep ...do i miss something ?

See reply #5.
Logged

Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

Greece
Offline Offline
Full Member
***
Karma: 2
Posts: 172
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you my friends for the help, i thing now it is working .....

Code:
#include <avr/sleep.h>

int led = 13;
int wakepin = 2;
boolean flag = false;

unsigned long time,stay = 0;

void wakeupnow(){
flag = true;
}

void setup(){
pinMode(led,OUTPUT);
pinMode(wakepin,INPUT);
digitalWrite(wakepin,HIGH);
attachInterrupt(0,wakeupnow,LOW);
}

void sleepnow(){
while (digitalRead(wakepin) == LOW)
digitalWrite(led,LOW);
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
attachInterrupt(0,wakeupnow,LOW);
sleep_mode();

sleep_disable();
time = millis();
delay(1000);
//detachInterrupt(0);
flag = false;
}

void loop(){
if (millis() - time > 1000){
time = millis();
digitalWrite(led,HIGH);
//delay(500);
stay = millis();
}

if  (millis() - stay > 500) digitalWrite(led,LOW);

if (flag == true) {
flag = false;
sleepnow();
}
}

The last issue it was when i was press the button when the led it was on (On delay....) i change the delay with millis and now it looks ok
and i use the bellow code to wait the relase of the button :-)

void sleepnow(){
   while (digitalRead(wakepin) == LOW); <-- here is the check.


Moderator edit: ditto.
« Last Edit: January 21, 2012, 02:49:06 pm by Coding Badly » Logged

Grand Blanc, MI, USA
Offline Offline
Faraday Member
**
Karma: 95
Posts: 4086
CODE is a mass noun and should not be used in the plural or with an indefinite article.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Good deal. One more thing, when posting code, people like to see it between code tags. This is done with the # button when composing the post.

Code:
char msg[] = "So the code ends up in a box like this.";
Logged

MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

Greece
Offline Offline
Full Member
***
Karma: 2
Posts: 172
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you my friend i try to do it now :-)


Code:
#include <avr/sleep.h>

int led = 13;
int wakepin = 2;
boolean flag = false;

unsigned long time,stay = 0;

void wakeupnow(){
flag = true;
}

void setup(){
pinMode(led,OUTPUT);
pinMode(wakepin,INPUT);
digitalWrite(wakepin,HIGH);
attachInterrupt(0,wakeupnow,LOW);
}

void sleepnow(){
while (digitalRead(wakepin) == LOW)
digitalWrite(led,LOW);
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
attachInterrupt(0,wakeupnow,LOW);
sleep_mode();

sleep_disable();
time = millis();
while (digitalRead(wakepin) == LOW)
//delay(1000);
//detachInterrupt(0);
flag = false;
}

void loop(){
if (millis() - time > 1000){
time = millis();
digitalWrite(led,HIGH);
//delay(500);
stay = millis();
}

if  (millis() - stay > 500) digitalWrite(led,LOW);

if (flag == true) {
flag = false;
sleepnow();
}
}
Logged

Pages: [1]   Go Up
Jump to: