A physical candy-dispensing quiz machine. Kid presses a button, gets asked a question, speaks the answer, and if they're right — a treat drops.
Runs on an NVIDIA Jetson Nano. Questions and answer grading come from a local LLM. Speech is handled entirely on-device.
button press
→ LLM generates a question (math, trivia, reasoning)
→ piper-tts speaks it aloud
→ vosk listens to the kid's answer
→ LLM grades it (generously)
→ correct: GPIO pulses the dispenser + "Here's your treat!"
→ wrong: encouragement, back to idle
- NVIDIA Jetson Nano
- Momentary button wired to GPIO (BOARD pin 11)
- Servo or solenoid dispenser wired to GPIO (BOARD pin 13)
- USB speaker/mic combo (Jabra SPEAK 410 or similar)
Python deps are managed with uv:
uv syncTwo things to install manually:
piper-tts — download the binary and a voice model from the piper releases page:
sudo cp piper /usr/local/bin/piper
sudo mkdir -p /opt/piper
sudo cp en_US-lessac-medium.onnx en_US-lessac-medium.onnx.json /opt/piper/Vosk model — download vosk-model-small-en-us-0.15 from alphacephei.com/vosk/models:
sudo mkdir -p /opt/vosk
sudo tar -xzf vosk-model-small-en-us-0.15.tar.gz -C /opt/vosk/Edit config.py before running:
| Setting | Description |
|---|---|
LLM_BASE_URL |
Your OpenAI-compatible LLM endpoint |
LLM_MODEL |
Model name on that server |
LLM_DIFFICULTY |
Question difficulty (e.g. "elementary school") |
BUTTON_PIN |
GPIO BOARD pin number for the button |
DISPENSER_PIN |
GPIO BOARD pin number for the dispenser |
DISPENSE_PULSE_MS |
How long to hold the dispenser pin HIGH (ms) |
uv run python main.pyIf Jetson.GPIO isn't available (e.g. on a dev machine), GPIO mocks automatically — the button becomes an Enter key press so you can test the full flow without hardware.