Voice-Controlled Home Assistant using esp32 tutorial using wowki simulator

Voice-Controlled Home Assistant Using ESP32 | MakeMindz
⚡ Advanced Project

Voice-Controlled Home Assistant Using ESP32

Create your own smart home assistant with wake word detection, appliance control, and real-time sensor monitoring — all on an ESP32.

🎤 Voice Commands 🌡️ DHT22 Sensor 📺 I2C LCD ✅ Wokwi Ready 🔌 Relay Control

Project Overview

This project turns your ESP32 microcontroller into a fully functional voice-controlled home assistant. Using serial commands (simulated voice input), you can control lights, a fan, AC, and a door — while monitoring real-time temperature and humidity with a DHT22 sensor displayed on an I2C LCD.

The system features an RGB LED status indicator, a buzzer for audio feedback, and a clean serial interface. It's perfect for learning home automation concepts and can be extended with a real microphone module (INMP441) and Edge Impulse / TensorFlow Lite for true on-device voice recognition.

💡 Beginner Note You can run this completely in your browser using Wokwi — no hardware required! Use the Serial Monitor to type voice commands and see the assistant respond in real time.
⚠️ Difficulty: Advanced This project requires familiarity with Arduino C++, I2C devices, and basic electronics. For true voice input, ML knowledge is needed.

Key Features

🎤
Voice Commands Control all devices via serial/voice input with simple natural language
🌡️
Temp & Humidity Real-time DHT22 sensor readings, updated every 2 seconds
📺
LCD Display 16×2 I2C LCD shows device states and sensor values
🔴
RGB LED Status Blue = Ready, Yellow = Processing, Green = Done
🔔
Audio Feedback Buzzer beeps confirm commands or signals errors
🏠
Smart Control "turn on all" / "status" / individual device control

Components Required

🔲
ESP32 Dev Board ESP32 DevKit V1 or similar
🌡️
DHT22 Sensor Temperature & humidity
📺
16×2 I2C LCD Address 0x27, 4-wire I2C
💡
LEDs × 4 White, Blue, Cyan, Yellow
🔴
RGB LEDs × 3 Red, Green, Blue status
🔔
Buzzer Passive/active buzzer
Resistors × 7 220Ω each for LEDs
🎤
INMP441 Mic Optional: for real voice input
✅ Libraries Needed Install LiquidCrystal I2C and DHT sensor library by Adafruit in your Arduino IDE Library Manager before uploading.

Pin Connections & Wiring

Connect all components to the ESP32 as shown in the table below. All LEDs should be connected through 220Ω resistors.

Component ESP32 Pin Wire Color Notes
LCD SDAD21GreenI2C Data
LCD SCLD22YellowI2C Clock
LCD VCC / GND3V3 / GNDRed / Black
DHT22 SDAD15OrangeData pin
DHT22 VCC / GND3V3 / GNDRed / Black
Light LEDD13WhiteVia 220Ω
Fan LEDD12BlueVia 220Ω
AC LEDD14CyanVia 220Ω
Door LEDD27YellowVia 220Ω
RGB RedD25RedVia 220Ω
RGB GreenD26GreenVia 220Ω
RGB BlueD33BlueVia 220Ω
Buzzer +D32MagentaBuzzer – to GND

How It Works

The system works by reading text commands from the Serial Monitor (simulating speech-to-text output). Here's the complete processing pipeline:

🎤 Voice / Serial Input
⬇️ toLowerCase() + trim()
🔍 Command Matching
⚙️ Execute Action
🔔 Feedback

The loop() function handles three things concurrently using non-blocking timers: reading the DHT22 sensor every 2 seconds, processing incoming serial characters into a command string, and updating the LCD every 3 seconds.

When a command is received, the RGB LED turns yellow during processing, then returns to green when complete. Successful commands trigger a double-beep; unrecognized commands trigger a triple-beep error tone.

Full Arduino Code

Copy the complete code below and paste it into your Arduino IDE or Wokwi project as voice_home_assistant.ino.

Arduino C++ · voice_home_assistant.ino
/*
 * VOICE-CONTROLLED HOME ASSISTANT - ESP32
 *
 * Features:
 * - Voice command recognition via serial (simulated)
 * - Control multiple home devices (lights, fan, AC, door)
 * - Temperature and humidity monitoring (DHT22)
 * - LCD display for status
 * - RGB LED for visual feedback
 * - Buzzer for audio feedback
 *
 * Voice Commands:
 * - "turn on light" / "turn off light"
 * - "turn on fan"  / "turn off fan"
 * - "turn on ac"   / "turn off ac"
 * - "open door"    / "close door"
 * - "show temperature"
 * - "show humidity"
 * - "turn on all"  / "turn off all"
 * - "status"
 */

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <DHT.h>

