57
\$\begingroup\$

Scenario

I have created a nice electronic door lock for my dorm room. It is currently an Arduino Diecimila with a servo [un]locking the door. It has a numerical keypad with 3x4 buttons and 5 LED's (2 serie pairs and one single LED). It also currently runs on a cellphone charger.

I have now redesigned it to run on a standalone Arduino (ATmega328), but would really like to have it run on AA batteries or even a 9V battery.

For the software part, I figured I could put sleep calls for certain times inside the loop method to keep the ATmega power consumption as low as possible. And let the LED's "flash" with as long as possible time off.

Question 1

When a button is pressed during the few milliseconds which the board sleeps, will it be "remembered"/"held" until it comes out of sleep and then be picked up as a button press?

What would be the best way to handle this button press on sleep? Can I code it to wake up upon button activity, or must I just let it sleep for e.g. 10m.s. in every loop?

Question 2

How would I approach the math of calculating how many AA batteries are needed to run this device for 10 months?

Also, I don't know how to measure the average power usage per minute or so, since it alternates quickly etc.

The Device

My door lock device

\$\endgroup\$

7 Answers 7

39
\$\begingroup\$

The Atmega328 provides six power saving modes, ordered from minimal to excellent (estimated current consumptions from this forum post):

  • SLEEP_MODE_IDLE: 15 mA
  • SLEEP_MODE_ADC: 6.5 mA
  • SLEEP_MODE_PWR_SAVE: 1.62 mA
  • SLEEP_MODE_EXT_STANDBY: 1.62 mA
  • SLEEP_MODE_STANDBY : 0.84 mA
  • SLEEP_MODE_PWR_DOWN : 0.36 mA

Quoting the original question:

I figured I could put sleep calls for certain times inside the loop method"

You would need to use sleep_cpu() after setting up the sleep mode you require, from the list above. The Arduino Playground has a useful post about this.

The application needs to be interrupt driven, use the above sleep modes extensively, and wake the processor up on button push, timer overflow and watchdog timer events to actually execute tasks.

Additional power savings can be obtained through the following steps:

  • Use the microcontroller's internal oscillator and a low clock rate (8MHz instead of 16) - but ensure that time and timing related code still works as expected. A different version of the bootloader might be needed for this.
  • Avoid keeping LEDs on for long if the application uses them. Using a rapid double or triple flash of short duration (0.05 second on, 0.5 second off), with gaps of seconds in between, ensures noticeable indication with minimal power consumption
  • Use a switching regulator instead of a linear one, if a regulator is required.
  • Run the microcontroller at lower voltage if supported, 3.0 Volts (e.g. CR2032 Lithium cell, no regulator needed) or 3.3 Volts instead of 5 Volts.
  • Follow recommendations in the datasheet for unused input and output pin settings for minimum power wastage.

Incorporating these suggestions allows for running microcontroller applications for weeks or months on a single CR2032 coin cell, and years on a LR123 type lithium cell. Of course, your mileage may vary depending on what sensors, outputs and actual processing your application requires.

Some useful references:

\$\endgroup\$
5
  • 2
    \$\begingroup\$ With my experience, in SLEEP_MODE_PWR_DOWN you can take it down to 0.1uA to 6.0uA if you've been smart about turning every little thing off (like brown-out detection). I've created builds that use less than 60uA which last 3-5 years on a set of alkaline AA batteries. \$\endgroup\$
    – Tim Eckel
    Commented Apr 18, 2013 at 14:45
  • \$\begingroup\$ @TimEckel I'm crazy about indicating status with LEDs - that eats power budget like it was going out of style. \$\endgroup\$ Commented Apr 18, 2013 at 14:59
  • 4
    \$\begingroup\$ It doesn't have to. Use high powered LEDs with high resistance. Will use a fraction of a mA instead of over 20 mA. Also, flash the status LED for 5-15 ms every few seconds instead of constantly on. I had a cheap dim status LED that used 30 mA, I changed it to high powered LED with a 3.3k Ohm resistor which I flashed for 15 ms once every 8 seconds. Went from 30 mA to 2.9 uA of average current, 1/1000 of the power! \$\endgroup\$
    – Tim Eckel
    Commented Apr 18, 2013 at 20:13
  • 4
    \$\begingroup\$ @TimEckel You clearly don't understand the extent of my passion for blinky lights :-D It's not as though I want to reduce intensity, I like those little things glittering like the flames of Hades, power budget be darned! On a more serious note: I'm aware of those little tricks, and in fact have fashioned a few of my own, which increase visual alarm impact while reducing power through the LEDs. That previous comment was (only partly) in jest, to go with the many fun LED questions I answer around here. \$\endgroup\$ Commented Apr 18, 2013 at 20:22
  • 4
    \$\begingroup\$ I measured power consumption of ATMega328P at different voltages and frequencies and made this chart docs.google.com/spreadsheets/d/… \$\endgroup\$
    – Cano64
    Commented Feb 23, 2016 at 16:07
