On the Pico W, WS2812B strips are a MicroPython one-liner: neopixel.NeoPixel(Pin(16), 8). The RP2040’s programmable I/O generates the 800 kHz signal in hardware.
Power a short strip from VBUS (USB 5 V) and keep the brightness low; anything longer gets its own 5 V supply with a shared ground.
Wiring
| Raspberry Pi Pico W | WS2812B addressable RGB LED strip (NeoPixel) | Wire | Notes |
|---|---|---|---|
| GP16 | DIN | green | Via 330 Ω — GP16 is physical pin 21. |
| VBUS | 5V | red | VBUS is USB 5 V (pin 40) — only present when the Pico runs from USB. Longer strips need their own 5 V supply with a common GND. |
| GND | GND | black |
5 V (about 60 mA per LED at full white) part, 3.3 V board. The strip expects a data HIGH of about 3.5 V at 5 V supply. From ESP32 or Pico the 3.3 V signal often works with short wires, but to be safe drive DIN through a 74AHCT125 (or 74HCT125) powered from 5 V.
Board quirks
- MicroPython’s
neopixelmodule uses the RP2040’s PIO, so timing is exact without any library to install. - The strip is 5 V and the Pico’s data is 3.3 V — fine on short wires; add a 74AHCT125 buffer if the first LED flickers.
- Brightness is scaled to 15 % in code to keep a short strip within USB limits.
Code
# WS2812B LED strip (8 LEDs) on a Raspberry Pi Pico W with the built-in neopixel module.
# DIN -> GP16 (pin 21) through a 330 ohm resistor, strip 5V -> VBUS (pin 40, USB 5 V), GND -> GND.
from machine import Pin
import neopixel
import time
LED_COUNT = 8
BRIGHTNESS = 0.15 # keeps a short strip well inside what USB can supply
strip = neopixel.NeoPixel(Pin(16), LED_COUNT)
def wheel(pos):
"""0-255 colour wheel -> (r, g, b)."""
pos %= 256
if pos < 85:
return (255 - pos * 3, pos * 3, 0)
if pos < 170:
pos -= 85
return (0, 255 - pos * 3, pos * 3)
pos -= 170
return (pos * 3, 0, 255 - pos * 3)
print("WS2812B rainbow on GP16")
offset = 0
while True:
for i in range(LED_COUNT):
r, g, b = wheel(offset + i * 256 // LED_COUNT)
strip[i] = (int(r * BRIGHTNESS), int(g * BRIGHTNESS), int(b * BRIGHTNESS))
strip.write()
offset = (offset + 4) % 256
time.sleep_ms(20)# WS2812B LED strip (8 LEDs) on a Raspberry Pi Pico W with the built-in neopixel module.
# DIN -> GP16 (pin 21) through a 330 ohm resistor, strip 5V -> VBUS (pin 40, USB 5 V), GND -> GND.
from machine import Pin
import neopixel
import time
LED_COUNT = 8
BRIGHTNESS = 0.15 # keeps a short strip well inside what USB can supply
strip = neopixel.NeoPixel(Pin(16), LED_COUNT)
def wheel(pos):
"""0-255 colour wheel -> (r, g, b)."""
pos %= 256
if pos < 85:
return (255 - pos * 3, pos * 3, 0)
if pos < 170:
pos -= 85
return (0, 255 - pos * 3, pos * 3)
pos -= 170
return (pos * 3, 0, 255 - pos * 3)
print("WS2812B rainbow on GP16")
offset = 0
while True:
for i in range(LED_COUNT):
r, g, b = wheel(offset + i * 256 // LED_COUNT)
strip[i] = (int(r * BRIGHTNESS), int(g * BRIGHTNESS), int(b * BRIGHTNESS))
strip.write()
offset = (offset + 4) % 256
time.sleep_ms(20)Expected serial output
WS2812B rainbow on GP16WS2812B rainbow on GP16
Common errors
First LED flickers or shows the wrong colour
Marginal 3.3 V data. Keep the data wire short and the 330 Ω resistor in place, or add a buffer.
Pico resets when LEDs turn white
Too much current from USB. Lower the brightness or give the strip its own supply.