How low can you Arduino?

How long can you run a cheap microcontroller on a single AA battery?

It’s safe to say that I have used a lot of micro-controllers over the years and an Arduino in some form or another has crept its way into most of the rigs and prototypes I make. They are cheap, reliable (enough) and support an army of open-source contributors to help get the job done. However, I have rarely had to work within a tight power budget, typically they end up tethered to a laptop gathering data or interacting with some wider system that ends up plugged into the wall.

This changed when I started to design a battery powered weather station. In theory its a simple project, an Arduino Nano connected to a few sensors and a low power BLE chip. However, when measuring the current consumption of an off-the-shelf board I concluded that a hungry PCB (ignoring the sensors for now) would gobble up an AA battery in just a couple of days. That’s no good!

So after going down a bit of a rabbit hole with googling and experimenting with power-saving techniques, I was eventually able to improve the system’s battery life into something a bit more acceptable. I have detailed below a series of steps that we can take to incrementally reduce the power consumption of these handy boards.  

The Benchmark

To evaluate how well our changes work at reducing power, we need to benchmark the current system. We can do this by running the “BareMinimum” of code required for a sketch to compile (Arduino IDE > Files > Examples > 01. Basics > BareMinimum). This is better than the default “Blink” sketch as it produces a stable current draw. After uploading the code and taking a measurement, it turns out that our baseline Arduino Nano consumes 16.9 mA.

Step 1: Removing the Power LED

The power saving process starts by removing some unnecessary components (See Muntzing). First we can eliminate the Power LED by de-soldering its current limiting resistor. This can save around 5 mA when running the BareMinimum sketch. If hardware serial comms are required, power savings can also be gained by removing the TX & RX LED’s. 

Step 2: Lower the VCC Supply Voltage & Clock Frequency​

Reducing the supply voltage is an easy way to decrease the Arduino’s power consumption. If we can power the board from a 3.3V supply rather than 5V, the current drops significantly from 11.8 mA, down to 4.2 mA (reducing power consumption by 77% to 13.8 mW!) However, when adjusting the supply voltage we must consult the Microchip oracle first (ATmega328P datasheet).

The datasheet, Section 28.4 explains how the Maximum Clock Frequency is dependent on the supply voltage. Figure 28.1 describes the “Speed Grades” of the chip and provides a safe area in which the ATmega328P should function correctly.

If we lower the supply voltage below 4.5V we must also reduce the clock frequency to stay within the area of safe operation.

It turns out that reducing this frequency also has substantial power savings, the Nano defaults to using a 16Mhz crystal. This means the ATmega microcontroller can execute up to 16 million instructions per second.  To reduce this number, we can once again refer to the datasheet and find the section regarding the “CLKPR – Clock Prescaler Register” (described in section 8.11) more info.

Clock Prescale Register (Page 33 of datasheet)

The prescale works by dividing the base clock frequency (16 MHz) by a division factor (1,2,4,8….256).  The factor is set by the 4 CLKPS bits in the CLKPR register. Normally the CLKPS bits will be reset to “0000”, which if we look the table below gives a division factor of 1 ie full speed 16 MHz.

If the CLKPS bits are set to “0011”, giving a division factor of 8, so the Arduino Nano will be executing instructions at (16/8) 2 MHz. This reduces power consumption and also allows us to stay within the safe zone (Figure 28.1) is we lower the VCC voltage.

Clock Prescale Settings

To avoid unintentional changes of clock frequency, a strict write procedure must be followed to change the CLKPS bits:

1. Write the clock prescaler change enable (CLKPCE) bit to one and all other bits in CLKPR to zero.

So in the setup section of our code, we need to write “10000000” into the register which = “0x80” (binary to hex). We write CLKPR = 0x80;

2. Within four cycles, write the desired value to CLKPS while writing a zero to CLKPCE.

Then immediately after we write the clock division factor by setting the 4 CLKPS, e.g. “0001” = Clock Division factor of 2, so the CPU runs at 8MHz. We write “0x01” (4 MHz = “0x02”, 2 MHz = “0x03”, 1 MHz = “0x04” and so on).

void setup() {
    CLKPR = 0x80; // enable a change to CLKPR
    CLKPR = 0x01; // change division factor
}

The data below shows current consumption for a number of clock frequencies and supply voltage combinations, when running the BareMinimum code.

