Usually in a project when we are using battery we need to use some techniques to save power, no one wants to change the battery every week.
The best way to save power is removing some components, like the regulator and the power led. And of course, put the microcontroller in deep sleep.
Atmega328p
Most of the Arduino boards were based on the microcontroller Atmega328p, if you check the datasheet of this chip on Power Consumption…
Power Consumption at 1MHz, 1.8V, 25°C - Active Mode: 0.2mA - Power-down Mode: 0.1μA - Power-save Mode: 0.75μA (Including 32kHz RTC)
Power-down mode looks really good, let’s try some codes… I’m using LowPower library to make everything easier.
#include "LowPower.h" void setup() { } void loop() { LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); }
I upload this code on the Arduino Pro Mini with no regulator and led, power with two AA batteries (~2.57 Volts), measure the current and a got around ~0.1uA.
But this code has a problem, the microcontroller will sleep forever and never wake up… I can use an external interrupt to wake up the microcontroller or use an internal watchdog to does the job.
Let’s try an internal watchdog first, with the code above.
#include "LowPower.h" void setup() { } void loop() { LowPower.powerDown(SLEEP_1S, ADC_OFF, BOD_OFF); }
The watchdog was setting to waking up every one second, is not a 1 second perfect but is good enough. It’s possible to change to other values, check the LowPower library. And when the watchdog is on the sleep current goes around ~3.9uA.
So it’s possible to make a code to wakes up every minute, or more without using any external component.
Now let’s try an external interrupt, and use a push button to wake up the microcontroller, the code above does the business, every time I press the button the LED toggle and goes to sleep forever.
#include "LowPower.h" const int wakeUpPin = 3; void wakeUp() { } void setup() { pinMode(LED_BUILTIN, OUTPUT); pinMode(wakeUpPin, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(wakeUpPin), wakeUp, FALLING); } void loop() { LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); }
Upload the code, the result is like this.
Conclusion
Basically, we have 2 options, use an external interrupt or the internal watchdog.
It depends on your project, but usually is a good idea to send data periodically, so the watchdog is a great solution, but drain ~4uA on sleep mode. Using two good AA battery the node gonna survive for a long time.
Remember you need to burn the BOD fuse, to go below 2.7V. Check the last post!
See you next time!
Reference:
Datasheet ATmega328p: ATmega328-328P_Datasheet.pdf
Power saving techniques for microprocessors: http://www.gammon.com.au/power
LowPower Arduino library: https://github.com/rocketscream/Low-Power/