🛠 Sommeil profond, dormclock et PIO autonome sur batterie
Objectives
Powered by a Li-Ion cell on VSYS (the onboard buck-boost regulator maintains 3.3 V from ~1.8 to 5.5 V), the Pico can run on battery. However, its power-saving floor is not that of an "ultra-low-power" chip: the datasheet specifies DORMANT ≈ 0.8 mA and SLEEP ≈ 1.3 mA at 25 °C under 5 V, dominated by the SMPS and onboard support circuitry — not microamperes. The challenge: combine WFI waiting, wake-up via GPIO/timer alarm, dormclock (1 kHz clock during sleep), and PIO that continues working while both cores sleep.
Hardware
- 1 × Raspberry Pi Pico + 3.7 V Li-Ion cell on VSYS and GND (pins 39/38) — never use an unprotected Li-Ion cell
- Button on GP2 (wake-up, pull-up), LED on GP25
- Ideally, a µA-meter in series with the battery to measure the actual current
Full Code
// dormant_pio.c — WFI + réveil GPIO, la PIO clignote pendant le sommeil
#include "pico/stdlib.h"
#include "hardware/regs/intctrl.h"
#include "hardware/xosc.h"
#include "hardware/pio.h"
#include "dormant_pio.pio.h" // programme PIO « blink » généré (pioasm)
#define BTN 2
int main(void) {
gpio_init(BTN); gpio_set_dir(BTN, GPIO_IN); gpio_pull_up(BTN);
// programme PIO : clignotement GP25 autonome (SM0, bloc PIO0)
PIO pio = pio0;
uint off = pio_add(pio, blink_program);
uint sm = pio_claim_unused_sm(pio, true);
pio_sm_init(pio, sm, off, &blink_config);
pio_sm_set_consecutive_pindirs(pio, sm, 25, 1, true);
pio_sm_config c = blink_program_get_default_config(off);
sm_config_set_set_pins(&c, 25, 1);
pio_sm_init(pio, sm, off, &c);
pio_sm_set_enabled(pio, sm, true); // la PIO tourne sans CPU ni IRQ
irq_set_enabled(IO_IRQ_BANK0, true);
while (true) {
gpio_set_irq_enabled(BTN, GPIO_IRQ_EDGE_FALL, true);
__wfi; // les 2 cœurs s'endorment ici
gpio_set_irq_enabled(BTN, GPIO_IRQ_EDGE_FALL, false);
sleep_ms(500); // réveillé : tâche courte
}
}
For true dormant mode (XOSC off, wake-up via pin only), the SDK provides dormant_sleep_until_32k / the dormclock pattern from the C SDK book: the chip remains powered at 1 kHz, and the PIO can continue if its clock allows — verify this on your board.
Expected Verification
With the µA-meter: in an active loop, ~30-90 mA depending on USB and peripherals; in WFI waiting, it drops to ~1.3 mA (SLEEP datasheet); in dormant mode, ~0.8 mA. The PIO LED continues to blink while the CPU waits — the principle "PIO consumes no CPU" also applies to sleep. The button wakes up the loop (activity LED, ADC measurement, etc.).
Common Errors
- Expecting µA: the floor is the onboard regulator (~0.8-1.9 mA under VBUS); for true µA, you must redesign the power supply or use the bare chip — the exact attribution to the SMPS is not broken down in the datasheet.
- Dormant wake-up: in deep dormant mode, only certain pins (VREG/USB/PIO-IRQ depending on configuration) wake up; a simple
gpio_set_irqis not enough, you need the SDK's dormant path. - Forgetting that
sleep_msis NOT deep sleep: it is an active timer delay. - Forcing the regulator into PFM mode (GPIO23 floating by default) and being surprised by ADC noise after waking up: force PWM mode before measurements.
- PIO without clock during sleep: if your PIO program depends on the main clock being cut off, it stops — design it for the surviving clock, or accept the pause.
Other tutorials for this board
Code examples for this board
clignotante.pyPythonbouton-interruption.pyPythonpwm-servo.pyPythonlecture-adc.pyPythonneopixel.pyPythonoled-i2c.pyPython