// ── Pin Definitions ─────────────────────────────
#define DHT_PIN       15
#define DHT_TYPE      DHT22
#define LIGHT_PIN     13
#define FAN_PIN       12
#define AC_PIN        14
#define DOOR_SERVO_PIN 27
#define RGB_RED       25
#define RGB_GREEN     26
#define RGB_BLUE      33
#define BUZZER_PIN    32
#define MIC_PIN       34  // Analog pin for mic simulation

// ── I2C LCD & DHT ───────────────────────────────
LiquidCrystal_I2C lcd(0x27, 16, 2);
DHT dht(DHT_PIN, DHT_TYPE);

// ── Device States ───────────────────────────────
bool lightState = false;
bool fanState   = false;
bool acState    = false;
bool doorState  = false;  // false=closed, true=open

float temperature = 0;
float humidity    = 0;

// ── Voice Command Buffer ─────────────────────────
String voiceCommand = "";

// ── Function Prototypes ──────────────────────────
void processVoiceCommand(String command);
void controlLight(bool state);
void controlFan(bool state);
void controlAC(bool state);
void controlDoor(bool state);
void readSensors();
void updateLCD();
void setRGB(int r, int g, int b);
void playConfirmationBeep();
void playErrorBeep();
void printStatus();

// ── setup() ─────────────────────────────────────
void setup() {
  Serial.begin(115200);

  // Initialize LCD
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("Voice Home");
  lcd.setCursor(0, 1);
  lcd.print("Assistant");

  dht.begin();

  // Pin modes
  pinMode(LIGHT_PIN,      OUTPUT);
  pinMode(FAN_PIN,        OUTPUT);
  pinMode(AC_PIN,         OUTPUT);
  pinMode(DOOR_SERVO_PIN, OUTPUT);
  pinMode(RGB_RED,        OUTPUT);
  pinMode(RGB_GREEN,      OUTPUT);
  pinMode(RGB_BLUE,       OUTPUT);
  pinMode(BUZZER_PIN,     OUTPUT);
  pinMode(MIC_PIN,        INPUT);

  // Initial LOW states
  digitalWrite(LIGHT_PIN,      LOW);
  digitalWrite(FAN_PIN,        LOW);
  digitalWrite(AC_PIN,         LOW);
  digitalWrite(DOOR_SERVO_PIN, LOW);

  setRGB(0, 0, 255);       // Blue — starting up
  playConfirmationBeep();
  delay(2000);

  Serial.println("\n╔═══════════════════════════════════════╗");
  Serial.println("║   VOICE-CONTROLLED HOME ASSISTANT     ║");
  Serial.println("╚═══════════════════════════════════════╝\n");
  Serial.println("System Ready! Listening for commands...");
  Serial.println("\nAvailable Commands:");
  Serial.println("  - turn on/off light");
  Serial.println("  - turn on/off fan");
  Serial.println("  - turn on/off ac");
  Serial.println("  - open/close door");
  Serial.println("  - show temperature");
  Serial.println("  - show humidity");
  Serial.println("  - turn on/off all");
  Serial.println("  - status\n");

  lcd.clear();
  lcd.print("Ready!");
  setRGB(0, 255, 0);       // Green — ready
}

// ── loop() ──────────────────────────────────────
void loop() {
  // Read DHT sensor every 2 seconds
  static unsigned long lastSensorRead = 0;
  if (millis() - lastSensorRead > 2000) {
    readSensors();
    lastSensorRead = millis();
  }

  // Build command from serial characters
  if (Serial.available() > 0) {
    char c = Serial.read();
    if (c == '\n' || c == '\r') {
      if (voiceCommand.length() > 0) {
        voiceCommand.toLowerCase();
        voiceCommand.trim();
        Serial.println("\n🎤 Command: " + voiceCommand);
        setRGB(255, 255, 0);    // Yellow — processing
        processVoiceCommand(voiceCommand);
        voiceCommand = "";
        delay(500);
        setRGB(0, 255, 0);      // Green — done
      }
    } else {
      voiceCommand += c;
    }
  }

  // Refresh LCD every 3 seconds
  static unsigned long lastLCDUpdate = 0;
  if (millis() - lastLCDUpdate > 3000) {
    updateLCD();
    lastLCDUpdate = millis();
  }

  delay(50);
}