21
\$\begingroup\$

I have an Arduino Pro Mini on my desk right now that is running off 2 AA batteries and could run for over a year if required.

There are three aspects of the design that have achieved this.

1. A different regulator

I'm using a LTC3525 boost regulator. It has very low quiescent current (7uA) and high efficiency (>90% @ 0.2mA). Something like this sparkfun board https://www.sparkfun.com/products/8999 should do a similar job. Make sure to connect it to the 5V pin on the Arduino, not VIN, so that the Arduino regulator is not used.

2. Sleeeeeeep

The proportion of time the device is active will be small. For the rest of the time the device should be asleep in SLEEP_MODE_POWER_DOWN. You can base your sleep routines off the Rocketscreem Low Power Library. According to that link you should be able to get it down to 1.7uA with ADC, BOD and WDT off and in power down mode.

3. Interrupts

The other half of sleep is interrupts to wake it up. In Power Down sleep mode, only level interrupts on INT1 and INT2, TWI match, and the WDT will wake it up. So you need to have a button connected to either INT1 or INT2 so that pressing the button will wake it up.

Other stuff:

Turn off all LEDs unless absolutely necessary. If the lock is indoors the LEDs do not have to be bright, saving more power. Also if you do need to have the MCU performing some task regularly, use the watchdog timer to periodically wake it up.

Edit:

One method that may work is to use the Low Power library above, and sleep for say 60ms every loop thanks to the watchdog timer. On wake up check for button press. The function to call would be

LowPower.powerDown(SLEEP_60MS, ADC_CONTROL_OFF, BOD_OFF);
\$\endgroup\$
15
\$\begingroup\$

All of these comments are spot on. I would like to add a few more suggestions:

1) For LEDs, use high output 20 mA LEDs. Here's the logic. Lets say you want a dim status LED that blinks every 8 seconds. You don't want it to be bright, so you use some random LED. The problem is, a dim LED still uses 20 mA (or more) to output only 100 mcd. Instead, get a high output LED that's still rated for 20 mA but can output 4000 mcd (make sure you look at the output angle, you still probably want it to be 30 degrees or more). With this 4000 mcd LED, you connect it with something like a 3.3 k Ohm resistor and you get around 100 mcd of light output, but are using less than 1 mA. So, instead of using 20 mA for the status LED, you're using a fraction of a single mA. I also typically set the status LED flash on time for only 5-15 ms, which can also save a lot of power if you previously had the flash on time at 100 ms.

2) My voltage regulator of choice is the Microchip MCP1700. It uses only 1.6 µA of quiescent current and is super cheap (around $0.30 in small quantities). It's only limitation is that the maximum input voltage is only 6 volts, so you can't use a 9 volt battery. But, it's perfect for 4 AA batteries, a single cell LiPo or two lithium coin cells.

3) For powering an ATmega circuit with 4 AA batteries, I typically use a 1N4001 diode on VCC to drop the maximum 6 volts of the 4 batteries to 5.5 volts. Also, the diode protects the ATmega from reverse voltage, so it serves two useful purposes. Doing this, I can create a battery powered circuit that can use as little as 0.1 µA while sleeping as there's no voltage regulator eating up current all the time.

\$\endgroup\$
8
\$\begingroup\$

I did a test on a bare atmega328P-PU on a breadboard using RocketScream LowPower library

Used this sketch:

#include "LowPower.h"

void setup(){}

void loop()
{
    LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);         
    delay(5000);
}

With a uCurrent Gold I measured 7.25 uA when in power down mode.

\$\endgroup\$
1
  • 2
    \$\begingroup\$ Nice! I'll try this as soon as possible. Does this allow to run an atmega238 for years with a CR2032 battery? \$\endgroup\$
    – Basj
    Commented Sep 22, 2017 at 20:30
5
\$\begingroup\$

There are two questions here, but only the second one is really part of the question title, so it's probably better if you open another one for the Arduino programming question. I'll answer the second question here.