Position Supply Voltage Test Clock Speed Current Consumption
1
5V
16 MHz
11.9 mA
2
5V
8 MHz
10.8 mA

3

3.3V

16 Mhz

4.2 mA

4
3.3 V
8 MHz
3.5 mA
5
3.3 V
4 MHz
2.1 mA

Step 3: Remove (or replace) the Voltage Regulator

On the back of the Nano (clone) is a AMS1117 SOT-223 Voltage regulator (datasheet). Generally the efficiency of these regulators is quite good under a heavy load, however with a lighter load their quiescent current draw dominates the remaining power budget. So, if we can power the ATmega328p with a 3.3v source, this negates the need for such regulator and we can remove it to bring the current consumption down by a further 200 μA.

You can snip through the smaller legs on the chip then wiggle it until the large pin breaks free.

If you need a 5V reference then we can consider an alternative voltage regulator that has been designed specifically for low Quiescent Current Consumption.

A good example is the MCP1700 which has an Extremely low operating current of only 1.6 µA, and is available in the exact same 3-Pin SOT-89 package for a direct replacement. 

Alternative Replacement Part

Step 4: Software Sleep Modes

If you don’t need the Arduino to be doing things all of the time, (which is a safe bet for most battery powered projects) you can place the CPU into a “Sleep mode” when it is not being used. All ATmega MCU’s have built in sleep modes, in general, sleep modes should be used as much as possible, and the mode should be selected so that as few as possible of the device’s functions are operating.

For example, my project for an low power weather station only requires temperature readings to be taken every 15 minutes or so, therefore we can power down the CPU into a low power sleep state for 99.9% of the time. Drastically increasing battery life.

Sleep Modes

We can leverage these sleep modes in software, and there are a number of Libraries which exist to help do just that. I highly recommend using the Low Power Library from RocketStreamIt has functions for sleeping the ATMega328P in various configurations and also support other Atmel chips including the ATmega 88, 168, 168P, 32U4, 2560 or 256RFR2. The library provides us some easy functions that help write to the various registers which control the chips’ Sleep Modes. (See Section 9 of the ATmega328P datasheet). 

Or visit the RocketStream Github

Once you download the library and install it in the Arduino IDE (help here), we can now access two very useful functions, see below for details.

Idle Mode

LowPower.idle(SLEEP_8S); 

This power saving mode does not reduce consumption as much as the powerDown mode but can wake up far more quickly. This mode can allow the SPI, USART, analog comparator, ADC, 2-wire serial interface, Timer/Counters, watchdog, and the interrupt system to continue operating.  

To save power we can manually turn these off, by adding the flowing arguments.

LowPower.idle(SLEEP_8S, ADC_OFF, TIMER2_OFF, TIMER1_OFF, TIMER0_OFF, SPI_OFF, USART0_OFF, TWI_OFF);

The MCU is place into idle mode by writing Sleep Mode Control Register SM2..0 bits to 000. 

Power Down Mode

LowPower.powerDown(SLEEP_8S);

This mode saves more power than the Idle condition, by stopping the external oscillator. The trade off however is that there is a delay on wake-up to allow the clock to become stable.

We can further reduce power consumption my manually disabling the Brown Out Detection module (BOD) and the Analog to Digital Convert module (ADC), by adding the following arguments.

LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);

powerDown mode is enabled by writing the Sleep Mode Control Register SM2..0 bits to 010

Power Down Mode (more details)

For most applications it seems that the “powerDown()” function is the most applicable. It enables excellent power savings at the expense of an extended wake up time, which can likely be accounted for in most home projects. Therefore l have presented some more information regarding its proper use below. The first thing to note is that you can wake the microcontroller up from the “powerDown()” state in one of two ways:

Via an External interrupt

In this configuration the chip can be told to sleep forever, and we can use an external interrupt from any of the interrupt pins (pins 2 & 3 for the 328p), to wake up the MCU when a change is detected, and execute some code.  This would be ideal for anything can be activated with a button press, or sensor input. See example code.

Or use an Internal Timer

Or we can use the internal watchdog timer to create timed interrupts that periodically wake the MCU. As the watchdog timer uses the on-chip 128 kHz oscillator, the sleep period is unaffected by changes made to system clock prescaler from step 2. We can set this interval from 15μs to a maximum of 8s.

