- Raspberry Pi 5 running Raspberry Pi OS
- Little Bird Toucan HAT (8 × APA102 LEDs)
- Python 3
- The
spidevandtimemodules (standard or installable viaapt/pip)
The Toucan plugs directly on the Pi’s 40-pin header. The APA102 uses two data lines:
| Toucan Pin | Function | Pi GPIO Pin | BCM Function |
|---|---|---|---|
| CI | Clock Input | Pin 23 | GPIO 11 (SCLK) |
| DI | Data Input | Pin 19 | GPIO 10 (MOSI) |
| 5 V | Power | Pin 2 or 4 | 5 V |
| GND | Ground | Pin 6 | GND |
💡 No level-shifting is required on a Pi 5 — its 3.3 V logic is sufficient for APA102s at 5 V.
- Open a terminal on your Pi.
- Run
sudo raspi-config. - Navigate to Interface Options → SPI → Enable.
- Reboot with
sudo reboot.
Verify it’s active:
ls /dev/spidev*
# → /dev/spidev0.0 should existSave as toucan_demo.py:
#!/usr/bin/env python3
import spidev
import time
NUM_LEDS = 8 # Little Bird Toucan = 8 LEDs
# Open SPI interface (Bus 0, Device 0)
spi = spidev.SpiDev()
spi.open(0, 0)
spi.max_speed_hz = 8000000 # 8 MHz is typical for APA102
spi.mode = 0b00
def send_frame(data):
spi.xfer2(data)
def set_color(index, r, g, b, brightness=31):
"""Return 4 bytes for one LED (APA102 format)."""
brightness = max(0, min(brightness, 31))
prefix = 0b11100000 | brightness
return [prefix, b & 0xFF, g & 0xFF, r & 0xFF]
def show(colors):
"""Send data to LEDs."""
# Start frame (32 bits of zeros)
send_frame([0x00, 0x00, 0x00, 0x00])
# LED frames
frame = []
for color in colors:
frame.extend(color)
send_frame(frame)
# End frame (at least num_leds/2 bits of 1s)
end_bytes = [0xFF] * ((NUM_LEDS + 15) // 16)
send_frame(end_bytes)
def wheel(pos):
"""Generate rainbow colors across 0-255 positions."""
if pos < 85:
return (pos * 3, 255 - pos * 3, 0)
elif pos < 170:
pos -= 85
return (255 - pos * 3, 0, pos * 3)
else:
pos -= 170
return (0, pos * 3, 255 - pos * 3)
try:
print("Little Bird Toucan demo running! Press Ctrl+C to stop.")
i = 0
while True:
colors = []
for j in range(NUM_LEDS):
r, g, b = wheel((int(i + j * 256 / NUM_LEDS)) & 255)
colors.append(set_color(j, r, g, b))
show(colors)
i = (i + 1) % 256
time.sleep(0.05)
except KeyboardInterrupt:
show([set_color(0, 0, 0, 0)] * NUM_LEDS)
spi.close()
print("\nGoodbye!")Run it:
python3 toucan_demo.pyYour Toucan HAT should now display a smooth rotating rainbow animation 🌈.
- SPI sends clock (
CKI) and data (SDI) in sync — matching the APA102’s interface spec (page 5 Application Circuit shows chaining via SDI/SDO and CKI/CKO). - Each LED frame = 32 bits:
0b111xxxxx(global brightness) + Blue + Green + Red. - Start/End frames (zeros/ones) ensure proper latching.
- The APA102C runs at 5 V ± 0.5 V, typical current ~20 mA per LED.
- Don’t stare at LEDs directly at full brightness — they’re very bright.