Example 2: Power-Down Sleep

In the previous example you saw the hardware pulled a constant amount of current even while sitting idle between measurements. Is there a way to reduce the power consumption during those idle periods? Indeed, using the sleep modes of the Arduino and CC3000 you can greatly reduce current consumption.

Sleep is a special mode of the processor which halts normal program execution and shuts down internal components to reduce power consumption. Once a processor is asleep it can only be awakened by specific events such as an external interrupt from a button press, or a timer counting a period of time.

One thing to note is that sleep modes aren't currently exposed by Arduino's programming library. However, because Arduino is built on the AVR Libc library you can access that library's sleep and power management functions in an Arduino sketch. This example is a little more complex than a typical Arduino sketch because it makes use of these lower level library functions to access sleep modes.
Above is a table of the sleep modes from section 9 of the ATmega328P processor datasheet (the processor that powers the Arduino Uno R3 and Nano v3). Notice that different sleep modes disable various internal clocks and components to reduce power consumption. Also of interest is what can wake the processor from each sleep mode, such as an interrupt or timer. I recommend skimming the sleep section of the datasheet for an overview of each sleep mode.

For this example I chose to use the lowest power consumption sleep mode, power-down sleep. In this mode almost all components of the processor are disabled and only an external interrupt, two-wire interface signal, or watchdog timer can wake the processor. Because I need the hardware to wake from sleep after a period of time, I use the watchdog timer to wake from power-down sleep.

The watchdog is a component inside the AVR processor which resets the processor if it detects normal program execution has stopped. Typically the watchdog is used to make an unreliable or buggy program run with more stability. However by changing the watchdog control registers, it's possible to use the watchdog as a timer which wakes the processor from power-down sleep instead of reseting it. See section 10.8 of the ATmega328P datasheet for more information on the watchdog.

The hardware for this example is exactly the same as the hardware from the first example. The only changes made are in the software. Load the Example_2_Power_Down_Sleep sketch from the software download in Arduino. Update the configuration in the same way as example 1, and upload the sketch to your hardware.

Looking at the sketch code, the differences from the previous example are:

The watchdog is configured as a timer to wake from sleep.

Inside the setup() function the watchdog control register is changed so the watchdog functions as a timer that fires interrupts instead of resetting the processor. The watchdog timer has a limited configuration of periods, so the maximum period of about 8 seconds is used for this example.

The Arduino is put into power-down sleep mode while sitting idle between measurements.

When the watchdog timer fires every 8 seconds the Arduino will be awakened from sleep. Once awake the Arduino increments a count and after it reaches 7 sleep iterations (roughly 56 seconds) a sensor measurement is logged. Finally, the Arduino is put back into sleep mode while it waits for the watchdog to wake it again.

The CC3000 is disabled while the Arduino is asleep.

In the setup() function communication with the CC3000 is initialized, and then the wlan_stop() function is called to put the CC3000 into a low power disabled state. When the Arduino awakes to take a measurement the CC3000 is enabled by calling wlan_start(), connects to the wireless network to send the measurement, and finally shuts down by calling wlan_stop() again.

Current Usage

Above is a graph of the current consumption over time for this example. There are periodic peaks of ~135 mA when a measurement is being logged, and then valleys of ~19 mA when the Arduino is asleep. This is quite an improvement from the first example as the average current consumption has fallen from 135 mA to about 45 mA!

Expected Battery Life

For this test I'll use the same AAA Ni-MH batteries as the first example. Looking at the chart of battery capacity at different discharge rates, I'll extrapolate a bit and assume at 45 mA of average current consumption the batteries will have a capacity of 775 mAh.

Expected battery life:

775 mAh / 45 mA = 17.2 hours

Actual Battery Life

Looking at the chart of battery voltage over time above, there's an interesting pattern that appears. When the hardware is consuming more current to send a measurement the voltage drops slightly. There's some aliasing in this chart because both the voltage sampling and hardware measurements happen at the same 1 minute frequency. However you can see how the changing current demands affect the battery voltage over time.

In this test the hardware ran for exactly the amount of time expected!

Actual battery life:

17.2 hours
This guide was first published on Feb 13, 2014. It was last updated on Feb 13, 2014. This page (Example 2: Power-Down Sleep) was last updated on Apr 22, 2019.