// ── Command Processor ───────────────────────────
void processVoiceCommand(String command) {
  bool recognized = true;

  if      (command.indexOf("turn on light") >= 0 || command.indexOf("light on") >= 0)
    { controlLight(true);  lcd.clear(); lcd.print("Light: ON");  }
  else if (command.indexOf("turn off light") >= 0 || command.indexOf("light off") >= 0)
    { controlLight(false); lcd.clear(); lcd.print("Light: OFF"); }
  else if (command.indexOf("turn on fan") >= 0 || command.indexOf("fan on") >= 0)
    { controlFan(true);    lcd.clear(); lcd.print("Fan: ON");    }
  else if (command.indexOf("turn off fan") >= 0 || command.indexOf("fan off") >= 0)
    { controlFan(false);   lcd.clear(); lcd.print("Fan: OFF");   }
  else if (command.indexOf("turn on ac") >= 0 || command.indexOf("ac on") >= 0
        || command.indexOf("turn on air") >= 0)
    { controlAC(true);     lcd.clear(); lcd.print("AC: ON");     }
  else if (command.indexOf("turn off ac") >= 0 || command.indexOf("ac off") >= 0
        || command.indexOf("turn off air") >= 0)
    { controlAC(false);    lcd.clear(); lcd.print("AC: OFF");    }
  else if (command.indexOf("open door") >= 0 || command.indexOf("door open") >= 0)
    { controlDoor(true);   lcd.clear(); lcd.print("Door: OPEN");   }
  else if (command.indexOf("close door") >= 0 || command.indexOf("door close") >= 0)
    { controlDoor(false);  lcd.clear(); lcd.print("Door: CLOSED"); }
  else if (command.indexOf("temperature") >= 0 || command.indexOf("temp") >= 0) {
    lcd.clear(); lcd.print("Temp: "); lcd.print(temperature); lcd.print("C");
    Serial.println("Temperature: " + String(temperature) + "°C");
    playConfirmationBeep();
  }
  else if (command.indexOf("humidity") >= 0) {
    lcd.clear(); lcd.print("Humidity: "); lcd.print(humidity); lcd.print("%");
    Serial.println("Humidity: " + String(humidity) + "%");
    playConfirmationBeep();
  }
  else if (command.indexOf("turn on all") >= 0 || command.indexOf("all on") >= 0) {
    controlLight(true); controlFan(true); controlAC(true);
    lcd.clear(); lcd.print("All Devices: ON");
  }
  else if (command.indexOf("turn off all") >= 0 || command.indexOf("all off") >= 0) {
    controlLight(false); controlFan(false); controlAC(false);
    lcd.clear(); lcd.print("All Devices: OFF");
  }
  else if (command.indexOf("status") >= 0) {
    printStatus();
  }
  else {
    recognized = false;
    Serial.println("❌ Command not recognized!");
    lcd.clear(); lcd.print("Unknown Cmd");
    playErrorBeep();
  }

  if (recognized
    && command.indexOf("temperature") < 0
    && command.indexOf("humidity")    < 0
    && command.indexOf("status")      < 0) {
    playConfirmationBeep();
    Serial.println("✅ Command executed!");
  }
  delay(2000);
}

// ── Device Control Helpers ──────────────────────
void controlLight(bool state) {
  lightState = state;
  digitalWrite(LIGHT_PIN, state ? HIGH : LOW);
  Serial.println("💡 Light: " + String(state ? "ON" : "OFF"));
}
void controlFan(bool state) {
  fanState = state;
  digitalWrite(FAN_PIN, state ? HIGH : LOW);
  Serial.println("🌀 Fan: " + String(state ? "ON" : "OFF"));
}
void controlAC(bool state) {
  acState = state;
  digitalWrite(AC_PIN, state ? HIGH : LOW);
  Serial.println("❄️  AC: " + String(state ? "ON" : "OFF"));
}
void controlDoor(bool state) {
  doorState = state;
  if (state) {
    for (int i = 0; i <= 90; i += 5)
      { analogWrite(DOOR_SERVO_PIN, map(i,0,180,0,255)); delay(15); }
  } else {
    for (int i = 90; i >= 0; i -= 5)
      { analogWrite(DOOR_SERVO_PIN, map(i,0,180,0,255)); delay(15); }
  }
  Serial.println("🚪 Door: " + String(state ? "OPEN" : "CLOSED"));
}

