ESP32-Based Voice Assistant with Battery-Powered Microphone and Speaker
View and Edit Project In Cirkit Designer
Circuit Documentation
Summary
This circuit is designed to interface various components including microphones, speakers, sensors, and microcontrollers to create a functional embedded system. The system includes an ESP32 microcontroller for processing and communication, an INMP441 microphone for audio input, a Max98357 amplifier for audio output, an IR sensor for proximity detection, a four-pin LED for visual indicators, and a TP4056 module for battery management. The circuit is powered by a Polymer Lithium Ion Battery and includes a toggle switch for power control.
Component List
INMP441 FRONT MIC
- Description: Digital MEMS microphone
- Pins: L/R, WS, SCK, SD, VDD, GND
Polymer Lithium Ion Battery - 850mAh
- Description: Rechargeable battery
- Pins: GND, VCC
8 OHM 20W SPEAKER
- Description: Speaker for audio output
- Pins: + speaker, - speaker
IR Sensor
- Description: Infrared sensor for proximity detection
- Pins: out, gnd, vcc
TP4056 Battery Charging Protection Module (Type C)
- Description: Battery charging and protection module
- Pins: OUT +, B+, B-, OUT -, +, -
Toggle Switch
- Description: Switch for power control
- Pins: L1, COM, L2
ESP32 (30 pin)
- Description: Microcontroller with Wi-Fi and Bluetooth capabilities
- Pins: EN, VP, VN, D34, D35, D32, D33, D25, D26, D27, D14, D12, D13, GND, Vin, D23, D22, TX0, RX0, D21, D19, D18, D5, TX2, RX2, D4, D2, D15, 3V3
LED: Four Pin (Common Cathode)
- Description: RGB LED with common cathode
- Pins: red anode, common cathode, green anode, blue anode
Max98357
- Description: I2S audio amplifier
- Pins: LRC, BLCK, DIN, GAIN, SD, GND, VIN, -, +
Wiring Details
INMP441 FRONT MIC
- SD connected to ESP32 (D34)
- SCK connected to ESP32 (D26)
- WS connected to ESP32 (D22)
- L/R, VDD connected to Toggle Switch (L2)
- GND connected to GND
Polymer Lithium Ion Battery - 850mAh
- VCC connected to TP4056 Battery Charging Protection Module (B+)
- GND connected to TP4056 Battery Charging Protection Module (B-)
8 OHM 20W SPEAKER
- + speaker connected to Max98357 (+)
- - speaker connected to Max98357 (-)
IR Sensor
- out connected to ESP32 (D23)
- vcc connected to Toggle Switch (L2)
- gnd connected to ESP32 (GND)
TP4056 Battery Charging Protection Module (Type C)
- B+ connected to Polymer Lithium Ion Battery (VCC)
- B- connected to Polymer Lithium Ion Battery (GND)
- OUT + connected to Power Rail
- OUT - connected to Ground Rail
Toggle Switch
- L1 connected to TP4056 Battery Charging Protection Module (B-)
- L2 connected to IR Sensor (vcc), INMP441 FRONT MIC (L/R, VDD), ESP32 (3V3), Max98357 (GAIN, VIN)
ESP32 (30 pin)
- D34 connected to INMP441 FRONT MIC (SD)
- D26 connected to INMP441 FRONT MIC (SCK)
- D22 connected to INMP441 FRONT MIC (WS)
- D23 connected to IR Sensor (out)
- RX2 connected to ESP32 (TX2)
- TX2 connected to ESP32 (RX2)
- D4 connected to LED: Four Pin (Common Cathode) (blue anode)
- D2 connected to LED: Four Pin (Common Cathode) (green anode)
- D15 connected to LED: Four Pin (Common Cathode) (red anode)
- GND connected to LED: Four Pin (Common Cathode) (common cathode)
- D25 connected to Max98357 (DIN)
- D26 connected to Max98357 (BLCK)
- D27 connected to Max98357 (LRC)
- 3V3 connected to Toggle Switch (L2)
LED: Four Pin (Common Cathode)
- blue anode connected to ESP32 (D4)
- green anode connected to ESP32 (D2)
- red anode connected to ESP32 (D15)
- common cathode connected to ESP32 (GND)
Max98357
- DIN connected to ESP32 (D25)
- BLCK connected to ESP32 (D26)
- LRC connected to ESP32 (D27)
- GAIN, VIN connected to Toggle Switch (L2)
- GND connected to ESP32 (GND)
- + connected to 8 OHM 20W SPEAKER (+ speaker)
- - connected to 8 OHM 20W SPEAKER (- speaker)
Documented Code
ESP32 (Instance 1)
#include <Arduino.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
// Wi-Fi credentials
const char* ssid = "Atharv";
const char* password = "Atharv844";
// Gemini API settings
const char* Gemini_Token = "AIzaSyBBt67xV8mscC1pF1kUOf9_WCgbRnO9GrM";
const char* Gemini_Max_Tokens = "100";
// Helper variables
String res = "";
void setup() {
Serial.begin(115200);
// Initialize Wi-Fi
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.print("Connecting to Wi-Fi");
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(".");
}
Serial.println("\nWi-Fi Connected!");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
}
void loop() {
// Request Speech-to-Text from Python
Serial.println("stt");
delay(500); // Wait for Python module to process
// Receive query text from Python
String userQuery = "";
while (Serial.available() == 0); // Wait until data is received
while (Serial.available()) {
userQuery += (char)Serial.read();
delay(10);
}
userQuery.trim();
if (userQuery.isEmpty()) {
Serial.println("No speech recognized, skipping...");
delay(1000);
return;
}
Serial.println("User Query: " + userQuery);
// Prepare Gemini API request
HTTPClient https;
String payload = "{\"contents\": [{\"parts\":[{\"text\":\"" + userQuery + "\"}]}],\"generationConfig\": {\"maxOutputTokens\": " + (String)Gemini_Max_Tokens + "}}";
// Make HTTP POST request to Gemini API
String apiURL = "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=" + String(Gemini_Token);
https.begin(apiURL);
https.addHeader("Content-Type", "application/json");
int httpResponseCode = https.POST(payload);
String answer = "";
if (httpResponseCode == HTTP_CODE_OK) {
String response = https.getString();
DynamicJsonDocument doc(1024);
deserializeJson(doc, response);
// Parse the Gemini API response and convert it into a String
String answer = doc["candidates"][0]["content"]["parts"][0]["text"].as<String>();
answer.trim();
// Log the answer
Serial.println("Gemini API Response: " + answer);
// Send Text-to-Speech request to Python
Serial.print("tts ");
Serial.println(answer);
} else {
answer = "Sorry, I couldn't process your query.";
}
https.end();
Serial.println("Gemini API Response: " + answer);
// Send Text-to-Speech request to Python
Serial.print("tts ");
Serial.println(answer);
delay(5000); // Wait for speech to play