🥔 Procedural robot eyes for Raspberry Pi - Cozmo/Vector-style animated face display
Find a file
2026-04-24 23:08:22 +02:00
.gitignore Add .gitignore, remove __pycache__ from tracking 2026-04-21 16:47:50 +02:00
README.md Update README: add TTS, antenna, sounds, buttons, windowed mode, env vars 2026-04-24 23:08:22 +02:00
spudface.py Fix mute: skip tap sound on mute button, longer flash, clear queue properly 2026-04-24 22:56:32 +02:00
spudface.service Redesign antenna: curved stem, two leaves, berry. Switch to fullscreen. 2026-04-24 22:14:49 +02:00

SpudFace 🥔

Procedural robot eyes for Raspberry Pi — Cozmo/Vector-style expressive face on a 7" touchscreen.

What it is

A lightweight Python/Pygame app that renders an animated robot face with two expressive eyes, a little potato sprout antenna, and text-to-speech. Controlled via JSON command file.

Features

  • 10 moods: neutral, happy, thinking, sad, excited, sleeping, cool, confused, angry, dead
  • Smooth transitions between expressions (parameter interpolation)
  • Automatic blinking at random intervals
  • Idle pupil wandering when neutral/thinking
  • Heart eyes for love mood (circle bumps + triangle)
  • Speech bubbles with large readable text
  • Antenna sprout with gentle bob animation
  • Happy bounce animation on excited moods
  • Sound effects: tap click, poke boop, blink soft tone, happy chirp
  • Text-to-Speech via gTTS (Google) — multiple accents, auto-speaks messages
  • Mute toggle — 5 min mute, kills TTS, clears message queue
  • Poke button — writes to poke.json for external integration
  • Face tap look — pupils follow where you tap (all moods)
  • Fullscreen or windowed mode (via env vars)
  • Header/footer with name, mood, time, wifi, CPU status

Quick Start

# Install dependencies
pip install pygame gtts

# Run (fullscreen on Pi display)
python3 spudface.py

# Or windowed (for desktop testing)
SPUDFACE_WINDOWED=1 python3 spudface.py

Controlling SpudFace

Write JSON to /run/user/1000/spudface/cmd.json:

{
  "mood": "happy",
  "say": "Hey there!",
  "say_duration": 10,
  "speak": true,
  "status": "Online"
}

Fields

Field Default Description
mood Expression name (see below)
say Text for speech bubble (auto-clears)
say_duration 15 Seconds to show message
speak true Auto-TTS speak the message
status Bottom status bar text

From OpenClaw (Spud agent)

echo '{"mood":"happy","say":"Hi!","say_duration":5}' > /run/user/1000/spudface/cmd.json

Supported Moods

Mood Description
neutral Default, idle state with wandering pupils
happy Wide eyes, squint, raised brows — triggers bounce
thinking One-sided lookup, angled brows
sad Droopy lids, inner brows up
excited Big wide eyes, high brows — triggers bounce
sleeping Nearly closed eyes, relaxed
cool Half-lidded, slight smirk brows
confused Different-sized pupils, angled brows
angry Narrowed eyes, steep brow angle
dead Flat line eyes, no pupils

Touch Buttons (bottom bar)

Button Action
📱 Poke Writes poke.json, shows "Poked!", plays boop sound
🕐 Time Shows current time and date
🔇/🔊 Mute Toggles 5-min mute — kills TTS, clears queue, shows icon

Face Tap Zones

  • Eyes area: surprised blink + exclamation
  • Mouth area: random quip (from built-in list)
  • Other face: pupils track your touch position

TTS / Voice

SpudFace speaks messages aloud via gTTS (Google Text-to-Speech).

Supported accents: en (US), en-uk (British), en-au (Australian), en-in (Indian), nl (Dutch), + 50+ languages.

To change default accent, edit _generate_voice() in spudface.py.

Mute: When muted, messages still show on screen but don't speak. Tap mute again to unmute after 5 minutes (or it auto-expires).

Antenna

A little green potato sprout with:

  • Curved stem that bobs gently
  • Two triangular leaves
  • Red berry on top with highlight

Bounce animation lifts the whole face when happy/excited.

Architecture

OpenClaw (Spud) → /run/user/1000/spudface/cmd.json
                        ↓
              spudface.py (Pygame loop, 30 FPS)
                        ↓
                 7" touchscreen

Environment Variables

Variable Default Description
SPUDFACE_WINDOWED Set to 1 for windowed mode
SPUDFACE_WIDTH 800 Window width
SPUDFACE_HEIGHT 480 Window height
SPUDFACE_CMD_FILE /run/user/1000/spudface/cmd.json Command file path

Running as Service (systemd)

mkdir -p ~/.config/systemd/user/
cp spudface.service ~/.config/systemd/user/
systemctl --user enable spudface.service
systemctl --user start spudface.service

The service runs as your user (not root), starts after Wayland/X11 is ready.

Display Setup

SpudFace auto-detects the display and tries multiple backends:

  1. Wayland (default on Pi 5 with desktop)
  2. X11
  3. Direct framebuffer

Force a specific driver:

SDL_VIDEODRIVER=fbcon python3 spudface.py

Files

  • spudface.py — main application
  • spudface.service — systemd service file
  • README.md — this file

License

MIT — do whatever you want with it.

Credits

  • Expression approach inspired by Anki Cozmo/Vector
  • OpenClawGotchi for the FACE:/SAY: tag system concept
  • gTTS for text-to-speech