We have just release the 1st revision of our low power library for Arduino. This is a simple and easy to use library that has the following features:
- Supports all sleeping mode of ATmega328P:
- Idle.
- ADC reduction mode.
- Power save.
- Power down.
- Standby.
- Extended standby.
- Selectable sleep duration:
- 15 ms, 30 ms, 60 ms, 120 ms, 250 ms, 500 ms, 1 s, 2 s, 4 s, 8 s, and forever (wake up using other resources) through on chip 125 kHz Watchdog timer. Using sleeping forever duration, the Watchdog timer module is not in use and will further reduce the current consumption by approximately 4 µA.
- Option to shutdown Analog to Digital Converter (ADC) module to further reduce current consumption.
- Option to disable Brownout Detector (BOD) module to further reduce current consumption by approximately 17 µA. BOD module cannot be disabled through software in idle and ADC noise reduction mode. It can only be disabled through fuse setting in these 2 modes.
- Option to shutdown Timer 2 module in idle, ADC noise reduction, power save, and extended standby mode. Timer 2 is used by the core of Arduino for PWM operation.
- Option to shutdown Timer 0, Timer 1, USART0, TWI, and SPI module in idle mode.
We didn’t add any wake up functionality except using the Watchdog timer module to allow certain amount of sleep duration as we think other wake up resources (interrupt on pins, TWI address match, ADC conversion complete, SPI serial transfer complete, EEPROM ready) are closely bind to the external peripheral or interface it is connected to. For example, an external RTC chip with it’s clock output pin connected to pin 2 of the Arduino board. In this case, the library should not know what this external interrupt signal means to the system (timer or counter for time stamping or other usage). Therefore, we omit them out (at least for now). But, rest assured examples are included (more will be added from time to time) to demonstrate the usage of the library with external peripheral and interface.
Please bear in mind that, most of the Arduino boards (official and also compatible) that is currently available in market (except some brilliant design from JeeLabs and Wiblocks, but there might be more out there that we are not aware of) are not low power by design. Low power design requires both hardware and software implementation. Our Mini Ultra 8 MHz (Arduino compatible) board is designed to be low power and is basically the testing platform for this library. Using the library on any Arduino boards (official or compatible) may and may not yield the best result.
Using our Mini Ultra 8 MHz (we are assembling an army of them right now using our reflow oven controller shield) and revision 1.0 of the library yields the following current consumption measurement result. The board is being powered by a Li-Ion 3.7 V battery running at 8 MHz with 3.3 V. The on board regulator of the Mini Ultra 8 MHz consumes about 1.6 µA of quiescent current.
| Mode | WDT | ADC | BOD | T2 | T1 | T0 | SPI | USART0 | TWI | Current |
|---|---|---|---|---|---|---|---|---|---|---|
|
Timer 1 & Timer 2 not in use Timer 2 not clock asynchronously from an external 32.768 kHz crystal (lower consumption can be further achieved) |
||||||||||
| Idle | On | On | On | On | On | On | On | On | On | 3648.0 µA |
| Idle | Off | On | On | On | On | On | On | On | On | 3643.0 µA |
| Idle | Off | Off | On | On | On | On | On | On | On | * |
| Idle | Off | Off | On | Off | On | On | On | On | On | * |
| Idle | Off | Off | On | Off | Off | On | On | On | On | 3618.0 µA |
| Idle | Off | Off | On | Off | Off | Off | On | On | On | 927.0 µA |
| Idle | Off | Off | On | Off | Off | Off | Off | On | On | 832.0 µA |
| Idle | Off | Off | On | Off | Off | Off | Off | Off | On | 789.0 µA |
| Idle | Off | Off | On | Off | Off | Off | Off | Off | Off | 687.0 µA |
| ADC Noise Reduction | On | On | On | On | - | - | - | - | - | 651.0 µA |
| ADC Noise Reduction | Off | On | On | On | - | - | - | - | - | 646.0 µA |
| ADC Noise Reduction | Off | Off | On | On | - | - | - | - | - | * |
| ADC Noise Reduction | Off | Off | On | Off | - | - | - | - | - | 584.0 µA |
| Power Down | Off | Off | Off | - | - | - | - | - | - | 1.7 µA |
| Power Down | Off | Off | On | - | - | - | - | - | - | 18.6 µA |
| Power Down | Off | On | On | - | - | - | - | - | - | 110.0 µA |
| Power Down | On | On | On | - | - | - | - | - | - | 113.9 µA |
| Power Save | Off | Off | Off | Off | - | - | - | - | - | 1.7 µA |
| Power Save | Off | Off | Off | On | - | - | - | - | - | 416.0 µA |
| Power Save | Off | Off | On | On | - | - | - | - | - | 435.0 µA |
| Power Save | Off | On | On | On | - | - | - | - | - | 527.0 µA |
| Power Save | On | On | On | On | - | - | - | - | - | 531.0 µA |
| Standby | Off | Off | Off | - | - | - | - | - | - | 201.7 µA |
| Standby | Off | Off | On | - | - | - | - | - | - | 218.5 µA |
| Standby | Off | On | On | - | - | - | - | - | - | 309.9 µA |
| Standby | On | On | On | - | - | - | - | - | - | 313.9 µA |
| Extended Standby | Off | Off | Off | Off | - | - | - | - | - | 202.2 µA |
| Extended Standby | Off | Off | Off | On | - | - | - | - | - | 416.0 µA |
| Extended Standby | Off | Off | On | On | - | - | - | - | - | 436.0 µA |
| Extended Standby | Off | On | On | On | - | - | - | - | - | 527.0 µA |
| Extended Standby | On | On | On | On | - | - | - | - | - | 531.0 µA |
In idle mode, the IO clock is available for general IO modules usage. Therefore, you need to pull any unused pins low in output mode to reduce the overall current consumption.
In power save mode, Timer 2 can be clocked asynchronously from an external 32.768 kHz crystal to achieve very low current consumption. However, this will require the removal of the external 8 MHz resonator (or crystal in other board variants) to facilitate the low frequency crystal. This will require the ATmega328 to run on its internal 8 MHz on chip RC oscillator in normal operation. But, this will affect time critical modules such as millis, PWM and higher baud rate USART communication as the accuracy of the on chip RC oscillator is limited and is affected pretty much by the operating voltage and temperature. We have some prototype work on running a 32.768 kHz crystal asynchronously which can be seen here.
Here’s a sample code snapshot on how to use the library.
#include "LowPower.h"
void setup()
{
// No setup is required for this library
}
void loop()
{
// Sleep for 8 s with ADC module and BOD module off
LowPower.powerDown(SLEEP_8S, ADC_CONTROL_OFF, BOD_OFF);
// Do something here
// Example: read sensor, log data, transmit data
}
The library is available on our GitHub repository. Comments and opinions are greatly appreciated! We hope you find this library useful for your application. Take care and happy tinkering.
Is there a way to measure current consumption in software? Or do I need an external ammeter?
Hi Mike,
You can actually use another microcontroller to measure a voltage drop across a very small resistor placed at the input of the board. But it basically has to be a differential measurement ADC. Then, you can calculate the current and push into a PC or something similar. We use 2 meter in our case, one to measure the current and 1 to monitor the input voltage.
Pingback: Low power libraries for Arduino – Control sleep with single function calls | EngBlaze
Hello,
I would like to put the Arduino to sleep with the command
LowPower.powerDown(SLEEP_8S, ADC_CONTROL_OFF, BOD_OFF);
However, I found out that since I have a sensor (TSL230) using an interrupt
the Arduino doesn’t go to sleep.
Is there a way to bypass the interrupt for sleeping?
Thanks for this useful library.
Frederic,
If I understand the TSL230 correctly, you wanted to use the TSL230 OUT pin to wake the Arduino? In that case instead of using SLEEP_8S as the argument, use SLEEP_FOREVER instead and configure the attachInterrupt on either pin 2 or 3 to wake the Arduino up.
In fact I am using the interrupt for reading frequency of the sensor. I would like to put the Arduino to sleep only with the timer SLEEP_8S; but when an interrupt occurs from the sensor (many time each second depending on lighting condition)the Arduino wakes-up (I tried both pin 2 and 3).
Is there a way to power down the Arduino only with timer 2 despite the interrupt being used?
The interrupt will definitely wake the Arduino up if the interrupt occurs within that 8s. But, you can go back to sleep after that interrupt happens in this case. If you can use a pin to indicate the sleep & awake sequence, you’ll probably be able to see the sleep & wake up sequence few times within a period of time. Timer 2 can be clocked asynchronously if driven by a low speed crystal attached to the oscillator pins in power save mode. But, that is totally a different thing. In power down mode, all clock to timer are disabled except the WDT.
Can someone draft a sample code that would put the device to sleep with a timer running for 15 minutes on low power but could also be woken up by an interrupt on pin 2 high (ie, external power is attached). why doesn’t the below work?
// **** INCLUDES *****
#include “LowPower.h”
// Use pin 2 as wake up pin
const int wakeUpPin = 2;
void wakeUp()
{
// Just a handler for the pin interrupt.
}
void setup()
{
// Configure wake up pin as input.
// This will consumes few uA of current.
pinMode(wakeUpPin, INPUT);
}
void loop()
{
// Allow wake up pin to trigger interrupt on low.
attachInterrupt(0, wakeUp, LOW);
// Enter power down state with ADC and BOD module disabled.
// Wake up when wake up pin is low.
LowPower.powerDown(SLEEP_900S, ADC_OFF, BOD_OFF);
// Disable external pin interrupt on wake up pin.
detachInterrupt(0);
// Do something here
// Example: Read sensor, data logging, data transmission.
}
Jory,
The maximum period you can insert is SLEEP_8S using the watchdog timer.
If you need to do something after 15 minutes periodically, you can use SLEEP_4S and wake up 225 times before executing the task you have in hand. The awake time to increment a counter (and check whether it is the 225′s time) will take pretty little time to execute.
Makes sense. If I need to use the 2 interrupts and the timer for the 4S what is the best option for saving power?
Also, do I need to detach the interrupts afterwards while I execute other functions during normal use? If so, (due to volitility) what is my best option for always being able to utilize the interrupts at any time?
Thanks
I’m getting an error using the library that BODS was not declared in the scope even though the h and cpp files are in the sketch folder.
Here is the code that I’m using in my sketch:
//int i is for loop decrement to have a 15 minute sleep (many 8 second sleeps) and if there is an interrupt then instead of decrementing the loop I want it to end the sleep cycling.
void wakeUp() //place to send the interrupts
{
int i=0;
}
void sleep()
{
// Allow wake up pins to trigger interrupt on change.
attachInterrupt(0, wakeUp, CHANGE); //Interrupt on pin 2 for any change in power plug
attachInterrupt(1, wakeUp, CHANGE); //Interrupt on pin 3 for any change in solar power
// Enter power down state with ADC and BOD module disabled.
// Wake up when wake up interrupts are triggered.
LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
detachInterrupt(0);
detachInterrupt(1);
}
Jory,
Can you try installing the library in the Arduino library folder instead?
I am getting this same error when trying to use the library, it is in the correct location but it seems like a variable isn’t declared or something in the .cpp file. Also is this compatible with a mega2560?
If you are trying to compile them to work for either 32U4 or Mega2560, the library is yet to support both of that chip. But, we will support them in the future. We need some low power board to test them.
http://i.imgur.com/CGYAI.png
It is already in the arduino folder as well as the sketch folder
is there any way I can send you an email and I can send you the code i’m trying to run so you so can test it with your library. (using arduino 1.0 newest build) and a sparkfun pro micro leonardo microprocessor – http://www.sparkfun.com/products/10998
Does the UNO fully support this library? I tried it with (as I recall) success with a Duemilanove and saw a significant reduction in power consumption. Now I’m using an UNO but never using less than about 20 mA with LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);. Nothing more than a bare Arduino and code that switches back and forth between power off 8s and delay(8000). I seem to recall better results with the 2009. Any thoughts, or am I missing something major? Thanks.
It shouldn’t be any different actually. The only different I can from the Uno point of view is the bootloader (upload speed, Optiboot smaller boot size). But, I didn’t actually try on an bare Uno yet. Some guys tested it to work with the Pro Mini with Optiboot bootloader and it works fine. Maybe you can a look at the fuses as a start?
I am wondering if this library supports ATMega8 chips?
Ron,
Haven’t check it’s compatibility on other processor other than ATMega328P. Currently looking for Mega2560 & Mega32U4 boards that I can convert into low power boards and expand the library supported devices.
Pingback: 17ο Επεισόδιο | The Beta Show
Hello,
using your library are causing Errors.
///MyCode///
#include “LowPower.h”
void setup()
{
// No setup is required for this library
}
void loop()
{
// Sleep for 8 s with ADC module and BOD module off
LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
// Do something here
// Example: read sensor, log data, transmit data
}
///MyCode///
Errors:
LowPower.cpp: In member function ‘void LowPowerClass::powerDown(period_t, adc_t, bod_t)’:
LowPower.cpp:298: error: ‘BODS’ was not declared in this scope
LowPower.cpp:298: error: ‘BODSE’ was not declared in this scope
LowPower.cpp: In member function ‘void LowPowerClass::powerSave(period_t, adc_t, bod_t, timer2_t)’:
LowPower.cpp:379: error: ‘BODS’ was not declared in this scope
LowPower.cpp:379: error: ‘BODSE’ was not declared in this scope
LowPower.cpp: In member function ‘void LowPowerClass::powerStandby(period_t, adc_t, bod_t)’:
LowPower.cpp:439: error: ‘BODS’ was not declared in this scope
LowPower.cpp:439: error: ‘BODSE’ was not declared in this scope
LowPower.cpp: In member function ‘void LowPowerClass::powerExtStandby(period_t, adc_t, bod_t, timer2_t)’:
LowPower.cpp:512: error: ‘BODS’ was not declared in this scope
LowPower.cpp:512: error: ‘BODSE’ was not declared in this scope
Where is the problem?
Hi Peter,
I believe your are trying to compile for Mega2560 or a Mega32U4?
Both of the chip’s BOD cannot be controlled through software. So, they lacked of the BODS register & BODSE control bit. I’m currently working to support that 2 MCU. You need a fast workaround, drop us a mail from the website.
I’am using Arduino 0023 and Arduino FIO board. I always getting this error
powerDownWakePeriodic.cpp:2:22: error: LowPower.h: No such file or directory
powerDownWakePeriodic.cpp: In function ‘void loop()’:
powerDownWakePeriodic:11: error: ‘LowPower’ was not declared in this scope
powerDownWakePeriodic:11: error: ‘SLEEP_8S’ was not declared in this scope
powerDownWakePeriodic:11: error: ‘ADC_OFF’ was not declared in this scope
powerDownWakePeriodic:11: error: ‘BOD_OFF’ was not declared in this scope
The library is already put in Arduino libraries folder
Thanks
Did you rename the downloaded library (removing characters appended by GitHub) accordingly to “LowPower”?
If the example is accessible from the IDE, the library should be there as well.
Hi,
I try to use your library with a atmega168. After some errors I realised, that the BODS is not supported by that chip.
Is there a way to use your library anyway?
Regards
Sebastian
Hi Sebastian,
Yes, the BODS register is only available on Pico Power devices. If need help for that, drop us a mail. We have a subsequent beta version.
Hey guys, Thanks for releasing the library. It works great and it’s very easy to learn. Currently using it with a standalone ATMega328p running on a couple AA’s.
Pingback: Moteino coin cell battery tests | LowPowerLab
Pingback: Smartmeter pulse counter (4) | Tinkerman
I’ve been successfully using the LowPower library on an Arduino Duemilanove with an ATMega328P. Having switched to the low power Olimexino-32U4, based around Leonardo architecture, the 32U4 will not support software BODS control (see above). Do you have a workaround/beta?
Hi Toby,
Check your inbox!
i’m currently working with an arduino leonardo and xbee and i’m trying to put the system to sleep. is it possible that you could also send me the beta/workaround, please. i didn’t find an update of the library on github yet.
Thanks in advance!
Christian
Christian,
Drop us a mail for beta of next version!
I’m also looking for the low power library for the arduino Leonardo, could you also send me the workaround.
Thanks in advance!
sincerely,
Jesse
Hi Lzyun,
Check your mail box.
Hello! I am currently working with an Arduino Mega 2560. Does the beta support that chip? I would appreciate a beta version, if possible. If not, I have to start from scratch and I really need a low power consumption library. Thank you very much
Hi Will,
Check your mailbox.
Heck, sorry.. I missed this, I just commented out the BODS stuff and it worked fine. The Leonardo boards were switched out for Xino boards in the end. Thanks, T
Pingback: Counting people | MontoyaLabs
Pingback: Time is running out…. | Decibear
May I also request support for the Atmega2560, or any beta code that you have developed for it so far? I would find great use for it! Can also report back on whether or not it works with the Mega.
Thanks!
Anders
Anders,
Check your mail!
Hi, im also working with arduino leonardo and i would like you to sende me some library or a test sketch try it, i was looking a lot on internet and this is the best post, but dont support leonardo, give me a hand xD
i wait ur answer
Alejandro,
Please check your mail.
Pingback: Project bibliography and reference | Decibear
Hi, can I use this lib with attiny45?
I haven’t actually try it out or look at the registers of Attiny45. There could be quite a number of peripheral not on the Attiny series. Expect some compilation error due to that.
Hi,
I would like to apply this to an open source GPS tracker (http://dsscircuits.com/geogram-one.html)
Could someone help me out with this.
The shipped sketch is using the millis timer to send the GPS and GSM module to sleep (not the MCU) but it consumes too much power for what I would like to use it for (Long term tracking, say 6+ months, with a 6000mAh battery).
If I could get the Arduino chip to sleep also, that would make this device so much better!
Thanks
You need another wake-up source other than millis(). Depending on your required timing accuracy, the built-in watch-dog timer (although will drift a little across temperature) could be enough. Other than that, an external RTC can also be used to wake the processor up.
ok, thanks. Is there any way to “sync” with the GPS time to keep the timer drift to a minimum?
If I understand correctly, the watchdog timer sleeps the device after it has completed one loop of the code for upto 8 seconds, then completes another loop, sleeps for 8 seconds and so on. Is that correct?
Hey,
I’m playing with the ATMega32u4. Could I get a copy of the beta library that supports it?
I’ve tested with the Uno and the ATMega328P and it works great!
Colby,
Check your mail!
Hi,
Thanks for the nice product (Mini Ultra+) and the low-power library. Being new to sleep modes and energy optimization with MCUs, I could not figure out how to make the software RTC (RTClib in my case) to work with the sleep mode, is it just impossible or do I always need a hardware RTC (like DS1307)?
My example code is like that:
#include
#include “RTClib.h” // https://github.com/adafruit/RTClib
#include // https://github.com/rocketscream/Low-Power
RTC_Millis RTC;
void setup(void){
Serial.begin(115200);
Wire.begin();
// following line sets the RTC to the date & time this sketch was compiled
RTC.begin(DateTime(__DATE__, __TIME__));
}
void loop(){
// Sleep for x s with ADC module and BOD module off
// other options, see LowPower.cpp, e.g. 15 ms to FOREVER
LowPower.powerDown(SLEEP_1S, ADC_OFF, BOD_OFF); // ADC_CONTROL_OFF -> ADC_OFF
// Get the time using the “software RTC”
DateTime now = RTC.now();
// Print on the Serial Monitor / Console the time (debugging)
Serial.print(now.year(), DEC);
Serial.print(‘/’);
Serial.print(now.month(), DEC);
Serial.print(‘/’);
Serial.print(now.day(), DEC);
Serial.print(‘ ‘);
Serial.print(now.hour(), DEC);
Serial.print(‘:’);
Serial.print(now.minute(), DEC);
Serial.print(‘:’);
Serial.print(now.second(), DEC);
Serial.println();
// Integer that could be saved to the EEPROM
// Could be then converted to human-readable format when reading
// in the data in Python, Matlab, Java, whatever
Serial.print(” seconds since 1970: “);
Serial.println(now.unixtime());
delay(10);
}
And the output on Serial Monitor like that (the time increment in “real-world time” is now 1 second)
2013/4/18 12:52:25
seconds since 1970: 1366289545
2013/4/18 12:52:25
seconds since 1970: 1366289545
2013/4/18 12:52:25
seconds since 1970: 1366289545
2013/4/18 12:52:25
seconds since 1970: 1366289545
Thanks,
P
The millis() requires the IO clock to drive the Timer 0. During sleep, it is not available.
Another more accurate way of doing this is using an external 32.768 kHz crystal (but the processor has to run off the internal 8 MHz) to drive Timer 2 asynchronously during power save mode. Simpler method, would be using the external RTC like what you mentioned above.
Hi, nice library and it works perfect.
I have a question – is it possbile to wake up the arduiono by for example a key press?
Or does that has to happen when the sleep of 8 seconds is done?
Joakim
You could attach external interrupt (key press) and then power down (SLEEP_FOREVER). It will wake up upon the key press.
Ah ok – but I do want my arduino to check some status from time to time and then go to sleep to save my batteries. But if the user pushes a button I would like the arduino to do some stuff and then get back to sleep and start checking when it wakes from the sleep period. This is not possible is it?
Joakim
You can do that. By pushing it to power down mode with the sleep interval you desire. At the same time, attach the external interrupt.
In this case, your board could wake up on either of the source. To check the wake up source, use a semaphore flag in your external interrupt handler function and check it upon waking up.