// ── Sensor & Display ────────────────────────────
void readSensors() {
  humidity    = dht.readHumidity();
  temperature = dht.readTemperature();
  if (isnan(humidity) || isnan(temperature)) {
    temperature = 25.0 + random(-5,5);
    humidity    = 60.0 + random(-10,10);
  }
}

void updateLCD() {
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("T:"); lcd.print(temperature,1); lcd.print("C H:"); lcd.print(humidity,0); lcd.print("%");
  lcd.setCursor(0,1);
  lcd.print("L:"); lcd.print(lightState?"1":"0");
  lcd.print(" F:"); lcd.print(fanState?"1":"0");
  lcd.print(" A:"); lcd.print(acState?"1":"0");
  lcd.print(" D:"); lcd.print(doorState?"O":"C");
}

// ── RGB & Buzzer ────────────────────────────────
void setRGB(int r, int g, int b) {
  analogWrite(RGB_RED,   r);
  analogWrite(RGB_GREEN, g);
  analogWrite(RGB_BLUE,  b);
}
void playConfirmationBeep() {
  tone(BUZZER_PIN, 1000, 100); delay(150);
  tone(BUZZER_PIN, 1500, 100);
}
void playErrorBeep() {
  for (int i=0; i<3; i++) { tone(BUZZER_PIN,500,100); delay(150); }
}

// ── Status Print ────────────────────────────────
void printStatus() {
  Serial.println("\n╔════════════ SYSTEM STATUS ════════════╗");
  Serial.println("║ Light:       " + String(lightState?"ON ":"OFF") + "                   ║");
  Serial.println("║ Fan:         " + String(fanState  ?"ON ":"OFF") + "                   ║");
  Serial.println("║ AC:          " + String(acState   ?"ON ":"OFF") + "                   ║");
  Serial.println("║ Door:        " + String(doorState ?"OPEN  ":"CLOSED") + "                ║");
  Serial.println("║ Temperature: " + String(temperature) + "°C               ║");
  Serial.println("║ Humidity:    " + String(humidity)    + "%                 ║");
  Serial.println("╚═══════════════════════════════════════╝\n");
  lcd.clear(); lcd.print("Status Shown");
  playConfirmationBeep();
}

Wokwi diagram.json

Save this as diagram.json in your Wokwi project. It defines all components and their connections automatically.

