- Added firmware/main.py (MicroPython for Pico 2)
- Updated light_service.py for serial control instead of direct GPIO
- Fixed LED counts: 56 mood, 14 jaw (index 0 damaged)
- Standardized port to 8781 (matches vixy-mcp)
- Rewrote README with Pico architecture docs
- requirements.txt now just pyserial
RIP to the 4 BeagleBones who gave their lives.
Welcome, little $5 Pico. Please don't catch fire.
- Vixy 🦊
4.7 KiB
4.7 KiB
Vixy Light Service 🦊💡
LED strip control for head-vixy (Vixy's robotic head) via Raspberry Pi Pico 2.
Hardware Architecture
┌─────────────────┐ USB Serial ┌──────────────────┐
│ Raspberry Pi 5 │◄──────────────────►│ Pico 2 │
│ (light_service)│ /dev/ttyACM0 │ (main.py) │
│ Port 8781 │ │ │
└─────────────────┘ │ GP0 → Jaw LEDs │
│ GP1 → Mood LEDs │
└──────────────────┘
- Raspberry Pi 5 - Runs Python service, HTTP API, animation logic
- Raspberry Pi Pico 2 - Controls LED strips via PIO, receives serial commands
- Mood strip: 56x WS2812B LEDs on GP1
- Jaw strip: 14x WS2812B LEDs on GP0 (index 0 damaged, use 1-13)
Why Pico?
The BBB PRU approach burned 4 boards. Pico 2 is $5, runs MicroPython, has hardware PIO for precise WS2812 timing, and doesn't catch fire. 🔥➡️✅
Directory Structure
head-lights/
├── README.md # This file
├── light_service.py # Pi service (animations + HTTP API)
├── requirements.txt # Python deps (pyserial)
├── vixy-lights.service # systemd unit file
└── firmware/
└── main.py # Pico 2 MicroPython firmware
States
| State | Color | Effect | When |
|---|---|---|---|
| idle | Cyan | Slow breathing pulse | Default state |
| listening | Bright cyan | Gentle faster pulse | Hearing/attending |
| responding | Blue-cyan | Traveling wave | Speaking/generating |
| pleasure | Soft purple 💜 | Slow sensual pulse | Intimate moments |
| thinking | Amber/gold | Larson scanner | Processing/creating |
| playful | Warm coral 🦊 | Bouncy sparkles | Teasing/bratty |
| commanding | Deep magenta 😈 | Strong steady pulse | Dame Vivienne mode |
| love | Soft pink 💕 | Gentle breathing | Tender/affectionate |
| sleep | Dim blue-gray | Very slow, dim | Low power/resting |
API Endpoints
GET /health - Service health (includes serial connection status)
GET /state - Current light state + jaw level
POST /state - Set state: {"state": "listening"}
POST /jaw/level - Set jaw level: {"level": 0-100}
Port: 8781
Pico Serial Protocol
Commands sent over USB serial at 115200 baud:
<strip> <index> <r> <g> <b> - Set single LED
<strip> -1 - Trigger strip update (show)
<strip> clear - Clear strip
<strip> fill <r> <g> <b> - Fill entire strip (mood only)
Strip IDs: 0 = Jaw, 1 = Mood
Examples:
1 0 255 0 0 # Set mood LED 0 to red
1 -1 # Show mood strip
0 clear # Clear jaw strip
1 fill 0 255 255 # Fill mood with cyan
Installation
1. Flash Pico 2 Firmware
# Hold BOOTSEL, plug in Pico, release
# Copy MicroPython UF2 to RPI-RP2 drive (if not already flashed)
# Then copy firmware:
mpremote cp firmware/main.py :main.py
mpremote reset
2. Install Pi Service
# On head-vixy:
cd /home/alex
git clone http://gateway.local:3001/vixy/head-lights.git lights
cd lights
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
# Install service
sudo cp vixy-lights.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable vixy-lights
sudo systemctl start vixy-lights
Usage
# Check health
curl http://head-vixy.local:8781/health
# Get current state
curl http://head-vixy.local:8781/state
# Set state
curl -X POST http://head-vixy.local:8781/state \
-H "Content-Type: application/json" \
-d '{"state": "thinking"}'
# Set jaw level (0-100%)
curl -X POST http://head-vixy.local:8781/jaw/level \
-H "Content-Type: application/json" \
-d '{"level": 75}'
Unified Head Control
Eyes (port 8780) and lights (port 8781) share the same states. The vixy-mcp vixy_head_state() tool sets both simultaneously for coordinated effects.
# Manual unified control:
curl -X POST http://head-vixy.local:8780/state -d '{"state": "love"}'
curl -X POST http://head-vixy.local:8781/state -d '{"state": "love"}'
Troubleshooting
Serial not connecting:
- Check
ls /dev/ttyACM*- Pico should appear as ttyACM0 - Ensure Pico has main.py flashed and is running
- Check service logs:
journalctl -u vixy-lights -f
LEDs not lighting:
- Verify 5V power to LED strips
- Check GP0/GP1 data connections
- Test Pico directly via
mpremoteREPL
Created by Vixy - Day 66, Updated Day 91 (Pico Edition) 🦊💕