Pico runs all 9 mood animations and jaw modes locally instead of receiving per-LED serial commands from the Pi. New protocol: bare integers for fire-and-forget jaw amplitude, "mood X" / "jaw X" for mode switches. Cuts light_service.py from 409 to 193 lines. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1.5 KiB
Pico-Side Animations - Phase 1
Move all animation logic from Pi's light_service.py to Pico's firmware/main.py.
Pi becomes a thin HTTP-to-serial bridge.
New Serial Protocol
| Input | Example | Response | Description |
|---|---|---|---|
<int> |
72 |
(none) | Jaw amplitude 0-100, fire-and-forget |
mood <mode> |
mood thinking |
OK |
Switch mood animation |
jaw <mode> |
jaw talking |
OK |
Switch jaw animation |
Mood modes: idle, listening, responding, pleasure, thinking, playful, commanding, love, sleep, off Jaw modes: idle, talking, off
Bare integers are jaw amplitude (fast path, no response). This replaces per-LED serial flooding.
Pico Firmware Architecture
Non-blocking main loop:
- Check serial (non-blocking poll)
- If data: integer -> jaw amplitude; string -> mode command
- Tick mood animation (based on mood_mode + time)
- Tick jaw animation (based on jaw_mode or amplitude)
- ~10-20ms frame pacing
All 9 mood animations ported from light_service.py using time.ticks_ms().
Jaw: "level" mode maps 0-100 to 13 LEDs, "talking" mode oscillates autonomously.
Pi light_service.py Changes
Remove: all animation logic, mood_buffer, per-LED helpers, main animation loop.
Keep: HTTP API, serial connection management.
POST /state -> sends mood <state>\n, waits for OK.
POST /jaw/level -> sends <level>\n, fire-and-forget (no readline).
Files Changed
firmware/main.py- Full rewrite with animation enginelight_service.py- Strip down to HTTP-to-serial bridge