JSON · diagram.json
{
  "version": 1,
  "author": "Voice Home Assistant",
  "editor": "wokwi",
  "parts": [
    { "type": "wokwi-esp32-devkit-v1", "id": "esp", "top": 0, "left": 0, "attrs": {} },
    {
      "type": "wokwi-lcd1602", "id": "lcd1",
      "top": -100, "left": 200,
      "attrs": { "pins": "i2c" }
    },
    { "type": "wokwi-dht22", "id": "dht1", "top": 240.3, "left": 369, "attrs": {} },
    { "type": "wokwi-led", "id": "led1",
      "top": -50, "left": 500,
      "attrs": { "color": "white", "label": "Light" } },
    { "type": "wokwi-led", "id": "led2",
      "top": 10, "left": 500,
      "attrs": { "color": "blue", "label": "Fan" } },
    { "type": "wokwi-led", "id": "led3",
      "top": 70, "left": 500,
      "attrs": { "color": "cyan", "label": "AC" } },
    { "type": "wokwi-led", "id": "led4",
      "top": 130, "left": 500,
      "attrs": { "color": "yellow", "label": "Door" } },
    { "type": "wokwi-led", "id": "rgb_red",
      "top": -80, "left": 600,
      "attrs": { "color": "red", "label": "RGB-R" } },
    { "type": "wokwi-led", "id": "rgb_green",
      "top": -20, "left": 600,
      "attrs": { "color": "green", "label": "RGB-G" } },
    { "type": "wokwi-led", "id": "rgb_blue",
      "top": 40, "left": 600,
      "attrs": { "color": "blue", "label": "RGB-B" } },
    { "type": "wokwi-buzzer", "id": "bz1", "top": 120, "left": 600, "attrs": {} },
    { "type": "wokwi-resistor", "id": "r1", "top": -50,  "left": 550, "attrs": { "value": "220" } },
    { "type": "wokwi-resistor", "id": "r2", "top": 10,   "left": 550, "attrs": { "value": "220" } },
    { "type": "wokwi-resistor", "id": "r3", "top": 70,   "left": 550, "attrs": { "value": "220" } },
    { "type": "wokwi-resistor", "id": "r4", "top": 130,  "left": 550, "attrs": { "value": "220" } },
    { "type": "wokwi-resistor", "id": "r5", "top": -80,  "left": 650, "attrs": { "value": "220" } },
    { "type": "wokwi-resistor", "id": "r6", "top": -20,  "left": 650, "attrs": { "value": "220" } },
    { "type": "wokwi-resistor", "id": "r7", "top": 40,   "left": 650, "attrs": { "value": "220" } }
  ],
  "connections": [
    [ "esp:TX0",    "$serialMonitor:RX", "",       [] ],
    [ "esp:RX0",    "$serialMonitor:TX", "",       [] ],
    [ "esp:GND.1",  "lcd1:GND",          "black",  [] ],
    [ "esp:3V3",    "lcd1:VCC",          "red",    [] ],
    [ "esp:D21",    "lcd1:SDA",          "green",  [] ],
    [ "esp:D22",    "lcd1:SCL",          "yellow", [] ],
    [ "esp:D15",    "dht1:SDA",          "orange", [] ],
    [ "esp:3V3",    "dht1:VCC",          "red",    [] ],
    [ "esp:GND.1",  "dht1:GND",          "black",  [] ],
    [ "esp:D13",    "r1:1",              "white",  [] ],
    [ "r1:2",       "led1:A",            "white",  [] ],
    [ "led1:C",     "esp:GND.2",         "black",  [] ],
    [ "esp:D12",    "r2:1",              "blue",   [] ],
    [ "r2:2",       "led2:A",            "blue",   [] ],
    [ "led2:C",     "esp:GND.2",         "black",  [] ],
    [ "esp:D14",    "r3:1",              "cyan",   [] ],
    [ "r3:2",       "led3:A",            "cyan",   [] ],
    [ "led3:C",     "esp:GND.2",         "black",  [] ],
    [ "esp:D27",    "r4:1",              "yellow", [] ],
    [ "r4:2",       "led4:A",            "yellow", [] ],
    [ "led4:C",     "esp:GND.2",         "black",  [] ],
    [ "esp:D25",    "r5:1",              "red",    [] ],
    [ "r5:2",       "rgb_red:A",         "red",    [] ],
    [ "rgb_red:C",  "esp:GND.2",         "black",  [] ],
    [ "esp:D26",    "r6:1",              "green",  [] ],
    [ "r6:2",       "rgb_green:A",       "green",  [] ],
    [ "rgb_green:C","esp:GND.2",         "black",  [] ],
    [ "esp:D33",    "r7:1",              "blue",   [] ],
    [ "r7:2",       "rgb_blue:A",        "blue",   [] ],
    [ "rgb_blue:C", "esp:GND.2",         "black",  [] ],
    [ "esp:D32",    "bz1:1",             "magenta",[] ],
    [ "bz1:2",      "esp:GND.2",         "black",  [] ]
  ],
  "dependencies": {}
}

Voice Commands Reference

Type any of these commands into the Wokwi Serial Monitor (press Enter to send):

turn on lightTurns the light LED on
turn off lightTurns the light LED off
turn on fanTurns the fan LED on
turn off fanTurns the fan LED off
turn on acActivates the AC (also: "turn on air")
turn off acDeactivates the AC
open doorSimulates door servo opening to 90°
close doorSimulates door servo closing to 0°
show temperatureDisplays current DHT22 temperature on LCD
show humidityDisplays current DHT22 humidity on LCD
turn on allTurns on Light, Fan, and AC simultaneously
turn off allTurns off all devices at once
statusPrints full system status to Serial Monitor

Run the Wokwi Simulation

1
Open Wokwi and create a new ESP32 project

Go to wokwi.com, click New Project, and choose ESP32 as your board.

2
Replace sketch.ino with the code above

Delete the default code and paste the full Arduino sketch from Step 06. Save the file as voice_home_assistant.ino.

3
Replace diagram.json with the wiring above

Click the diagram.json tab in Wokwi, select all, and paste the JSON from Step 07. All components will appear automatically wired.

4
Add the required libraries

Click the Library Manager icon in Wokwi (or add to libraries.txt): add LiquidCrystal I2C and DHT sensor library.

5
Start simulation & test commands

Click the ▶ Play button. Once the Serial Monitor shows "System Ready!", type a command like turn on light and press Enter. Watch the LED light up and the LCD update!

🔬 Try it Live in Your Browser

No hardware needed — run the full simulation instantly on Wokwi

▶ Open Free Simulation

© 2026 MakeMindz · ESP32 Tutorials & IoT Projects · Salem, Tamil Nadu

Comments

try for free