The power consumption of the embedded controller is the main concern in low-power designs. Arduino boards are often used in devices that rely on battery or solar charging. These devices are usually deployed away from the power line for periodic battery replacement or are mobile devices designed for periodic charging cycles. In this case, optimizing the Arduino for low power consumption is essential. Arduino optimization also allows you to ensure that the entire circuit is used more efficiently. Several measures can be applied to reduce the overall power consumption of the controller. However, the net energy consumption by the device still depends on other components interconnected with the controller.
There are several hacks and tricks that designers use to reduce the power consumption of the Arduino board. When low power design is the priority, designers first choose an Arduino board with lower operating voltage. Selecting an Arduino board cannot be based solely on operating voltage or power consumption. Often, a low-power Arduino may not be a good fit for a specific application. Typically, low power variants have fewer hardware resources or fewer GPIO. In these situations, the application may not be viable or may be compromised by using a low-power Arduino. Regardless of the Arduino board selected for a given application, designers almost always use sleep modes or Arduino power-saving modes to optimize power consumption.
In addition to selecting a low-power Arduino and using power-saving modes, some software and hardware hacks can be used to reduce power consumption. Software hacks include reducing clock speed, reducing operating voltage, and optimizing software code for low power consumption. Care must be taken that software hacks do not compromise the intended performance of the application. The hardware hack includes removing extra hardware from the Arduino board that may not be used after deploying the application/device. Let's discuss all these power saving measures for Arduino.
Selecting the right Arduino
First, the smallest suitable Arduino board should be selected for a low-power project. If an application does not have many external components, you should use Arduino nano or Arduino Pro Mini instead of Arduino UNO or MEGA. Typically, the Arduino Nano has a power consumption of 20-30 mA when powered by a 9V battery. In the same application, the Arduino Pro Mini can have a power consumption of 15 to 20 mA. The Arduino Pro Mini 3V3 has a power consumption of less than 10mA. If an application requires more GPIO or many microcontroller resources, only Arduino UNO or MEGA should be selected.
Interestingly, the Arduino MEGA has more GPIO and integrated peripherals; its power consumption is one third lower compared to the Arduino UNO. The power footprint of the Arduino UNO typically ranges from 100 to 120 mA, while the MEGA can only consume between 70 to 80 mA for the same application. Note that the energy footprint of a Nano is a fifth of an Arduino and a quarter of a Mega. Using the 3V3 Pro Mini can further reduce power consumption by 50%.
Arduino Low Power Modes
The best way to reduce the power consumption of a battery-powered application is to use power saving modes. Each microcontroller has sleep modes or power saving modes. Most Arduino boards are based on the ATmega328P controller, which offers six power saving modes. They are also called sleep modes or standby modes. These modes can be enabled with the help of the LowPower.h library. The power.h or sleep.h libraries can also manage Arduino sleep modes. The six power saving modes on Arduino are as follows.
- Idle mode
- ADC noise reduction mode
- Shutdown mode
- Power saving mode
- Standby
- Extended standby mode
To activate any of the above sleep modes, the Sleep Enable (SE) bit in the Sleep Mode Control Register (SMCR) must be set to 1. A specific sleep mode can be selected by setting the sleep mode selection bits (SMCR .SM(2 :0)). Once sleep mode is activated and one of the modes is selected, sleep mode can be executed by calling the SLEEP instruction. To wake the Arduino from sleep mode, a reset button can be pressed or an Arduino interrupt can be programmed. During sleep modes, the power consumption of Arduino boards is reduced to a few microamps compared to the power consumption of several milliamps in the active state.
Arduino idle mode
Sleep mode is activated by writing '000' to the Sleep mode selection bits (SMCR.SM(2:0)). In idle mode, the clock signal from the CPU and flash is disabled while the clock signal from other peripherals is kept active. Therefore, the CPU is turned off while USART, SPI, TWI, timer/counter, analog comparator, watchdog timer, and interrupts remain operational. Software or external interrupt can be used to wake the Arduino from idle sleep mode. The software interrupt could be timer overflow or USART. A button or sensor can generate the external interrupt. The Arduino can also be woken from sleep using a time delay.
LowPower.h must be imported into the Arduino sketch to enable idle mode. The library can be found at the following link. The library needs to be downloaded as a ZIP file and included in the Arduino libraries by navigating to Sketch->Include Library -> Add .Zip Library in the Arduino IDE. The library can be imported into the Arduino sketch using the following instruction.
#include “LowPower.h”
To enable idle mode on ATmega328P/ATmega168 based Arduino, add the following statement to the loop function.
LowPower.idle(SLEEP_8S, ADC_OFF, TIMER2_OFF, TIMER1_OFF, TIMER0_OFF, SPI_OFF, USART0_OFF, TWI_OFF);
The above instruction activates idle mode for 8 seconds. Idle mode can be activated for 15ms, 30ms, 60ms, 120ms, 250ms, 500ms, 1 second, 2 seconds, 4 seconds, 8 seconds or forever by passing SLEEP_15MS, SLEEP_30MS, SLEEP_60MS, SLEEP_120MS, SLEEP_250MS, SLEEP_500MS, , 2S, SLEEP_4S , SLEEP_8S or SLEEP_FOREVER as arguments respectively. The above instruction also disables the analog comparator, timer 0, timer 1, timer 2, USART, TWI and SPI.
To enable idle mode on ATmega32U4 based Arduino, add the following statement to the loop function.
LowPower.idle(SLEEP_8S, ADC_OFF, TIMER4_OFF, TIMER3_OFF, TIMER1_OFF, TIMER0_OFF, SPI_OFF, USART1_OFF, TWI_OFF, USB_OFF);
To enable idle mode on ATmega2560 based Arduino, add the following statement to the loop function.
LowPower.idle(SLEEP_8S, ADC_OFF, TIMER5_OFF, TIMER4_OFF, TIMER3_OFF, TIMER2_OFF, TIMER1_OFF, TIMER0_OFF, SPI_OFF, USART3_OFF, USART2_OFF, USART1_OFF, USART0_OFF, TWI_OFF);
To enable idle mode on ATmega256RFR2 based Arduino, add the following statement to the loop function.
LowPower.idle(SLEEP_8S, ADC_OFF, TIMER5_OFF, TIMER4_OFF, TIMER3_OFF, TIMER2_OFF, TIMER1_OFF, TIMER0_OFF, SPI_OFF, USART1_OFF, USART0_OFF, TWI_OFF);
The analog comparator can be turned off or kept on using ADC_OFF or ADC_ON as arguments respectively. Timer 0 can be turned off or kept on using TIMER0_OFF or TIMER0_ON as arguments respectively.
Similarly, Timer 1, Timer 2, Timer 3, Timer 4 and Timer 5 are turned off/on using TIMER1_OFF/TIMER1_ON, TIMER2_OFF/TIMER2_ON, TIMER3_OFF/TIMER3_ON, TIMER4_OFF/TIMER4_ON and TIMER5_OFF/TIMER5_ON as arguments respectively. USART 0, USART 1, USART 2 and USART 3 can be turned off or kept on using USART0_OFF/USART0_ON, USART1_OFF/USART1_ON, USART2_OFF/USART2_ON and USART3_OFF/USART3_ON as arguments respectively.
TWI can be turned off or kept on using TWI_OFF or TWI_ON as arguments respectively. SPI can be turned off or kept on using SPI_OFF or SPI_ON as arguments respectively. The USB port can be turned off or left on using USB_OFF or USB_ON as an argument.
ATmega328P based Arduino such as Nano, Pro Mini and UNO have a brown-out detector (BOD) to monitor power supply voltage during sleep modes. The BOD can be turned off or kept on using BOD_OFF or BOD_ON as arguments respectively. The default maximum duration for idle standby mode is 8 seconds. The duration can be increased by calling LowPower.idle within a loop. For example, the following instruction puts the Arduino into idle sleep for 40 seconds.
for(int i = 0; i<= 4; i++)
{
LowPower.idle(SLEEP_8S, ADC_OFF, TIMER2_OFF, TIMER1_OFF, TIMER0_OFF,SPI_OFF, USART0_OFF, TWI_OFF);
}
Using the for loop to increase sleep duration is quite useful. For example, the Arduino can be put to sleep for several minutes and then woken up for a few seconds to take sensor readings or perform other application tasks.
Arduino ADC Noise Reduction Mode
ADC noise reduction sleep mode is enabled by setting '001' for the sleep mode select bits (SMCR.SM(2:0)). In this mode, the clock signal to CPU, flash, and I/O are interrupted while the clock signal to other peripherals remains active. The analog comparator, timer/counter, watchdog timer, TWI, and external interrupts remain active in ADC noise reduction mode.
The Arduino can be activated using an external reset, an external level interrupt on INT, pin change interrupt, timer interrupt, SPM/EEPROM ready interrupt, brown-out reset, watchdog interrupt, watchdog system reset or TWI address matching.
Again, LowPower.h can be used to enable ADC noise reduction mode. Add the following line to enable this sleep mode in the loop function.
LowPower.adcNoiseReduction(SLEEP_8S, ADC_OFF, TIMER2_OFF)
Note that LowPower.h allows you to explicitly turn off the analog comparator and timer two for ADC noise reduction mode. Sleep mode can be activated for 15ms, 30ms, 60ms, 120ms, 250ms, 500ms, 1 second, 2 seconds, 4 seconds, 8 seconds, or forever.
Arduino shutdown mode
Shutdown mode can be activated by writing '010' in the sleep mode select bits (SMCR.SM(2:0)). All generated clocks are stopped in this mode while asynchronous modules remain active. Therefore, only external interrupts, TWI address matching, and watchdog timer remain operational.
The Arduino can wake up from shutdown mode using external reset, external interrupt on INT pin, pin change interrupt, watchdog interrupt, watchdog system reset, TWI address match, or Brow-out reset.
Again, LowPower.h can be used to enable shutdown mode. Add the following statement to enable this sleep mode in the loop function.
LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
Note that the BOD and analog comparator can be explicitly turned off or left on in off mode. Sleep mode can be activated for 15ms, 30ms, 60ms, 120ms, 250ms, 500ms, 1 second, 2 seconds, 4 seconds, 8 seconds, or forever.
Following is a valid example of how to wake Arduino from off mode using an external interrupt.
#include “LowPower.h”
const int wakeUpPin = 2;
void wakeUp {#interrupt_handler}
void setup { pinMode(wakeUpPin, INPUT);}
empty loop
{
attachInterrupt(0, wakeUp, LOW);
LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
detachInterrupt(0);
}
Following is a valid example of how to wake up Arduino periodically from off mode.
#include “LowPower.h”
null configuration {}
empty loop
{
LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
}
Arduino Power Saving Mode
Power save mode is activated by writing '011' to the sleep mode select bits (SMCR.SM(2:0)). This mode is the same as shutdown mode, except Timer 2 is activated. Therefore, timer overflow and output comparison events can be used to activate the Arduino.
Again, LowPower.h can be used to enable power saving mode. Add the following statement to enable this sleep mode in the loop function.
LowPower.powerSave(SLEEP_8S, ADC_OFF, BOD_OFF, TIMER2_OFF)
Note that LowPower.h allows you to explicitly turn on/off the analog comparator, brown-out detector and timer 2. Sleep mode can be activated for 15ms, 30ms, 60ms, 120ms, 250ms, 500ms, 1 second, 2 seconds , 4 seconds , 8 seconds or forever.
Arduino Standby Mode
Standby mode is activated by writing '110' to the Sleep mode selection bits (SMCR.SM(2:0)). This mode is the same as shutdown mode, except that the external oscillator continues to run in this mode.
Again, LowPower.h can be used to activate standby mode. Add the following statement to enable this sleep mode in the loop function.
LowPower.powerStandby(SLEEP_8S, ADC_OFF, BOD_OFF)
Note that LowPower.h allows you to turn off the analog comparator and power outage detector explicitly for this mode. Sleep mode can be activated for 15ms, 30ms, 60ms, 120ms, 250ms, 500ms, 1 second, 2 seconds, 4 seconds, 8 seconds, or forever. Note that LowPower.h only offers idle and standby sleep modes for SAMD21G18A-based Arduino boards.
Arduino Extended Standby Mode
Extended standby mode is activated by writing '111' to the sleep mode select bits (SMCR.SM(2:0)). This mode is the same as power save mode, except that the external oscillator continues to run in this mode.
Again, LowPower.h can be used to enable extended standby mode. Add the following statement to enable this sleep mode in the loop function.
LowPower.powerExtStandby(SLEEP_8S, ADC_OFF, BOD_OFF, TIMER2_OFF)
Note that LowPower.h allows you to turn off the analog comparator, power outage detector and timer 2 explicitly for this mode. Sleep mode can be activated for 15ms, 30ms, 60ms, 120ms, 250ms, 500ms, 1 second, 2 seconds, 4 seconds, 8 seconds, or forever. Extended standby mode takes five clock cycles to activate.
Reducing clock speed
If timing is not important in an embedded application or if the application does not require many instructions to be executed, the clock speed can be reduced to save battery power. It can triple battery life by halving clock speed. The clock speed determines the number of instructions the Arduino can execute per second. If the clock frequency is 16 MHz, the Arduino can execute 16 million instructions per second. The following table lists the default clock frequency for different Arduino boards.
Note that reducing the clock frequency also increases the Arduino sketch execution time. For example, if an Arduino sketch takes five seconds to run at a clock frequency of 16 MHz, it will take ten seconds to run at a clock frequency of 8 MHz. This can reduce the actual sleep time of the Arduino. Reducing the clock frequency also affects the operation of synchronous peripherals such as ADC, flash, and I/O.
To reduce the clock speed, a System Clock Prescaler is used. The Prescaler clock is controlled by the Arduino Clock Prescale Register (CLKPR). The register has the following bit diagram.
First, the clock prescaler must be enabled by setting the CLKPCE bit to 1. Then the clock divider can be selected by setting the CLKPS3, CLKPS2, CLKPS1 and CLKPS0 bits according to the following table.
To reduce the clock speed by half, add the following lines to the setup function.
CLKPR = 0x80; //Enables clock prescaling
CLKPR = 0x01; //Use clock division factor 2
Power consumption can be reduced by reducing the clock speed from 20% to 60%. Each Arduino board has a different response to reducing clock frequency.
Reducing operating voltage
By lowering the supply voltage, power consumption can be reduced by more than half. However, reducing the supply voltage must accompany the reduction in clock speed, as the Arduino may behave strangely if it is clocked at the default frequency while the operating voltage is reduced. Arduino boards can also have a certain maximum clock frequency for lower voltages. For example, if the ATmega328P-based Arduino is operated at 3.3V, i.e. its minimum operating voltage, the maximum clock speed should be 13 MHz in contrast to the standard 16 MHz. The operating voltage and speed clock speeds are related according to the following graph on the ATmega328.
The operating voltage and clock speed are related according to the following graph on the ATmega2560.
The following table lists the minimum possible supply voltage at reduced clock speeds for different Arduino boards.
Reducing the operating voltage can save energy consumption by 15 to 20 percent. Reducing the operating voltage also extends the time in which the battery reaches the Arduino's minimum supply voltage. Therefore, battery replacement may be required for a longer period of time than the Arduino operating at typical operating voltage.
Optimizing the Arduino sketch
To further reduce Arduino power consumption, integrated peripherals can be explicitly turned off in the sketch. The integrated peripherals, such as timer/counter, watchdog timer, power outage detector and analog comparator, continue to consume energy, regardless of whether they are used by the Arduino program or not. When implementing sleep modes using the LowPower.h library, appropriate integrated peripherals can be explicitly turned off by passing their respective arguments. If an integrated peripheral such as ADC or timer/counter is required, it can be activated by writing its corresponding registers and then deactivated again. This is a good trick to optimize power consumption with the help of Arduino software.
Removing unused components
On an Arduino board, not just the SoC, other components on the PCB also draw current which contributes to the net battery power consumption. Only the USB bridge on Arduino boards consumes around 10mA. After loading the final Arduino sketch, the USB bridge can be removed from the Arduino PCB to reduce some power consumption. However, this can only be done if the Arduino board does not need to be reprogrammed at any point.
Similarly, the integrated voltage regulator also wastes a lot of battery power as power is drained due to the difference between the voltage consumed by the ATmega328 and the actual voltage supplied by the battery. The integrated voltage regulator can be removed and the Arduino can be powered by an SMPS. The integrated linear regulator has an energy efficiency of about 70%, which is much lower than the typical 90% efficiency of the SMPS. Adding SMPS will add some additional cost to the embedded device.
Conclusion
Low power design is a significant concern in battery-powered embedded devices. The Arduino can be optimized for low power applications by choosing a low power Arduino, using power saving modes, reducing the clock speed, lowering the operating voltage, disabling peripherals used in the Arduino sketch, and removing extra components from the Arduino PCB.