A single top-end alkaline 1.5V AA battery has a capacity of about 2600mAh. If you go for lithium batteries, you can get about 3400mAh if you're lucky. Let's go with that figure as a baseline for absolute best-case.

The way you calculate theoretical maximum running time for a load is simply capacity divided by load. If your load is 1mA, you can run it for 3400 / 1 = 3400 hours = 141 days = ~5 months. However, this is only a theoretical maximum, since you'll start to get significant voltage drooping around 65% into that time. If you're regulating the output, you'll get a runaway effect where the lower the battery voltage, the higher current needed to maintain regulated voltage, which drains the battery faster. I'd be surprised if you can get more than 80% of the advertised capacity out of it with a voltage high enough to run your device.

So, let's say that you get 80% of that time after voltage drooping and regulator inefficiencies. We'll assume that you're running at 3.3V from three batteries in series. This will still give you the same capacity, but the voltage will be enough for a regulator. If your device runs at 15mA (that's a rather conservative estimate) the numbers will look like this:

  • Capacity after 80% efficiency = 3400 * 0.8 = 2720mAh
  • Time = 2720 / 15 = 181 hours = 7.54 days

So you'd need about 144 lithium batteries (48 sets of 3) to run it for a year. Not so good!

I'd suggest using a regulated DC supply from the mains instead. A battery backup can be included, which is easy to set up with an SPDT relay - just hook up the coil to the mains DC and have the "off" contact connected to the battery. When the DC fails, the contact drops and the battery is used instead.

\$\endgroup\$
7
  • \$\begingroup\$ My cordless dreams are crushed ;) Thanks for the detailed answer. This seemed to the best option to me as well. \$\endgroup\$
    – Pangolin
    Commented Nov 19, 2012 at 8:18
  • 1
    \$\begingroup\$ Coincidentally, this was the same question I posed to myself when designing an electronic door lock. Even with a chunky 10,000mAh rechargeable battery it wasn't worth it. Ended up just using a 250mA DC adapter and an old mobile phone battery as a backup. \$\endgroup\$
    – Polynomial
    Commented Nov 19, 2012 at 8:38
  • 6
    \$\begingroup\$ 15 mA average doesn't sound very conservative to me! The 328 can run at single-digit microamps in sleep mode, and surely you could get away with having it in at least semi-deep sleep a lot of the time. Also, at low frequencies (e.g. 0.5 MHz) you can get by with <1 mA in active mode. Of course, other components (voltage regulators etc.) need to be picked to suit the low-power nature. \$\endgroup\$
    – exscape
    Commented Nov 19, 2012 at 9:05
  • 6
    \$\begingroup\$ @Polynomial I didn't look closely at the schematic, but surely the project could be build without a "power LED". Or you could blink it, so that it's on e.g. at half brightness (via PWM), only for say 25 ms every 2 seconds, such that the current use would drop to an average of ~0.09 mA instead of 15. \$\endgroup\$
    – exscape
    Commented Nov 19, 2012 at 9:25
  • 3
    \$\begingroup\$ Arduino is power hungry. Building your own board would solve this. Atmega328 draws 0.2 mA when 32kH and 0.75 uA at power save mode. \$\endgroup\$
    – Vorac
    Commented Nov 21, 2012 at 11:33
5
\$\begingroup\$

Something no one has mentioned yet: You need to have some way to turn off the +5V supply powering the servo, when you're not using it. Even when it's not moving, a servo will still draw power.

A FET with the gate controlled by an I/O pin from the arduino is a good way to do that.

\$\endgroup\$
2
  • \$\begingroup\$ I typically use a 2N3904 for each sensor or whatever to turn it on/off. Or, if the sensor is low-powered and the same voltage as what I'm running the ATmega, I just use a pin directly to control the power status. \$\endgroup\$
    – Tim Eckel
    Commented Apr 18, 2013 at 20:19
  • 1
    \$\begingroup\$ Use a 2n7000 to use significantly less power than a 2n3904 and you don't need a base resistor. \$\endgroup\$ Commented Jul 10, 2014 at 8:07
4
\$\begingroup\$

You might consider using a micro-controller thats especially optimized for low power consumption for your next design. For low power consumption it is necessary to take very low power while sleeping. What is often overlooked is that it is also important how fast it can wake up from this sleep.

What counts is how much charge it takes from the deepest sleep to handle a interrupt fastest possible (because the power burst will be very short then) and go back to sleep again.

One example of such a micro-controler is MSP430 from Texas Instruments. On their website you'll find application notes how to conserver energy and energy-harvesting applications.

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.