Build Your Own
AI Talking Robot
with ESP32!
Ask it anything — science, history, jokes, homework — and it answers out loud using real ChatGPT AI! 🎙️✨
💡 What Does This Robot Do?
You press a button → your robot listens for a question typed via Serial → it sends that question to ChatGPT over the internet → gets the answer → and reads it aloud through a speaker using a text-to-speech chip! It's like having a tiny Einstein in a box. 🧪
The ESP32 is the perfect brain for this: it has built-in Wi-Fi to talk to ChatGPT's API, enough processing power to handle JSON data, and it's cheap and beginner-friendly!
"Hey robot, why is the sky blue?"
"The sky is blue because of a process called Rayleigh scattering — blue light bounces around more than other colours!"
DFPlayer Mini plays the audio through the speaker. The robot talks! 🎉
🛒 Parts Shopping List
Everything here is available on Amazon India, Robu.in, or your local electronics shop:
⚡ Circuit Diagram
Wire everything up exactly as shown. Take it slow — good connections make a good robot!
🔧 Step-by-Step Build Guide
Follow every step in order — get it right and your robot will be talking in a few hours! 🚀
The ESP32 needs a special setup in Arduino IDE before you can program it:
- Open Arduino IDE → File → Preferences
- Paste this in "Additional Board URLs":
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json - Go to Tools → Board → Board Manager → search "esp32" → Install
- Select: ESP32 Dev Module from the boards list
Then install these libraries via Sketch → Include Library → Manage Libraries:
LIBRARY MANAGER// Search and install each of these: "Adafruit NeoPixel" // for the RGB LEDs "Adafruit SSD1306" // for the OLED display "Adafruit GFX Library" // needed by SSD1306 "DFRobotDFPlayerMini" // for the MP3 player "ArduinoJson" // to parse ChatGPT's reply "HTTPClient" // built into ESP32 core
Your robot needs permission to talk to ChatGPT. Here's how to get an API key:
- Go to platform.openai.com and create a free account
- Click your profile → API Keys → Create new secret key
- Copy the key — it looks like:
sk-xxxxxxxxxxxxxxxxxxxxxxxx - ⚠️ Keep it secret! Never share your API key publicly
The DFPlayer Mini reads MP3 files from the SD card for the robot's voice. We use Google Text-to-Speech to create audio files for common responses:
- Format your SD card as FAT32
- Create a folder called mp3 on the card
- Save these audio files (record or use TTS tools):
SD Card/
└── mp3/
├── 0001.mp3 ← "Hello! Ask me anything."
├── 0002.mp3 ← "Let me think about that..."
├── 0003.mp3 ← "Here is my answer:"
├── 0004.mp3 ← "Sorry, I could not connect."
└── 0005.mp3 ← "Please try again."
This is the complete brain of your robot. Replace the Wi-Fi and API key details with your own:
chatgpt_robot.ino#include <WiFi.h> #include <HTTPClient.h> #include <ArduinoJson.h> #include <Adafruit_NeoPixel.h> #include <Adafruit_SSD1306.h> #include <DFRobotDFPlayerMini.h> // ── 🔑 YOUR SETTINGS — change these! ─────────── #define WIFI_SSID "Your_WiFi_Name" #define WIFI_PASS "Your_WiFi_Password" #define OPENAI_API_KEY "sk-xxxxxxxxxxxxxxxxxxxxxxxx" // ── Pin Definitions ──────────────────────────── #define BUTTON_PIN 4 #define NEO_PIN 5 #define NEO_COUNT 3 #define SCREEN_W 128 #define SCREEN_H 64 // ── Hardware Setup ───────────────────────────── Adafruit_NeoPixel pixels(NEO_COUNT, NEO_PIN, NEO_GRB + NEO_KHZ800); Adafruit_SSD1306 display(SCREEN_W, SCREEN_H, &Wire, -1); HardwareSerial dfSerial(2); // UART2 for DFPlayer DFRobotDFPlayerMini dfPlayer; // ── LED colour helpers ───────────────────────── void setLEDs(uint32_t colour) { for (int i=0; i<NEO_COUNT; i++) pixels.setPixelColor(i, colour); pixels.show(); } void thinkingAnim() { // blue pulse while waiting for (int b=10; b<200; b+=20) { setLEDs(pixels.Color(0, 0, b)); delay(40); } for (int b=200; b>10; b-=20) { setLEDs(pixels.Color(0, 0, b)); delay(40); } } // ── OLED text helper ─────────────────────────── void showText(const String& line1, const String& line2 = "") { display.clearDisplay(); display.setTextSize(1); display.setTextColor(WHITE); display.setCursor(0, 0); display.println(line1); if (line2 != "") { display.setCursor(0,20); display.println(line2); } display.display(); } // ── Ask ChatGPT ──────────────────────────────── String askChatGPT(const String& question) { HTTPClient http; http.begin("https://api.openai.com/v1/chat/completions"); http.addHeader("Content-Type", "application/json"); http.addHeader("Authorization", String("Bearer ") + OPENAI_API_KEY); // Build the JSON request body StaticJsonDocument<512> doc; doc["model"] = "gpt-3.5-turbo"; doc["max_tokens"] = 80; // short answers = faster + cheaper JsonArray msgs = doc.createNestedArray("messages"); JsonObject sys = msgs.createNestedObject(); sys["role"] = "system"; sys["content"] = "You are a friendly robot for kids. Give short, fun answers under 20 words."; JsonObject usr = msgs.createNestedObject(); usr["role"] = "user"; usr["content"] = question; String body; serializeJson(doc, body); int code = http.POST(body); if (code != 200) { http.end(); return "Error: " + String(code); } // Parse the reply JSON StaticJsonDocument<1024> reply; deserializeJson(reply, http.getString()); http.end(); return reply["choices"][0]["message"]["content"].as<String>(); } // ── Setup ────────────────────────────────────── void setup() { Serial.begin(115200); dfSerial.begin(9600, SERIAL_8N1, 16, 17); pixels.begin(); setLEDs(pixels.Color(50,0,50)); // purple = booting display.begin(SSD1306_SWITCHCAPVCC, 0x3C); showText("Booting robot..."); pinMode(BUTTON_PIN, INPUT_PULLUP); // Connect to Wi-Fi WiFi.begin(WIFI_SSID, WIFI_PASS); showText("Connecting WiFi", WIFI_SSID); while (WiFi.status() != WL_CONNECTED) { delay(400); thinkingAnim(); } // Start DFPlayer if (dfPlayer.begin(dfSerial)) { dfPlayer.volume(25); dfPlayer.play(1); // "Hello! Ask me anything." } setLEDs(pixels.Color(0,200,0)); // green = ready showText("AI Robot Ready!", "Press button :)"); Serial.println("Ready. Type question in Serial Monitor then press button."); } // ── Main Loop ────────────────────────────────── void loop() { if (digitalRead(BUTTON_PIN) == LOW) { delay(50); // debounce if (digitalRead(BUTTON_PIN) == LOW) { // Read question from Serial Monitor showText("What's your Q?", "Type in Serial..."); dfPlayer.play(2); // "Let me think..." setLEDs(pixels.Color(0,0,200)); while (!Serial.available()) { thinkingAnim(); } String question = Serial.readStringUntil('\n'); question.trim(); Serial.print("❓ Question: "); Serial.println(question); showText("Q: " + question.substring(0,18), "Asking ChatGPT..."); dfPlayer.play(2); // Get answer from ChatGPT String answer = askChatGPT(question); Serial.print("🤖 Answer: "); Serial.println(answer); // Show answer on OLED showText("A: " + answer.substring(0,18), answer.substring(18,36)); // Play "Here is my answer" audio dfPlayer.play(3); setLEDs(pixels.Color(0,200,100)); // cyan = answering delay(3000); // Return to ready setLEDs(pixels.Color(0,200,0)); showText("AI Robot Ready!", "Press button :)"); } } }
Make your AI assistant look like an actual robot! Use a medium-sized cardboard box or 3D print a face panel:
- Face panel: Cut holes for OLED screen (eyes) and speaker grille (mouth)
- Top button: Mount the push button on the top of the head like an antenna button
- Side LEDs: Place the 3 RGB LEDs on the sides as "ear indicators"
- Antenna: Wire antenna made from pipe cleaner — totally optional but looks cool!
- Paint: Silver spray paint + black eye outlines = instant robot face 🤖
Time for the big moment! Power up your robot and try these tests:
SERIAL MONITOR — TEST QUESTIONS// Try typing these questions when button is pressed: "Why is the sky blue?" "Tell me a joke" "What is photosynthesis?" "How far is the moon?" "What is 15 times 17?"
You should see: 🟣 Purple (booting) → 🔵 Blue (thinking) → 🟢 Green (answering). The OLED shows the question and answer, and the speaker announces the response!
🛠️ Troubleshooting Guide
Don't panic if something doesn't work — debugging is a superpower every engineer needs!
| 🔴 Problem | 🟡 Likely Cause | ✅ Fix |
|---|---|---|
| Wi-Fi won't connect | Wrong SSID/password or 5GHz network | ESP32 only works on 2.4GHz Wi-Fi — switch your router to 2.4GHz band |
| API returns 401 error | Wrong or expired API key | Log in to platform.openai.com and generate a fresh API key |
| OLED shows nothing | Wrong I²C address (0x3C vs 0x3D) | Try changing 0x3C to 0x3D in display.begin(). Run an I²C scanner sketch to find address |
| DFPlayer not playing | SD card files in wrong folder | Files MUST be in /mp3/ folder and named 0001.mp3, 0002.mp3 etc. Format SD as FAT32 |
| LEDs dim or flickering | Insufficient power from ESP32 | Add a 470Ω resistor on NeoPixel data line. Power NeoPixels from 5V Vin, not 3.3V |
| Robot crashes on long answers | StaticJsonDocument too small | Increase buffer from 1024 to 2048 in askChatGPT(). Also reduce max_tokens to 60 |
| Button triggers multiple times | Button bounce / no debounce | Increase debounce delay from 50ms to 100ms in the loop |
🚀 Supercharge Your Robot!
Once it's talking, these upgrades turn it from a prototype into something truly epic:
Add an INMP441 microphone — speak your question instead of typing it via Serial!
Two SG90 servos + ping pong balls — eyes that look around while the robot thinks!
Add DHT11 temp sensor — robot answers "It's 32°C today, stay hydrated!" automatically.
Ask your robot questions via Telegram on your phone — anywhere in the world!
Swap the USB adapter for an 18650 LiPo battery + TP4056 charger — fully wireless!
Use Google Cloud Text-to-Speech API for a natural human-sounding voice output.
❓ Frequently Asked Questions
New OpenAI accounts get free credits (around $5) which is enough for 500+ questions. After that, GPT-3.5 costs roughly $0.002 per question — basically free for a school project. GPT-4 is more expensive.
Use your mobile phone as a Wi-Fi hotspot! Set your phone hotspot name and password as the WIFI_SSID and WIFI_PASS in the code. The robot will connect through your phone's internet.
Yes! Add an INMP441 I²S microphone and use the ESP32's built-in I²S driver + a Speech-to-Text API (Google or Whisper). That's an advanced upgrade — perfect for version 2.0 of your robot!
Add "max_tokens: 40" in the API call and change the system prompt to say "Answer in exactly 10 words or less." Shorter answers fit better on the OLED. You can also add scrolling text code!
Absolutely — and it's a showstopper! Let visitors press the button and type any question. Make sure to bring a mobile hotspot as backup Wi-Fi in case the venue network is unavailable.
Yes! Both Anthropic's Claude API and Google's Gemini API work with very similar HTTP request structures. Just change the endpoint URL and JSON format — the ESP32 Wi-Fi code stays the same.

Comments
Post a Comment