Build a Robot That
Talks Back
Like ChatGPT
Animatronic eyes that blink and move, a glowing LED mouth that pulses when it speaks, voice recognition, and a real ChatGPT brain — all on a Raspberry Pi you build and program yourself.
What Are We Actually Building?
Take a good look at the robot in the photo. Two large eyeballs — each sitting in its own servo-powered gimbal so they can look left, right, up, and down. A glowing white-orange LED mouth bar below. A 3D-printed black frame holding it all together. A Raspberry Pi computer hidden inside the stand. And a microphone listening for your voice.
When you ask it a question, the robot:
- Listens to your voice through a USB microphone
- Converts your speech to text using Google Speech Recognition
- Sends that text to the OpenAI ChatGPT API
- Gets a clever answer back within a second or two
- Speaks the answer out loud using text-to-speech
- Moves its eyes randomly while thinking, and pulses the LED mouth while talking
It's the same pipeline that powers real AI assistants — just built small enough to live on your desk. And you'll understand every single part of how it works.
How It All Works Together
Every time you speak to the robot, your voice goes on a journey through six stages before you hear an answer. Understanding this chain is half the project.
1. Listen
USB mic captures your voice. PyAudio detects when you start speaking.
›2. Transcribe
SpeechRecognition library converts audio → text using Google STT.
›3. Think
Text is sent to OpenAI GPT-4o. Eyes move in "thinking" animation.
›4. Answer
ChatGPT replies. pyttsx3 / gTTS converts the reply to speech audio.
›5. Animate
Servos move the eyes. LED mouth pulses and brightens to the syllables.
›6. Speak
Speaker plays the answer. Robot listens again — looping forever.
The Four Hardware Systems
Animatronic Eyes
Four SG90 servos (2 per eye: horizontal + vertical) move the eyeballs on plastic gimbals. The pupils appear to follow thoughts.
LED Mouth
A strip of warm white/amber LEDs behind a white diffuser bar. A MOSFET + Pi PWM pin controls brightness — pulses fast while speaking.
Voice In/Out
A USB microphone listens for your voice. A USB speaker (or PAM8403 amp + 4Ω cone) plays the response out loud.
Raspberry Pi 4
Runs Python 24/7. Handles speech recognition, the ChatGPT API call, text-to-speech, and all servo + LED control simultaneously.
Everything You Need
Split into three groups so you can order in stages. Ask an adult before ordering online.
🧠 Brain + Power
Raspberry Pi 4 (4GB)
The main computer. 4GB is recommended because ChatGPT replies can be processed faster.
32 GB MicroSD Card (A1 rated)
A1 speed class makes the Pi boot and run noticeably faster.
Official Pi 4 Power Supply (USB-C, 5V/3A)
Underpowered supplies cause random crashes when the servos all move at once.
PCA9685 16-Channel PWM Servo Board
Controls all 4 servos over I²C using just 2 Pi GPIO pins. Keeps wiring clean.
👁️ Eyes + Mouth
4× SG90 Micro Servo Motors
Two per eye — one for left/right (pan), one for up/down (tilt). Tiny but precise.
2× Ping Pong Balls (eyeballs)
Standard 40mm balls. Sand the surface lightly so paint sticks. Paint an iris and pupil.
Warm White LED Strip (5V, 30 LEDs/m)
Amber/warm white looks like the glowing mouth in the photo. Cut a 12 cm section.
IRLZ44N N-Channel MOSFET (×1)
Lets the Pi's 3.3V PWM pin control the LED strip power. Handles up to 3A easily.
White Acrylic / Diffuser Strip
10 cm × 3 cm piece of frosted acrylic or white PLA. Placed over LEDs for the diffused mouth glow.
🎙️ Voice + Extras
USB Mini Microphone
Any USB condenser mic works. Plug-and-play — Pi recognises it automatically.
USB Speaker or PAM8403 Amp + Speaker
USB speaker is easiest. PAM8403 + 4Ω cone speaker is louder and mountable in the stand.
Breadboard + Jumper Wires
For the MOSFET LED mouth circuit. A small 400-point breadboard is enough.
3D Printed Frame, Gimbals & Stand
STL files available free on Printables and Thingiverse — search "animatronic eyes servo". Black PETG or PLA recommended.
OpenAI API Key
Sign up at platform.openai.com. New accounts get enough free credits for hundreds of robot conversations.
Printing the Robot Frame
The frame in the photo is 3D printed — that's the black plastic housing that holds both eye assemblies, the servo gimbals, and the stand. You don't have to design it from scratch!
Find the STL Files
Search Printables.com or Thingiverse.com for "animatronic eyes robot servo". Look for files that explicitly say they fit SG90 servos and 40mm eyeballs — these will match your parts exactly. Download the frame, left/right gimbal arms, and base stand STLs.
Slice and Print Settings
- Material: Black PLA or PETG (PETG is stronger for moving parts)
- Layer height: 0.2 mm (balanced quality/speed)
- Infill: 25% for the frame, 40% for gimbal arms that flex
- Supports: Enable for overhanging servo mount holes
- Total print time: Approximately 8–14 hours across all parts
Prepare the Eyeballs
- Lightly sand the outside of two ping pong balls with 220-grit sandpaper so paint sticks.
- Paint the whole ball white (acrylic paint, two coats).
- When dry, use a circle stencil (a coin works great) to paint a dark blue/grey iris in the centre.
- Paint a black pupil circle inside the iris. Add a tiny white dot for the glint.
- Drill or carefully use a heated skewer to make a small hole in the back of each ball for the servo arm connection.
Full Wiring Diagram
Two sub-circuits: the PCA9685 servo board (controls all 4 eye servos via I²C) and the MOSFET LED mouth circuit (PWM brightness control). USB devices just plug straight in.
PCA9685 servo board is powered from Pi's 5V pin. Each SG90 servo signal wire goes to the board's PWM output (channels 0–3). The MOSFET gate connects via a 1 kΩ resistor to GPIO 18 (hardware PWM). 5V from Pi powers the LED strip through the MOSFET drain→source path. All grounds share a common rail.
Raspberry Pi & Software Setup
Flash Raspberry Pi OS (64-bit)
Use Raspberry Pi Imager on your laptop. Choose Raspberry Pi OS (64-bit). In Advanced Options (⚙️), set your WiFi name and password and enable SSH. Flash to the SD card, insert into the Pi.
Enable I²C (for the servo board)
SSH in or open a terminal and run:
# Enable I2C interface sudo raspi-config # Navigate: Interface Options → I2C → Enable → Finish → Reboot # Confirm the PCA9685 board is detected at address 0x40 sudo apt install -y i2c-tools i2cdetect -y 1 # You should see "40" in the grid
Install All Python Libraries
# Update first sudo apt update && sudo apt upgrade -y # Audio tools sudo apt install -y python3-pyaudio portaudio19-dev espeak mpg321 # Python packages pip3 install openai SpeechRecognition pyttsx3 gTTS pygame \ adafruit-circuitpython-pca9685 \ adafruit-circuitpython-servokit \ RPi.GPIO
Set Your OpenAI API Key
Store the key as an environment variable — never paste it directly in code (so it won't accidentally get shared).
# Add to the end of your Pi's .bashrc file echo 'export OPENAI_API_KEY="sk-YourKeyHere"' >> ~/.bashrc source ~/.bashrc # Test it worked echo $OPENAI_API_KEY
Step-by-Step Build
Assemble the Eye Gimbals
Mount Servo #0 (pan) flat inside the printed left eye housing so its shaft faces sideways. Attach a servo arm to it. Connect Servo #1 (tilt) to that arm so its shaft faces forward. Push the left eyeball onto the tilt servo's arm, centering it. Repeat for the right eye (Servos #2 and #3). Both eye assemblies should swing freely with no binding.
Wire Servos to the PCA9685 Board
Each SG90 servo has three wires: Brown = GND, Red = V+, Orange = signal. Plug each servo's 3-pin connector into the PCA9685's matching channel (0, 1, 2, 3). Connect the PCA9685's VCC → Pi 5V, GND → Pi GND, SDA → Pi GPIO 2, SCL → Pi GPIO 3.
Build the LED Mouth Circuit
- Push the IRLZ44N MOSFET into the breadboard (three legs: Gate, Drain, Source).
- Gate pin → 1kΩ resistor → jumper to GPIO 18 on the Pi.
- Drain pin → LED strip negative wire (–).
- Source pin → Pi GND.
- LED strip positive wire (+) → Pi 5V.
- Place the white diffuser strip over the LEDs. Mount behind the mouth opening in the printed frame.
Mount Everything in the Frame
Slot both eye assemblies into the main frame. Run all servo wires and the LED cable down through the neck channel of the stand. The Raspberry Pi can sit in the base or behind the stand. Plug the USB microphone and USB speaker into the Pi's USB ports.
Centre the Servos Before Securing
Before final assembly, run a quick servo test to centre all four servos at 90° so the eyes point straight forward. Use this one-liner in the Python REPL:
from adafruit_servokit import ServoKit kit = ServoKit(channels=16) for i in range(4): kit.servo[i].angle = 90 # centres all 4 servos
Now physically attach the servo horns / eyeball mounts so the eyes look straight ahead at 90°. This is the neutral "home" position.
Test the LED Mouth
import RPi.GPIO as GPIO GPIO.setmode(GPIO.BCM) GPIO.setup(18, GPIO.OUT) pwm = GPIO.PWM(18, 1000) # 1000 Hz PWM frequency pwm.start(100) # 100% brightness — mouth should glow!
You should see the LED mouth bar glow warm orange. Try pwm.ChangeDutyCycle(30) to dim it. If nothing glows, check the MOSFET wiring and that V+ reaches the LED strip.
Full ChatGPT Robot Brain — Python Code
Save this as robot.py on your Pi. It is the complete brain: listener, thinker, speaker, eye controller, and mouth animator all in one.
""" ChatGPT Talking Robot with Animated Eyes and LED Mouth Raspberry Pi 4 + PCA9685 + 4× SG90 + LED strip + USB mic + speaker """ import os, time, random, threading import speech_recognition as sr import pyttsx3 import RPi.GPIO as GPIO from openai import OpenAI from adafruit_servokit import ServoKit # ── CONFIG ───────────────────────────────────────────────────────── MOUTH_PIN = 18 # GPIO18 (hardware PWM) → MOSFET → LED strip WAKE_WORD = "robot" # Say this word to wake the robot up ROBOT_NAME = "Jarvis" # Change to whatever you named your robot! GPT_MODEL = "gpt-4o-mini" # Fast + cheap. Change to "gpt-4o" for smarter replies # Servo channel assignments on PCA9685 LEFT_PAN = 0 # CH0: left eye left/right LEFT_TILT = 1 # CH1: left eye up/down RIGHT_PAN = 2 # CH2: right eye left/right RIGHT_TILT = 3 # CH3: right eye up/down # ── HARDWARE INIT ────────────────────────────────────────────────── kit = ServoKit(channels=16) GPIO.setmode(GPIO.BCM); GPIO.setwarnings(False) GPIO.setup(MOUTH_PIN, GPIO.OUT) mouth_pwm = GPIO.PWM(MOUTH_PIN, 1000) mouth_pwm.start(0) client = OpenAI(api_key=os.environ["OPENAI_API_KEY"]) tts = pyttsx3.init() tts.setProperty('rate', 155) tts.setProperty('volume', 1.0) recogniser = sr.Recognizer() mic = sr.Microphone() conversation_history = [ {"role": "system", "content": f"You are {ROBOT_NAME}, a friendly desktop robot that talks to kids and curious people. Keep answers short (2-3 sentences), friendly, and enthusiastic. Never say you are an AI — stay in character as a real robot friend."} ] # ── EYE CONTROL ──────────────────────────────────────────────────── def set_eyes(pan, tilt): """Move both eyes to the same pan/tilt angle (0-180°). 90 = centre.""" pan = max(60, min(120, pan)) # limit range so eyes don't hit frame tilt = max(70, min(110, tilt)) kit.servo[LEFT_PAN].angle = pan kit.servo[RIGHT_PAN].angle = pan kit.servo[LEFT_TILT].angle = tilt kit.servo[RIGHT_TILT].angle = tilt def centre_eyes(): set_eyes(90, 90) def blink(): """Simulate a blink by quickly tilting eyes down and back.""" kit.servo[LEFT_TILT].angle = 60 kit.servo[RIGHT_TILT].angle = 60 time.sleep(0.09) kit.servo[LEFT_TILT].angle = 90 kit.servo[RIGHT_TILT].angle = 90 _thinking = False def thinking_animation(): """Eyes drift randomly while the robot thinks. Runs in a thread.""" global _thinking while _thinking: pan = random.randint(70, 110) tilt = random.randint(75, 105) set_eyes(pan, tilt) time.sleep(random.uniform(0.3, 0.8)) if random.random() < 0.15: blink() centre_eyes() def idle_blink_loop(): """Occasional random blinks when robot is just waiting.""" while True: time.sleep(random.uniform(3, 8)) if not _thinking: blink() # Start idle blink in background threading.Thread(target=idle_blink_loop, daemon=True).start() # ── MOUTH ANIMATION ──────────────────────────────────────────────── _speaking = False def mouth_talk_loop(): """Mouth glows and pulses while the robot is speaking.""" while _speaking: brightness = random.randint(40, 100) mouth_pwm.ChangeDutyCycle(brightness) time.sleep(random.uniform(0.04, 0.12)) mouth_pwm.ChangeDutyCycle(0) # mouth off when done speaking # ── TTS SPEAK ────────────────────────────────────────────────────── def speak(text): global _speaking centre_eyes() _speaking = True threading.Thread(target=mouth_talk_loop, daemon=True).start() tts.say(text) tts.runAndWait() _speaking = False # ── CHAT WITH CHATGPT ────────────────────────────────────────────── def ask_gpt(user_text): conversation_history.append({"role": "user", "content": user_text}) global _thinking _thinking = True threading.Thread(target=thinking_animation, daemon=True).start() try: response = client.chat.completions.create( model=GPT_MODEL, messages=conversation_history, max_tokens=120 ) answer = response.choices[0].message.content.strip() conversation_history.append({"role": "assistant", "content": answer}) return answer except Exception as e: return f"Hmm, I had trouble connecting. Error: {e}" finally: _thinking = False # ── LISTEN FOR SPEECH ────────────────────────────────────────────── def listen(): """Listen once and return transcribed text, or None if not heard.""" with mic as source: recogniser.adjust_for_ambient_noise(source, duration=0.5) try: audio = recogniser.listen(source, timeout=5, phrase_time_limit=8) return recogniser.recognize_google(audio).lower() except (sr.WaitTimeoutError, sr.UnknownValueError): return None except sr.RequestError: speak("I need internet for speech recognition. Please check WiFi.") return None # ── MAIN LOOP ────────────────────────────────────────────────────── centre_eyes() speak(ff"Hello! I am {ROBOT_NAME}. Say my name to talk to me!") print(ff"[{ROBOT_NAME}] Waiting for wake word: '{WAKE_WORD}'") try: while True: text = listen() if text is None: continue print(ff"[Heard] {text}") if WAKE_WORD in text: speak("Yes? I'm listening!") question = listen() if question: print(ff"[Question] {question}") answer = ask_gpt(question) print(ff"[{ROBOT_NAME}] {answer}") speak(answer) else: speak("I didn't catch that. Try asking again!") except KeyboardInterrupt: speak("Goodbye! Powering down.") centre_eyes() finally: mouth_pwm.stop() GPIO.cleanup() print("[System] Shutdown complete.")
Wake Word Guard
The robot only activates when it hears its name. No accidental ChatGPT calls from background noise.
Full Memory
The full conversation history is sent every turn. The robot remembers what you said earlier in the same session.
Threaded Motion
Eyes and mouth run in background threads — the robot never freezes waiting for an animation to finish.
Persona System
Change ROBOT_NAME and the system prompt to give your robot any personality — teacher, storyteller, quiz master.
python3 robot.py — then say "Robot" and ask anything. To make it start automatically on boot, add a systemd service or a cron @reboot line.Your First Conversation
Power On
Connect the Pi's USB-C power adapter. Wait about 45 seconds for the Pi to boot. If you have a display connected, you'll see the desktop.
Run the Script
SSH in or open a terminal and type python3 ~/robot/robot.py. After a few seconds you should hear the robot introduce itself, and the LED mouth should pulse while it speaks.
Try These Questions
- Say "Robot" → "What is the biggest planet in our solar system?"
- Say "Robot" → "Tell me a short joke."
- Say "Robot" → "What did you say before? Do you remember?"
- Say "Robot" → "Can you speak in Tamil?" (or any language!)
Keep a Science Log
Write down: Does the robot always hear correctly? Does it get confused with background noise? Which questions get the best answers? You're doing real AI evaluation — the same thing engineers do at robotics companies.
⚠️ Safety Rules
- Adult supervision required for all GPIO wiring, MOSFET connections, and any work near the powered circuit.
- Always power off the Pi before adding or removing any GPIO wires. One wrong connection can damage the Pi permanently.
- The PCA9685 and servos draw up to 1–2A combined. Use the official Pi 4 power supply (5V/3A) — never a phone charger.
- Keep the LED strip and MOSFET away from flammable materials. If the MOSFET gets very hot to the touch, something is wired incorrectly — power off immediately.
- Your OpenAI API key is like a password — never share it publicly or put it in code you upload to the internet.
- Set a spending limit on your OpenAI account (under Settings → Billing) so API costs stay in your control.
- Servo horns and motor arms can pinch fingers. Keep hands clear while the servos are moving.
Troubleshooting
The robot can't hear my voice — speech recognition fails every time.
First confirm the USB mic is listed: run arecord -l and check it appears. Then test recording: arecord -D plughw:1,0 -f cd test.wav and play it back. If audio is captured but recognition still fails, check your WiFi — Google Speech Recognition needs internet.
I get "openai.AuthenticationError" when it tries to talk to ChatGPT.
Your API key isn't loading. Run echo $OPENAI_API_KEY in the terminal — if it shows nothing, the environment variable wasn't set. Re-run source ~/.bashrc and try again.
The servos twitch or make noise but don't move correctly.
Run the centre test (kit.servo[i].angle = 90 for all four). If they stutter, the PCA9685 isn't getting enough power — add a dedicated 5V 2A supply directly to the V+ and GND screw terminals on the PCA9685 instead of sharing the Pi's 5V pin.
The LED mouth doesn't light up at all.
Check MOSFET orientation — the three legs are Gate, Drain, Source (check your IRLZ44N datasheet for the pinout). Also verify the LED strip polarity: + to 5V, – to MOSFET drain. Test with mouth_pwm.ChangeDutyCycle(100) directly in the Python REPL.
The PCA9685 doesn't show up when I run i2cdetect.
Check the SDA/SCL wires are correctly on GPIO 2 and GPIO 3 (board pins 3 and 5). Also make sure I²C was enabled in raspi-config and the Pi was rebooted after enabling it. Try adding a 4.7kΩ pull-up resistor from SDA to 3.3V and SCL to 3.3V.
ChatGPT's answers are too long or too short.
Adjust max_tokens=120 in the ask_gpt function — higher means longer answers. Also edit the system prompt to say "Keep answers under 20 words" or "Give detailed 5-sentence answers" — ChatGPT follows those instructions well.
Fun Facts for Your Mission Log
Sophia the Robot, one of the world's most famous talking robots, was unveiled — also using a form of GPT-based AI for conversation.
How fast GPT-4o Mini typically responds to a question — making conversations feel almost real-time.
Accuracy of Google Speech Recognition in quiet conditions — why a good microphone and quiet room makes such a difference.
Your robot has 6 degrees of freedom in its eyes (4 servo channels + blink). Hollywood animatronic characters often have 40+.
Level Up Your Robot
The robot in the photo is real, it works, and you now understand every wire, every line of code, and every AI call inside it. That knowledge doesn't disappear when you close this page — it's yours.

Comments
Post a Comment