Created
November 6, 2025 05:17
-
-
Save schappim/c6f91599b4c9efdba817bc5eeb39e116 to your computer and use it in GitHub Desktop.
Revisions
-
schappim created this gist
Nov 6, 2025 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,134 @@ ## 🧰 What You’ll Need * Raspberry Pi 5 running Raspberry Pi OS * Little Bird Toucan HAT (8 × APA102 LEDs) * Python 3 * The `spidev` and `time` modules (standard or installable via `apt`/`pip`) --- ## ⚙️ Wiring / Setup 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. --- ## 🧑💻 Enable SPI 1. Open a terminal on your Pi. 2. Run `sudo raspi-config`. 3. Navigate to **Interface Options → SPI → Enable**. 4. Reboot with `sudo reboot`. Verify it’s active: ```bash ls /dev/spidev* # → /dev/spidev0.0 should exist ``` --- ## 🐍 Demo Python Code Save as `toucan_demo.py`: ```python #!/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: ```bash python3 toucan_demo.py ``` Your Toucan HAT should now display a smooth **rotating rainbow animation** 🌈. --- ## 🧩 Explanation * **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. --- ## ⚠️ Safety * 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**. --- This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,62 @@ #!/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!")