Optimize battery use for the Raspberry Pi Pico
Power Saver
The Raspberry Pi Pico's high-performance chip is trimmed for I/O and does not try to save power. However, a few tricks in battery mode can keep it running longer.
A large number of pins, variable voltage input, and good community support are what make the Raspberry Pi Pico a popular single-board computer (SBC) for newcomers and professionals alike. Just connect it to your PC over USB and get started, power supply included.
When you want the Pico to run autonomously, you will need to face the question of how long the battery supply will last. Like most microcontrollers, the Pi Pico requires comparatively little power, but it has limitations when it comes to operating continuously on battery operation, not least because it continues to consume power during sleep periods. A few tricks will help you reduce the power consumption in these phases to extend the battery runtime.
Whenever you read "Pico," it also applies to other microcontrollers, either because they directly support CircuitPython (a software implementation of the Python 3 programming language used here and targeted toward beginners), or because everything also works in the same way with C/C++.
There's an old adage: If you work, you get to eat. But microcontrollers are more like non-workers in their normal state. A remote sensor or control lies around nearly 100 percent of the time, then has to respond very quickly when a button is pressed. Even a sensor that records the current temperature every 10 minutes has an uptime of less than one percent. Therefore, it's a good idea for the Pico to save resources to the extent possible when it's doing nothing.
Measure Again
The measurement setup for the program examples shown here is simple. The power supply is routed by way of a measuring circuit that continuously monitors voltage and current. The Pico simulates regular work with its built-in LED, which it switches on for one second every 30 seconds. It does nothing in between. The source code for the sample programs is available from my GitHub project [1].
If you are familiar with microcontroller programming, you will be aware that time can elapse in several ways (Listing 1). One possibility is an empty loop that keeps the program busy for a while (lines 26-29), which is the Pico treading virtual water. As you would expect, power consumption is high (Figure 1) and is why I will be using this approach as the benchmark when comparing alternatives.
Listing 1
Empty Test Loop
01 import time 02 import board 03 import alarm 04 from digitalio import DigitalInOut, Direction, Pull 05 06 LED_TIME = 1 07 INT_TIME = 30 - LED_TIME 08 SPIN = 0x1 09 SLEEP = 0x2 10 LIGHT_SLEEP = 0x3 11 DEEP_SLEEP = 0x4 12 MODE = SPIN 13 14 led = DigitalInOut(board.LED) 15 led.direction = Direction.OUTPUT 16 17 # --- Simulate work 18 def work(): 19 led.value = 1 20 time.sleep(LED_TIME) 21 led.value = 0 22 23 # --- Main loop 24 while True: 25 work() 26 if MODE == SPIN: 27 next = time.monotonic() + INT_TIME 28 while time.monotonic() < next: 29 continue 30 elif MODE == SLEEP: 31 time.sleep(INT_TIME) 32 elif MODE == LIGHT_SLEEP: 33 time_alarm = alarm.time.TimeAlarm(monotonic_time=time.monotonic()+INT_TIME) 34 alarm.light_sleep_until_alarms(time_alarm) 35 elif MODE == DEEP_SLEEP: 36 time_alarm = alarm.time.TimeAlarm(monotonic_time=time.monotonic()+INT_TIME) 40: 37 alarm.exit_and_deep_sleep_until_alarms(time_alarm)
The basic consumption of the Pico in this active wait mode is 26mA. The LED pushes the consumption up by 5mA for a short time. Taken by itself, the basic requirement is still very low because even a Pi Zero uses 90mA in idle mode, which represents the lower limit of what headless operation can offer without digging deep into your bag of tricks.
Converting consumption into the expected battery life proves to be relatively easy. Popular lithium polymer (LiPo) batteries have a self-discharge rate of 10 percent within the first 24 hours, then about five percent per month. This value already includes the current draw by the integrated protection circuit. As soon as the voltage drops below 3V, the battery switches off. You can also assume the residual capacity to be 10 percent. Exact values for self-discharge and residual capacity need be determined experimentally.
Given these assumptions, the flashing Pico will run for 46 hours on a 1,500mAh battery, whereas the Pi Zero lasts a good 15 hours. Consequently, the use of a Raspberry Pi in combination with rechargeable batteries only makes sense in scenarios where long service lives are not important (e.g., robotic cars).
Sleep Modes
With the use of Python, you can send the Pico to sleep for X seconds with time.sleep(<X>)
(Listing 1, lines 30 and 31). However, the technical implementation of time.sleep()
on the Pico uses the Pico SDK's busy_wait()
functions. In other words, the sleep function has no effect on power consumption; it just makes the Python code a bit easier to understand. The power consumption graph looks exactly like Figure 1 when this function is used. For other microcontrollers, on the other hand, the implementation can offer good savings with the light-sleep mode.
Besides time.sleep()
, CircuitPython offers two special sleep modes: light sleep and deep sleep. In both of these modes, the CPU not only stops computing but also shuts down various function blocks of the SBC, saving electricity. Both sleep modes require a timer to wake up.
In light sleep mode, the program continues normally at the point after the sleep
command, but on waking up from deep sleep, when the Pico restarts after the specified time, the current program context, including the variable values, is lost. The Pico's internal real-time clock (RTC) only retains its value during light sleep.
From the programming point of view, the two variants are not very complex, provided you import the alarm
module. The timers created in lines 33 and 36 then use the alarm.light_sleep_until_alarms()
(line 34) and alarm.exit_and_deep_sleep_until_alarms()
(line 37) commands.
With these two modes, the idle power consumption drops to 17mA in light sleep mode and 6mA in deep sleep mode (Figure 2). The additional overhead when waking up from deep sleep can also be seen: It pushes the average consumption up to 10mA in the sample scenario. The battery will then last for five days. On the ESP32-S2, which also runs CircuitPython, the consumption in deep sleep drops to below 1mA and the average consumption to 2.5mA – with a correspondingly longer runtime.
If you want to test the sleep modes yourself, please note that deep sleep does not work with an active USB connection (i.e., the serial console). This safety measure prevents buggy code from immediately sending the Pico into deep sleep without the user being able to intervene.
Also important is that the Pico does not turn off the 3.3V output. If a peripheral device is connected, it will continue to run. If you don't want that, you also need to turn off the devices connected to the output, if possible, before you send the Pico to sleep, or use a simple circuit to deactivate them.
Awake at the Touch of a Button
Timed wake-up is a useful solution to many cyclic application problems but is of little value for the remote control example cited above. Fortunately, besides alarm.time.TimeAlarm
, you also have alarm.pin.PinAlarm
, which causes the Pico to wake up after a pin voltage change (Listing 2).
Listing 2
alarm.pin.PinAlarm
pin_alarm = alarm.pin.PinAlarm(WAKE_PIN,value=False,edge=True,pull=True) if MODE == LIGHT_SLEEP: alarm.light_sleep_until_alarms(pin_alarm) elif MODE == DEEP_SLEEP: alarm.exit_and_deep_sleep_until_alarms(pin_alarm)
Although light sleep doesn't change anything in terms of power consumption, deep sleep is far more efficient with PinAlarm
than with TimeAlarm
; the current draw drops from 6mA to 1. You do not need to connect a pushbutton to the pin: Any component that pulls the pin to ground will work in the same way. One firm candidate for this is an external RTC like the DS3231 with its interrupt pin.
Another feature of the CircuitPython implementation proves to be very useful in this context: The sleep_until_
functions accept any number of alarms. If a device has several buttons, you don't need to use a dedicated wake-up button. The alarms for the sleep functions can theoretically be a mix of timer and pin alarms, but not every chip supports all variants.
Some controllers additionally wake up on a touch event. The Pico is not one of them, but the ESP32-S2 supports this feature. As with the timer alarm, the potential savings in sleep modes for the pin and touch alarms also depends on the processor.
Buy this article as PDF
(incl. VAT)
Buy Linux Magazine
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
Support Our Work
Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.
News
-
Gnome Fans Everywhere Rejoice for the Latest Release
Gnome 47.2 is now available for general use but don't expect much in the way of newness, as this is all about improvements and bug fixes.
-
Latest Cinnamon Desktop Releases with a Bold New Look
Just in time for the holidays, the developer of the Cinnamon desktop has shipped a new release to help spice up your eggnog with new features and a new look.
-
Armbian 24.11 Released with Expanded Hardware Support
If you've been waiting for Armbian to support OrangePi 5 Max and Radxa ROCK 5B+, the wait is over.
-
SUSE Renames Several Products for Better Name Recognition
SUSE has been a very powerful player in the European market, but it knows it must branch out to gain serious traction. Will a name change do the trick?
-
ESET Discovers New Linux Malware
WolfsBane is an all-in-one malware that has hit the Linux operating system and includes a dropper, a launcher, and a backdoor.
-
New Linux Kernel Patch Allows Forcing a CPU Mitigation
Even when CPU mitigations can consume precious CPU cycles, it might not be a bad idea to allow users to enable them, even if your machine isn't vulnerable.
-
Red Hat Enterprise Linux 9.5 Released
Notify your friends, loved ones, and colleagues that the latest version of RHEL is available with plenty of enhancements.
-
Linux Sees Massive Performance Increase from a Single Line of Code
With one line of code, Intel was able to increase the performance of the Linux kernel by 4,000 percent.
-
Fedora KDE Approved as an Official Spin
If you prefer the Plasma desktop environment and the Fedora distribution, you're in luck because there's now an official spin that is listed on the same level as the Fedora Workstation edition.
-
New Steam Client Ups the Ante for Linux
The latest release from Steam has some pretty cool tricks up its sleeve.