LowPower.powerDown(SLEEP_FOREVER);
LowPower.powerDown(SLEEP_8S);

But I want to sleep for longer that 8 seconds!

No problem! For my project designing a weather station, I needed the MCU to sleep for around 1 hour then wake up, take a reading and send some data and then go back to sleep. However as explained above, the maximum sleep period is 8 seconds. We can effectively extend this sleep period by placing the function in a loop that executing the maximum 8 seconds sleep function a number of times. The trick to maintaining low power consumption is that in this loop the MCU will only wake up for a very shot time then go straight back to sleep. 

The library also provides functions for accessing other ATmega328p sleep modes including powerStandby, powerSave, adcNoiseReductionmode and functions for the SAMD21G18A more info here.

#include "LowPower.h"
// How long should sleep last
const int sleep_hours = 1;

void setup()
{
    // No setup is required
}

void loop() 
{
    // Enter power down state for 8 s with ADC and BOD module disabled
    for(int i=0, i<=sleep_hours*480; i++){
      LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);  
    }
    // Do something here
    // Example: Read temperatrue, send data
} 

Step 5. Remove the FTDI chip

The final step to bring the power down as far as it will go is removing the FTDI chip.  This chip provides a USB to Serial interface, allowing the Arduino to communicate with a PC’s USB port as traditional serial ports are not available on most modern computers. (On many of these cheaper “cloned” boards this chip of often a CH340 rather than a proper FTDI chip). As there are no power saving features like an enable pin on offer, it requires power even when idle and not in use.

Therefore If you really do need super low power, its got to go, as the last power hungry thing on the board removing it can save us ~ 200 μA

The Final Results

How long can it run on a single AA?

As the nominal battery voltage of a standard AA cell is below the VCC range of the ATmega328P, we need a boost converter to bring the supply voltage up to the required 3.3V.  With low power in mind, I found the MCP16251 Low Quiescent Current (4 µA) Synchronous Boost Converter.

To work out how long the system can run, we must first choose an AA battery. The Energizer Ultimate Lithium AA battery (datasheet) looks like a good candidate.

To calculate how long the system can run on this cell, the first step is to look at the start-up voltage of the boost converter. The datasheet states this as 0.82V, so rounding up to 0.9V gives us the lowest voltage we can safely discharge the battery to, and still supply a steady 3.3V to the Arduino.

Looking at the discharge curve from the datasheet, we see that for the lowest constant current given of 1mA,when the battery reaches 0.9V this equates to capacity of 3500 mAh. great!

You can see from the “temperature effects on Capacity” plot, lithium cells are largely unaffected by temperatures changes, ideal for a battery running outside.

Next we need to consider the efficiency of the boost converter, as stated on the MCP16251 datasheet the quiescent current draw is as low 4 µA.  With a maximum output current of 125 mA that that should be more than sufficient to drive our Arduino.

The datasheet provides a plot which describes how the efficiency changes with load. As our system will be running at the lower end of the Iout scale, the efficiency can as high as 78% with a 1.5V input.

However as our battery voltage will dip over time and to account for some losses we have not considered, I will reduce the overall efficiency to 60% to play it safe.

MCP16251 Efficiency Vs Current

If we consider this in the context of a real system (my battery-powered weather station project) if we wake the system once an hour to take a reading (communicate with an I2C Sensor and log the data), the MCU draws around 50 mA for 3 seconds (this was measured using a current clamp on an oscilloscope). The rest of the time the system will stay in a sleep state consuming, 4.5 µA (along with the quiescent current of the voltage regulator 4 µA). Running at an average 60% efficiency.

Taking those numbers and considering the capacity of the battery under the light load conditions, we can estimate the runtime of our system using the following process:

How long can It run on a single AA?

4+ Years

Alternative Boards?

There a number of alternate Arduino-compatible boards that have been designed specifically for this task, and if you can swap out the Nano, provide even better power savings. Here are two noteworthy boards I came across when researching this topic.

An Arduino Compatible board are carefully designed with low power consumption in mind. For use with the Arduino compatible low power library.

Minimum 1.7 uA in low-power mode

Moteino is a versatile low-power Arduino based on the Atmel ATMega328P microcontroller

Minimum 2 uA  in low-power mode