The heart of the Sleepy Pi 2 is the Atmega328P which is one of the most widely used “Arduino” processors. The chip itself has many “Sleep” modes that provide a variety of power management options. These sleep modes are central to Sleepy Pi development – we achieve low power by using the Arduino to control power to the Raspberry Pi and then also apply low power strategies to the Arduino itself to reduce power consumption as far as we can.
This note shows the implications on power consumption of the Arduino depending on which settings are chosen from those available.
Atmega328P Power Management and Sleep Modes #
The image above shows a breakdown of the various options for sleep. It’s not overly clear and fortunately the Sleepy Pi simplifies this by using the “Low Power” library from Rocket Scream. This provides the following functions from lowest current consumption to highest:
- powerDown – Lowest current consumption
- powerSave
- powerStandby
- powerExtStandby
- adcNoiseReduction
- idle – highest current consumption
Why you would use each mode depends on your application, but generally you would use “PowerDown” unless you have a specific reason to do otherwise. For example, you might want to use “PowerSave” instead as this doesn’t shutdown the main clock, so wakes a bit quicker and you might decide that is more “reliable”. You might also want to keep BOD enabled during sleep if you are worried about battery / solar power integrity. What is the BOD? The BOD stands for “Brown Out Detect” aka “Brown Trousers” and monitors the power supply and resets the Arduino is it’s “a bit dodgy”. You can see from the measurements below that having the BOD on has very little impact on overall current consumption.
NOTE: the BOD is enabled in the fuses of the Sleepy Pi Arduino by default.
Using the Low Power Modes #
The LowPower Arduino library works broadly by “halting” the program in its tracks and putting the processor to sleep. When the processor “wakes” it carries on from exactly where it left off. To wake it, the library either uses a timed interval or an asynchronous event such as a pin change.
NOTE: It’s important to understand that this library makes use of the “watchdog timer” to wake the processor on timed intervals. If you plan to use the watchdog for other purposes, be aware that the library enables it when you put the processor to sleep and disables it when it wakes. The only exception to this is when you opt to SLEEP_FORVER, when it is not used. When sleeping forever you can be woken by a pin change or kiss from a Prince.
To put the processor to sleep, you use ONE of these calls:
SleepyPi.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); or SleepyPi.powerSave(SLEEP_FOREVER, ADC_OFF, BOD_OFF, TIMER2_OFF); or SleepyPi.powerStandby(SLEEP_FOREVER, ADC_OFF, BOD_OFF); or SleepyPi.powerExtStandby(SLEEP_FOREVER, ADC_OFF, BOD_OFF, TIMER2_OFF); or SleepyPi.adcNoiseReduction(SLEEP_FOREVER, ADC_OFF, TIMER2_OFF); or SleepyPi.idle(SLEEP_FOREVER, ADC_OFF,TIMER2_OFF,TIMER1_OFF,TIMER0_OFF,SPI_OFF, USART0_OFF,TWI_OFF);
To turn on / off a peripheral just toggle the parameter to ON or OFF i.e BOD_ON or BOD_OFF.
Use one of those lines and the Arduino will be put to sleep. See the examples i.e. ButtonOnOff to see how it can be used in a complete sketch.
Current Measurements #
The following are a series of measurements to show just how these settings affect a Sleepy Pi 2.
The measurements were made with a Sleepy Pi2 powered from 12V once it was “asleep”. The LowPower library used was version 1.81.
powerDown #
Option | ON (uA) | OFF (uA) | |
ADC | 112 | 81 | SleepyPi.powerDown(SLEEP_FOREVER, ADC_ON / OFF, BOD_OFF); |
BOD | 86.5 | 81 | SleepyPi.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_ON / OFF); |
ADC & BOD | 114 | 81 | SleepyPi.powerDown(SLEEP_FOREVER, ADC_ON / OFF, BOD_ON / OFF); |
powerSave #
Option | ON (uA) | OFF (uA) | |
ADC | 112 | 81 | SleepyPi.powerSave(SLEEP_FOREVER, ADC_ON / OFF, BOD_OFF, TIMER2_OFF); |
BOD | 86.5 | 81 | SleepyPi.powerSave(SLEEP_FOREVER, ADC_OFF, BOD_ON / OFF, TIMER2_OFF); |
Timer 2 | 196.5 | 81 | SleepyPi.powerSave(SLEEP_FOREVER, ADC_OFF, BOD_OFF, TIMER2_ON / OFF); |
All ON / OFF | 229 | 81 | SleepyPi.powerSave(SLEEP_FOREVER, ADC_ON / OFF, BOD_ON / OFF, TIMER2_ON / OFF); |
powerStandby #
Option | ON (uA) | OFF (uA) | |
ADC | 162 | 132 | SleepyPi.powerStandby(SLEEP_FOREVER, ADC_ON / OFF, BOD_OFF); |
BOD | 138 | 132 | SleepyPi.powerStandby(SLEEP_FOREVER, ADC_OFF, BOD_ON / OFF); |
All ON / OFF | 164 | 132 | SleepyPi.powerStandby(SLEEP_FOREVER, ADC_ON / OFF, BOD_ON / OFF); |
powerExtStandby #
Option | ON (uA) | OFF (uA) | |
ADC | 162 | 132 | SleepyPi.powerExtStandby(SLEEP_FOREVER, ADC_ON / OFF, BOD_OFF, TIMER2_OFF); |
BOD | 138 | 132 | SleepyPi.powerExtStandby(SLEEP_FOREVER, ADC_OFF, BOD_ON / OFF, TIMER2_OFF); |
Timer 2 | 196 | 132 | SleepyPi.powerExtStandby(SLEEP_FOREVER, ADC_OFF, BOD_OFF, TIMER2_ON / OFF); |
All ON / OFF | 229 | 132 | SleepyPi.powerExtStandby(SLEEP_FOREVER, ADC_ON / OFF, BOD_ON / OFF, TIMER2_ON / OFF); |
adcNoiseReduction #
Option | On (uA) | Off (uA) | |
ADC | 267 (?!) | 249 | SleepyPi.adcNoiseReduction(SLEEP_FOREVER, ADC_ON / OFF TIMER2_OFF); |
Timer 2 | 249 (?!) | 249 | SleepyPi.adcNoiseReduction(SLEEP_FOREVER, ADC_OFF, TIMER2_ON / OFF); |
All ON / OFF | 267 | 249 | SleepyPi.adcNoiseReduction(SLEEP_FOREVER, ADC_ON / OFF TIMER2_ON / OFF); |
powerIdle #
Option | ON (uA) | OFF (uA) | |
ADC | 326 | 280 | SleepyPi.idle(SLEEP_FOREVER, ADC_ON/ OFF,TIMER2_OFF,TIMER1_OFF,TIMER0_OFF,SPI_OFF, USART0_OFF,TWI_OFF); |
Timer 2 | 312 | 280 | SleepyPi.idle(SLEEP_FOREVER, ADC_OFF,TIMER2_ON / OFF,TIMER1_OFF,TIMER0_OFF,SPI_OFF, USART0_OFF,TWI_OFF); |
Timer 1 | 295 | 280 | SleepyPi.idle(SLEEP_FOREVER, ADC_OFF,TIMER2_OFF,TIMER1_ON / OFF,TIMER0_OFF,SPI_OFF, USART0_OFF,TWI_OFF); |
Timer 0 | 300 | 280 | SleepyPi.idle(SLEEP_FOREVER, ADC_OFF,TIMER2_OFF,TIMER1_OFF,TIMER0_ON / OFF,SPI_OFF, USART0_OFF,TWI_OFF); |
SPI | 307 | 280 | SleepyPi.idle(SLEEP_FOREVER, ADC_OFF,TIMER2_OFF,TIMER1_OFF,TIMER0_OFF,SPI_ON / OFF, USART0_OFF,TWI_OFF); |
USART0 | 292 | 280 | SleepyPi.idle(SLEEP_FOREVER, ADC_OFF,TIMER2_OFF,TIMER1_OFF,TIMER0_OFF,SPI_OFF, USART0_ON / OFF,TWI_OFF); |
TWI | 310 | 280 | SleepyPi.idle(SLEEP_FOREVER, ADC_OFF,TIMER2_OFF,TIMER1_OFF,TIMER0_OFF,SPI_OFF, USART0_OFF,TWI_ON / OFF); |
All ON / OFF | 458 | 280 | SleepyPi.idle(SLEEP_FOREVER, ADC_ON / OFF, TIMER2_ON / OFF, TIMER1_ON / OFF,TIMER0_ON / OFF,SPI_ON / OFF, USART0_ON / OFF, TWI_ON / OFF); |
Hopefully that should give a better picture of what the various modes offer in terms of current consumption.