The AI Puppet Storyteller Robot
Build a magical robot that listens to children, invents a story using AI, narrates it out loud, and makes puppets come alive — all automatically!
✨ How Does the Magic Work?
Five simple steps from "Tell me a story!" to puppet show time.
1. Child Speaks
Microphone listens for a story request
2. AI Thinks
Claude AI creates a brand new story
3. Robot Narrates
Text-to-speech reads the story aloud
4. Pi Controls
Raspberry Pi sends commands to servos
5. Puppets Act!
Puppets move and perform the scenes
Fun Fact for Young Makers!
This project combines three types of engineering — mechanical (moving puppets), electrical (circuits and motors), and software (Python and AI coding). Real robotics engineers use all three together!
🛒 Parts You Will Need
Most of these can be found at electronics shops or ordered online. Ask a grown-up to help!
Raspberry Pi 4
The brain of the robot. 2GB RAM or more works great.
× 1PCA9685 Servo Driver
Controls up to 16 servos at once via I2C.
× 1SG90 Micro Servo Motors
Tiny, lightweight — perfect for puppet arms and heads.
× 4–6USB Microphone
Plug-and-play mic to capture the child's story request.
× 1USB Speaker / 3.5mm
For the AI narrator's voice to come out loud and clear.
× 1Puppet Figures
Foam, felt, or toy puppets. Attach servos to their limbs!
× 2–4Cardboard / Wood Frame
Build a mini puppet stage to mount everything on.
× 15V 3A Power Supply
Official Raspberry Pi power adapter — servos need good power!
× 1Jumper Wires + Breadboard
For making all the connections between components.
× 1 setParent / Guardian Note
You'll also need a free API key from Anthropic (claude.ai) or OpenAI for the AI story generation. Always get an adult to handle API key setup and wiring.
⚡ Circuit Wiring Diagram
Here's exactly how to connect everything together. Take it one wire at a time!
🔌 Complete Wiring Connection Table
| From (Raspberry Pi) | To (Component) | Wire Colour | Purpose |
|---|---|---|---|
| Pin 3 — GPIO 2 | PCA9685 → SDA | 🔵 Blue | I2C Data Line |
| Pin 5 — GPIO 3 | PCA9685 → SCL | 🟡 Yellow | I2C Clock Line |
| Pin 1 — 3.3V | PCA9685 → VCC | 🔴 Red | Logic Power |
| Pin 6 — GND | PCA9685 → GND | ⚫ Black | Ground |
| External 5V PSU | PCA9685 → V+ | 🔴 Red | Servo Power (separate!) |
| PCA9685 → CH0 | Servo 1 (Puppet Head) | 🟠 Orange (signal) | PWM Control |
| PCA9685 → CH1 | Servo 2 (Left Arm) | 🟠 Orange (signal) | PWM Control |
| PCA9685 → CH2 | Servo 3 (Right Arm) | 🟠 Orange (signal) | PWM Control |
| PCA9685 → CH3 | Servo 4 (Body / 2nd Puppet) | 🟠 Orange (signal) | PWM Control |
| USB Port A | USB Microphone | USB Cable | Voice Input |
| 3.5mm Audio Jack | Speaker | Audio Cable | Story Narration Output |
Important Wiring Rule!
Always power servos from a separate 5V source, NOT directly from the Raspberry Pi's GPIO pins. Too much current from servos will damage your Pi. Use the PCA9685's V+ and GND terminals for servo power.
🔧 Step-by-Step Build Instructions
Work through these steps in order. Take your time — a good build always wins!
Set Up Your Raspberry Pi
Install the OS and enable I2C
Download Raspberry Pi OS (64-bit) from the official site and flash it to your SD card using Raspberry Pi Imager.
- Boot up the Pi and connect keyboard, monitor, and mouse
- Go to Preferences → Raspberry Pi Configuration → Interfaces
- Enable I2C — this lets the Pi talk to the servo driver
- Connect your USB microphone and USB speaker, then test sound
# Update the system first sudo apt update && sudo apt upgrade -y # Install required Python libraries pip3 install adafruit-circuitpython-pca9685 pip3 install SpeechRecognition pip3 install pyttsx3 pip3 install anthropic pip3 install smbus2 sudo apt install python3-pyaudio espeak -y
Build the Puppet Stage
Create the physical theatre
Cut a cardboard box to make a mini theatre stage approximately 50cm wide × 40cm tall.
- Paint or decorate it with curtains, stars, and backdrops
- Mount servo motors at the top of the stage using hot glue or zip ties
- Attach puppet figures to servo arms using thin fishing line or stiff wire
- Servo 1 (CH0) → puppet head nod | Servo 2 (CH1) → left arm wave
- Servo 3 (CH2) → right arm | Servo 4 (CH3) → second puppet body
- Place the speaker inside or behind the stage for best sound effect
Make It Yours!
Decorate with themes — jungle animals, space explorers, fairy tale characters! The story AI will adapt to whatever puppets you create.
Wire Up the Circuit
Connect Pi → PCA9685 → Servos
Follow the wiring table above carefully. Work with the power OFF at all times when connecting wires.
- Connect I2C wires: GPIO 2 (SDA) and GPIO 3 (SCL) to the PCA9685
- Connect 3.3V and GND from Pi to PCA9685's logic power pins
- Connect your separate 5V PSU to PCA9685's V+ and GND (for servo power)
- Plug each servo into CH0, CH1, CH2, CH3 on the PCA9685
- Orange wire = signal | Red = 5V | Brown/Black = GND (on each servo)
After wiring, run this quick test to check I2C is detecting the board:
# Should show 0x40 (the PCA9685 address)
i2cdetect -y 1
Get Your AI API Key
Connect to Claude AI for story generation
Ask a parent or guardian to do this step. The AI key lets the robot generate new stories!
- Go to console.anthropic.com and create a free account
- Generate an API key under "API Keys"
- Never share this key publicly or put it directly in code you share
- Store it safely as an environment variable on your Pi
# Add to ~/.bashrc so it loads every time echo 'export ANTHROPIC_API_KEY="your_key_here"' >> ~/.bashrc source ~/.bashrc
🐍 The Complete Python Code
This is the full program. Copy it into a file called puppet_storyteller.py on your Raspberry Pi.
#!/usr/bin/env python3 # ======================================================== # 🎭 AI PUPPET STORYTELLER ROBOT # Raspberry Pi + PCA9685 + Claude AI # Kids Robotics Project # ======================================================== import os import time import re import threading import speech_recognition as sr import pyttsx3 import anthropic import board import busio from adafruit_pca9685 import PCA9685 from adafruit_motor import servo # ── SETUP ──────────────────────────────────────────── # Initialize I2C and PCA9685 servo driver board i2c = busio.I2C(board.SCL, board.SDA) pca = PCA9685(i2c) pca.frequency = 50 # Standard servo frequency: 50 Hz # Create servo objects for each puppet part # SG90 servos operate between 500μs and 2400μs pulse width servos = { "head": servo.Servo(pca.channels[0], min_pulse=500, max_pulse=2400), "left_arm": servo.Servo(pca.channels[1], min_pulse=500, max_pulse=2400), "right_arm": servo.Servo(pca.channels[2], min_pulse=500, max_pulse=2400), "body": servo.Servo(pca.channels[3], min_pulse=500, max_pulse=2400), } # Initialize AI client and speech engine ai_client = anthropic.Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"]) tts_engine = pyttsx3.init() tts_engine.setProperty("rate", 145) # Slightly slower for kids tts_engine.setProperty("volume", 0.95) # Nice and loud recognizer = sr.Recognizer() # ── PUPPET ANIMATIONS ─────────────────────────────── def move_servo_smooth(servo_obj, start_angle, end_angle, steps=20): """Smoothly move a servo from start to end angle.""" for i in range(steps + 1): angle = start_angle + (end_angle - start_angle) * i / steps servo_obj.angle = angle time.sleep(0.02) def reset_puppets(): """Move all puppets to neutral resting position.""" print("🎭 Resetting puppets to start position...") for name, s in servos.items(): move_servo_smooth(s, s.angle or 90, 90) def puppet_idle_dance(): """Gentle idle animation while waiting for a story request.""" servos["head"].angle = 80 time.sleep(0.4) servos["head"].angle = 100 time.sleep(0.4) servos["head"].angle = 90 def perform_scene(scene_type): """Perform a choreographed puppet animation based on scene type.""" print(ff"🤖 Performing scene: {scene_type}") if scene_type == "greeting": # Both arms wave hello for _ in range(3): move_servo_smooth(servos["left_arm"], 90, 45) move_servo_smooth(servos["right_arm"], 90, 135) move_servo_smooth(servos["left_arm"], 45, 90) move_servo_smooth(servos["right_arm"], 135, 90) elif scene_type == "walk": # Alternating arm swing like walking for _ in range(4): servos["left_arm"].angle = 60 servos["right_arm"].angle = 120 time.sleep(0.25) servos["left_arm"].angle = 120 servos["right_arm"].angle = 60 time.sleep(0.25) elif scene_type == "surprised": # Head jerks up, arms fly out servos["head"].angle = 50 servos["left_arm"].angle = 30 servos["right_arm"].angle = 150 time.sleep(0.6) reset_puppets() elif scene_type == "happy": # Bouncy up-down body movement for _ in range(4): move_servo_smooth(servos["body"], 90, 75, steps=8) move_servo_smooth(servos["body"], 75, 105, steps=8) servos["body"].angle = 90 elif scene_type == "scared": # Shake trembling for _ in range(6): servos["head"].angle = 85 time.sleep(0.08) servos["head"].angle = 95 time.sleep(0.08) elif scene_type == "fight": # Arms punch outward alternately for _ in range(3): servos["left_arm"].angle = 20 time.sleep(0.2) servos["left_arm"].angle = 90 servos["right_arm"].angle = 160 time.sleep(0.2) servos["right_arm"].angle = 90 else: # default: slow head nod move_servo_smooth(servos["head"], 90, 70) move_servo_smooth(servos["head"], 70, 110) move_servo_smooth(servos["head"], 110, 90) # ── STORY KEYWORDS → PUPPET SCENES ───────────────── SCENE_MAP = { "walk": ["walked", "ran", "ran", "hopped", "skipped", "travelled"], "greeting": ["hello", "hi", "waved", "met", "greeted"], "surprised": ["suddenly", "gasped", "surprised", "shocked", "wow"], "happy": ["happy", "excited", "cheered", "laughed", "celebrated"], "scared": ["scared", "frightened", "trembled", "afraid", "monster"], "fight": ["fought", "battled", "defeated", "dragon", "villain"], } def detect_scene_from_sentence(sentence): """Pick the best puppet animation based on story sentence keywords.""" sentence_lower = sentence.lower() for scene, keywords in SCENE_MAP.items(): if any(kw in sentence_lower for kw in keywords): return scene return "default" # ── VOICE RECOGNITION ─────────────────────────────── def listen_for_story_request(): """Listen via microphone and return the child's story request.""" with sr.Microphone() as source: print("🎤 Listening... say 'Tell me a story about...' ") recognizer.adjust_for_ambient_noise(source, duration=1) tts_engine.say("Hello! What story shall I tell you today?") tts_engine.runAndWait() puppet_idle_dance() try: audio = recognizer.listen(source, timeout=8, phrase_time_limit=8) request = recognizer.recognize_google(audio) print(ff"✅ Heard: {request}") return request except sr.WaitTimeoutError: tts_engine.say("I didn't hear anything! Try again?") tts_engine.runAndWait() return None except sr.UnknownValueError: tts_engine.say("Hmm, I couldn't understand. Could you say it again?") tts_engine.runAndWait() return None # ── AI STORY GENERATION ───────────────────────────── def generate_story(request): """Ask Claude AI to write a child-friendly puppet story.""" print("🧠 Asking AI to write a story...") tts_engine.say("Ooh, let me think of a wonderful story for you!") tts_engine.runAndWait() prompt = f"""You are a friendly puppet theatre narrator for young children aged 4-10. Write a short puppet show story (5-7 sentences) based on: "{request}" Rules: - Simple, fun, age-appropriate language only - Include action words like: walked, waved, jumped, fought, laughed, ran, surprised - Have a clear beginning, middle and happy ending - Each sentence on its own line - No scary or sad endings""" response = ai_client.messages.create( model="claude-sonnet-4-6", max_tokens=400, messages=[{"role": "user", "content": prompt}] ) story = response.content[0].text.strip() print(ff"\n📖 STORY:\n{story}\n") return story # ── PERFORMANCE ENGINE ─────────────────────────────── def perform_story(story): """Split story into sentences, narrate each one, and animate puppets.""" sentences = [s.strip() for s in story.split("\n") if s.strip()] tts_engine.say("Lights! Camera! Action!") tts_engine.runAndWait() time.sleep(0.5) for i, sentence in enumerate(sentences): print(ff"🎤 [{i+1}/{len(sentences)}]: {sentence}") # Determine puppet animation from sentence content scene = detect_scene_from_sentence(sentence) # Run narration and animation in parallel threads narrate_thread = threading.Thread( target=lambda s=sentence: (tts_engine.say(s), tts_engine.runAndWait()) ) animate_thread = threading.Thread( target=perform_scene, args=(scene,) ) narrate_thread.start() animate_thread.start() narrate_thread.join() animate_thread.join() time.sleep(0.3) # Brief pause between sentences reset_puppets() tts_engine.say("The End! I hope you loved the show! Clap clap clap!") tts_engine.runAndWait() perform_scene("happy") # Bow after the show! # ── MAIN LOOP ───────────────────────────────────────── def main(): print("🎭 AI Puppet Storyteller Robot Starting Up!") reset_puppets() time.sleep(1) while True: try: request = listen_for_story_request() if request: story = generate_story(request) perform_story(story) print("⏳ Waiting 3 seconds before next story...\n") time.sleep(3) except KeyboardInterrupt: print("\n👋 Show's over! Goodbye!") reset_puppets() pca.deinit() break except Exception as e: print(ff"❌ Error: {e}") tts_engine.say("Oops, something went wrong! Let's try again.") tts_engine.runAndWait() time.sleep(2) if __name__ == "__main__": main()
Running the Program
Open a terminal on your Raspberry Pi and type: python3 puppet_storyteller.py — then say "Tell me a story about a brave lion!"
🛡️ Safety Rules for Young Makers
Safety is the most important part of any build. Every real engineer follows these rules!
Power Off First
Always unplug everything before connecting or changing wires. Never work on live circuits.
Adult Supervision
Always have a parent or guardian nearby when working with electronics and tools.
Check Wires Twice
Double-check all connections before powering on. Crossed wires can damage your Pi.
Right Power Supply
Use only the official Raspberry Pi 5V/3A adapter. Wrong voltage can break components.
Keep API Keys Secret
Never share your AI API key publicly or put it in code you upload online.
Ventilate Your Pi
Raspberry Pi can get warm. Keep it in a case with ventilation holes — don't cover it!
🚀 Cool Upgrade Ideas
Once your basic puppet bot is working, try these awesome additions!
LED Stage Lights
Add WS2812B LED strips to light up the stage in different colours for mood lighting!
Web Control Panel
Build a Flask web app so you can request stories from a phone or tablet browser.
Camera + Face Detection
Add a Pi Camera — the puppets could turn to look at whoever is watching the show!
Multi-Language Stories
Add a language selection button — tell stories in Tamil, Hindi, French, or Spanish!
Background Music
Play royalty-free music tracks that match the story mood using pygame.mixer.
Educational Mode
Modify the AI prompt to turn any story into a science lesson or maths adventure!
You Did It, Young Engineer!
Building this project means you've touched AI, robotics, electronics, coding, and creative design all at once. That's exactly what real engineers and inventors do every day. Keep building, keep asking questions, and keep making amazing things!

Comments
Post a Comment