Move all animations to Pico firmware, Pi becomes HTTP-serial bridge

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>
This commit is contained in:
Alex
2026-01-31 21:34:03 -06:00
parent 135ab1138c
commit c74371a24a
4 changed files with 442 additions and 349 deletions

View File

@@ -0,0 +1,41 @@
# 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:
1. Check serial (non-blocking poll)
2. If data: integer -> jaw amplitude; string -> mode command
3. Tick mood animation (based on mood_mode + time)
4. Tick jaw animation (based on jaw_mode or amplitude)
5. ~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 engine
- `light_service.py` - Strip down to HTTP-to-serial bridge