Optimize battery use for the Raspberry Pi Pico
All Gone?
One disadvantage of deep sleep is the complete restart of the program, wherein (almost) the entire state of the Pico is lost. However, the Pico and other microcontroller units (MCUs) also have non-volatile memory or non-volatile RAM (NVRAM). This memory does not act like a disk drive; programs can only address it as a byte sequence. The Pico has 4KB for this purpose. The SAMD21 has just 256 bytes, and its big brother, the SAMD51, has 8KB. The size is not documented, but you can find the values in the CircuitPython source code.
Listing 3 shows how to access this NVRAM. The second and third lines convert a string into bytes and then write the value to memory. The last two lines read the memory again. The difference between the two alternatives is that the second variant can also handle Unicode characters that comprise more than one byte in UTF-8 encoding: The ä in the example occupies two bytes. You can convert numbers smaller than 255 directly. For larger numbers, use the standard to_bytes
and from_bytes
functions.
Listing 3
Non-Volatile Memory
import microcontroller microcontroller.nvm[42:48] = b'Hello' microcontroller.nvm[10:14] = 'Hä?'.encode('utf-8') print(microcontroller.nvm[42:48]) print(microcontroller.nvm[10:14].decode('utf-8'))
Unfortunately, I could find no information online about the Pico's potential number of memory write cycles. Microchip Technology Inc. specifies 100,000 (minimum) to 600,000 cycles (typical) for the SAMD21 processor, and the value should be in the same range for the Pico. Therefore, if you write to this memory every minute, you will run out of road within a year. You definitely need a program that is a little smarter.
Some boards have other memory areas besides the NVRAM whose contents survive the deep sleep but not a complete reset, including SAMD21/51 boards and ESP microcontroller boards, but not the Pico. Unlike flash, this RAM area, sometimes known as backup memory, is not worn out by write operations. CircuitPython serves it up as a byte array in the alarm.sleep_memory
variable. Access is like NVRAM access.
External Control
The Pico's 3V3_EN pin (physical pin 37) offers another very efficient option for battery operation. When pulled to ground, it completely shuts down the Pico, including the 3.3V output. However, manufacturers typically omit this pin from smaller Pico boards.
The enable timer board (Figure 3) by Adafruit [2] is perfect for this setup. You can set the wake-up interval with a slightly fiddly rotary potentiometer or optionally use a fixed resistor. Additionally, a button gives you a manual wake-up option.
The Pico takes care of shutting itself down as soon as you connect a GPIO pin to the Done pin of the timer and toggle it to high. The button's own consumption is very low at 20µA, and the current curve starts looking pretty much ideal (Figure 4). The only disadvantage in this constellation is that the intervals are restricted to a range of between one second and two hours. Daily intervals are not supported, but the enable timer is perfect for many cyclic use cases.
C Alternative
If you rely on CircuitPython, you are relinquishing full control over the processor – not just the clock-synched signals, but also the memory and peripherals. If you want to use the Pico and other MCUs to the max, you have to use C/C++.
Because ultimately the CircuitPython implementation uses the C/C++ SDK, you cannot hope to extract too much more from the sleep modes. Pico SDK-speak does not refer to light sleep and deep sleep, but sleep mode and dormant mode. The SDK provides two sample programs – hello_sleep
and hello_dormant
– that demonstrate the use.
For your own projects, it's worth taking a look at the SleepyPico GitHub repo [3], which contains a complete application, including a reusable Sleep
class. You need to define a setup function for this (one-off) call, along with a loop function that calls the class once per work interval.
« Previous 1 2 3 Next »
Buy this article as PDF
(incl. VAT)