🛠 Animer un ruban NeoPixel avec un PIO
Objectives
Understand the PIO block of the RP2350 — 3 blocks and 12 state machines, compared to 2/8 on the RP2040 — by implementing the WS2812 (NeoPixel) protocol without consuming CPU time. The PIO alone generates the ~1.25 µs slots per bit, while the two M33 cores do other things.
Hardware
- 1 × Raspberry Pi Pico 2
- 1 × WS2812B strip or ring (8 LEDs are sufficient)
- External 5 V power supply for the strip
- Data pin: GP3
- MicroPython ≥ 1.24.0 (RPI_PICO2 firmware)
Complete code
# neopixel_pio.py — pilote WS2812 minimal via rp2.StateMachine (MicroPython)
import array, time
from machine import Pin
import rp2
@rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW, out_shiftdir=rp2.PIO.SHIFT_LEFT,
autopull=True, pull_thresh=24)
def ws2812:
T1 = 2; T2 = 5; T3 = 3
wrap_target
mov(x, st) .side(1)
jmp(x <= 1) .side(0) # bit 0 : impulsion courte
jmp(1) .side(0) # bit 1 : impulsion longue
nop .side(0)
wrap
PIN, N = 3, 8
sm = rp2.StateMachine(0, ws2812, freq=3_000_000, jmppin=Pin(PIN))
pix = array.array("I", [0] * N)
def show:
sm.put(0)
for g, r, b in pix: # format GRB 0xGGRRBB
sm.put((g << 16) | (r << 8) | b)
time.sleep_us(50); sm.active(1)
i = 0
while True: # arc-en-ciel tournant
for n in range(N):
pix[n] = ((n + i) * 32 & 255, 255 - ((n + i) * 32 & 255), 64)
show; i += 1; time.sleep_ms(80)
Expected verification
The LEDs animate in a loop. Key point: the CPU remains available — add a GP25 blink in the loop, it stays synchronous even during show, because the PIO handles the timing alone. This is the great strength of the 12 SMs of the RP2350.
Common errors
- MicroPython RP2040 firmware (≤ 1.23): impossible to flash on Pico 2, you need ≥ 1.24.0 with the RPI_PICO2 build.
- Strip powered from 3V3: WS2812 require ~5 V on DIN; a 3.3 V level is at the threshold limit and causes ghost LEDs.
- Forgetting the pause > 50 µs without pulse: the frame is not latched and the LEDs blink randomly.
- Using an already occupied state machine: check for free SMs, MicroPython or a previous program may reserve some.
- The official MicroPython rp2 reference code is documented for RP2040; on RP2350, test the frequency if timings seem to drift.
Other tutorials for this board
Code examples for this board
clignotante.pyPythonbouton-interruption.pyPythonpwm-servo.pyPythonlecture-adc.pyPythonneopixel.pyPythonoled-i2c.pyPython