You can follow the interrupted sleep tutorial by NoMi Design to learn just how to set things up.
My code, however, is just like this example, provided on Engblaze.com, except that Ive added some serial communications to see that its working visually and to re-enable the interrupt attach so that I can constantly bring the device out of sleep every time it goes to sleep.
//remove the space between '<' and 'avr'. #include < avr/interrupt.h> #include < avr/power.h> #include < avr/sleep.h> #include < avr/io.h> void setup() { Serial.begin(9600); DDRD &= B00000011; // set Arduino pins 2 to 7 as inputs, leaves 0 & 1 (RX & TX) as is DDRB = B00000000; // set pins 8 to 13 as inputs PORTD |= B11111100; // enable pullups on pins 2 to 7 PORTB |= B11111111; // enable pullups on pins 8 to 13 pinMode(13,OUTPUT); // set pin 13 as an output so we can use LED to monitor digitalWrite(13,HIGH); // turn pin 13 LED on } void loop() { // Stay awake for 1 second, then sleep. // LED turns off when sleeping, then back on upon wake. delay(2000); Serial.println("Entering Sleep Mode"); sleepNow(); Serial.println(" "); Serial.println("I am now Awake"); } // void sleepNow() { // Choose our preferred sleep mode: set_sleep_mode(SLEEP_MODE_PWR_SAVE); // interrupts(); // Set pin 2 as interrupt and attach handler: attachInterrupt(0, pinInterrupt, HIGH); //delay(100); // // Set sleep enable (SE) bit: sleep_enable(); // // Put the device to sleep: digitalWrite(13,LOW); // turn LED off to indicate sleep sleep_mode(); // // Upon waking up, sketch continues from this point. sleep_disable(); digitalWrite(13,HIGH); // turn LED on to indicate awake } void pinInterrupt() { detachInterrupt(0); attachInterrupt(0, pinInterrupt, HIGH); }
Dont mind any avr's at the end. Its a glitch the website keeps doing when I post #includes at the top of the code on the blog.
Sleep Modes
Finally, its important to discuss the types of Sleep Modes that you can choose from. There are 6 sleep modes available on the Arduino Uno (ATMEGA328):- SLEEP_MODE_IDLE – least power savings
- SLEEP_MODE_ADC
- SLEEP_MODE_EXTENDED_STANDBY
- SLEEP_MODE_PWR_SAVE
- SLEEP_MODE_STANDBY
- SLEEP_MODE_PWR_DOWN – most power savings
Ive decided to go with SLEEP_MODE_PWR_SAVE for this example, just because it gives me some flexibility with waking it, and because the power savings are a bit better than idle. Power down is overkill for my applications, and its comparative to actually turning off the device, which I don't need my hardware to do.
You're welcome to ask questions, about this code if you arent sure whats going on. The bit of setting up the pins in the Arduino hardware is explained more on the Engblaze post.
VERY Interesting! However in both Arduino 0023 and 1.01 I get this error when pasting this code:
ReplyDelete---------------------( COPY )----------------------
sketch_oct11a.cpp:1:41: error: C:\Users\TerryKing\Desktop\ArduinoDev\arduino-1.0.1\hardware\arduino\cores\arduino/avr interrupt.h="interrupt.h": Invalid argument
-----------------( END COPY )----------------------
Am I missing some library??
Thanks!
Regards, Terry King
...In The Woods in Vermont, USA
terry@yourduino.com
It should be ' #include < avr/interrupt.h' > without quotes and spaces. Blogger reformatted how the code was supposed to display. I've fixed it now.
DeleteYou can give this a try instead:
ReplyDelete#include < avr/interrupt.h>
#include < avr/power.h>
#include < avr/sleep.h>
#include < avr/io.h>
with no space between < and avr.
I know for sure that those work in my code. Let me know how it goes. If so, I'll update the code above to reflect this edit.
I dont get the setting of the pins as input or outputs and pull-ups. Im trying to get a FIO based app as energy efficient as possible.
ReplyDeleteBesides pins, I do:
-power down sleep
-ADC disable
-AC disable
-BOD disable
This gets me down to 108 uA, of which I assume the majority to be 'unsaveable' due to it being used by the voltage regulator (~100uA).
When I add in your pin code (copy paste, input and pull-up), it goes up to 155 uA while sleeping. So I dont see how this is saving power, and different sources seem to disagree on the web. Any explanation?
PS: only FIO board being used, no peripherals/sensors/XBEE. 9V battery powered
It could be because you are using a 9V battery. Try using a 3.3V Li-Ion battery and then let me know. It could also be the use of The PWR SAVE mode. Try PWR DOWN to see if you save more power.
ReplyDeleteSeems there was a problem with pin 13. Although I did put it as input, the pull-up seems to make the LED draw a tiny amount of current, even making it glow, albeit very dim.
DeleteAnyway, after I tested again (already used power down sleep), and now results are there isnt any difference between all 4 combinations (in/out and high/low).
The 9V battery is only used in development/testing. For the real deal Ill be switching to 40AH 6V battery. The device must last several years at a calculated avg current of 1 mA....I also have no LIPO at my disposal atm.
For now Ill keep the code in, perhaps I havent been in situations where the difference is more profound...currently at a stable 105 uA sleep power. Thanks anyways!
Sorry I couldnt help with your project. Perhaps you can share what you did in your code and maybe I can see whats going on? Do you necessarily need the Fio? There are plenty of other uC's out there that are way less power hungry than the Atmega32u4 on the Fio.
Deletehi may I have the library for avr/interrupt, avr/power, avr/sleep, avr/io because I could not find the link to download it from the web. if its possible could you zip the file? thank you and sorry for the trouble.
ReplyDeleteThey are libraries that come with the Arduino software. Download the latest version of Arduino from www.arduino.cc and you will have them.
DeleteHi I understand it already thank you so much! However I am getting error when verifying. Is it that the function cannot work with the arduino version that I have? Below is the error that I get.
ReplyDeletesleepmode.ino: In function 'void sleepNow()':
sleepmode:32: error: 'SLEEP_MODE_PWR_SAVE' was not declared in this scope
sleepmode:32: error: 'set_sleep_mode' was not declared in this scope
sleepmode:40: error: 'sleep_enable' was not declared in this scope
sleepmode:44: error: 'sleep_mode' was not declared in this scope
sleepmode:47: error: 'sleep_disable' was not declared in this scope
Hi for the error that I ask you earlier on I solved it. So sorry to trouble you cause I forgotten to //remove the space between '<' and 'avr'.
ReplyDeleteHi Tamir, thanks for the very useful tutorial!
ReplyDeleteI've experienced an issue with the Serial.print before sleepNow(); and just figured out, it had no time to transfer the text. You might consider to give it a delay(30) before executing sleepNow(); just in order to properly Serial.print the text of choice.
.
.
.
Serial.println("Entering Sleep Mode");
delay(30);
sleepNow();
.
.
.
Interesting input on the delay bit. I hadnt thought of that. Thanks for sharing!
DeleteAre you using the Arduino Due? Because I couldn't get this to work for me. The documentation says you can't set an interrupt for HIGH as you have, except for in the Due. It has to be RISING or CHANGED. Then when you do that, the only power mode you can sleep in is IDLE, not PWRSAVE.
ReplyDeleteAs the post says, its anything with an Atmega 168/328p. I was using a Fio. I know this example works, because I used it many times. I dont post example code unless Ive tried it and used it in my projects.
DeleteAlso, which documentation are you referring to? You should use the chip manufacturer's manuals not Arduino.
DeleteJust a question, if the Arduino uses bluetooth as a serial connection, and I set the Arduino to sleep, will it still provide enough power to the Bluetooth to wake it up via serial?
ReplyDeleteIt should. I was able to successfully wake the Arduino from sleep using XBee commands, so I would think that Bluetooth is similar enough to work.
DeleteThe whole purpose of sleep mode is to conserve power. But if you program to wake on serial, then it will sleep as long as there is no serial communication. I would approach your coding as the following: Once the wireless device receives the signal to wake, it will wake the Arduino...do whatever it needs to do, transmit again, and then sleep again.
Hope this helps!