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 ?
#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: </mark> <mark>[code]</mark> <mark>
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.
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);
}
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.
@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.
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 ...
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:
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.
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.
tasosstr:
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 ?
Thank you my friends for the help, i thing now it is working .....
#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.