Smart home automation system using ESP 32 Wowki simulator

ESP32 Smart Home Automation System – Web-Controlled IoT Project | MakeMindz
ESP32 IoT Project Wokwi Ready Beginner–Advanced

🏠 Smart Home Automation System using ESP32

Build a fully web-controlled IoT home system with DHT22 sensors, PIR motion detection, OLED display, and an HTTP control panel. Fully testable in Wokwi — no hardware needed.

🌡️

DHT22 Sensor

Real-time temperature & humidity monitoring with auto fan control logic.

🚶

PIR Motion Detection

Detects movement and automatically controls the smart light in AUTO mode.

🌐

Web Control Panel

Built-in HTTP server at port 80 — control everything from your browser.

📺

OLED Display

128×64 SSD1306 screen shows live temp, humidity, light, fan & mode status.

🔔

Buzzer Alerts

Audible alarm triggers when temperature exceeds safe threshold.

⚙️

AUTO / MANUAL Modes

Toggle between sensor-driven automation and full manual web control.

How the System Works

The ESP32 connects to WiFi and spins up a web server. Sensors are polled every 2 seconds — in AUTO mode, the firmware makes all decisions; in MANUAL mode, you're in charge via the web panel.

⚡ AUTO Mode

  • Motion detected → Light ON
  • No motion → Light OFF
  • Temp > 28°C → Fan ON + Buzzer
  • Temp ≤ 26°C → Fan OFF

🕹️ MANUAL Mode

  • Toggle Light via web
  • Toggle Fan via web
  • Switch modes anytime
  • Monitor sensor data live

📌 Pin Configuration

All connections for the ESP32 DevKit V1. Use these with the diagram.json below in Wokwi.

Component GPIO Pin Notes
DHT22 Temp/HumidityGPIO 15Data pin (SDA)
PIR Motion SensorGPIO 14Digital input (OUT)
Light LEDGPIO 26Yellow LED + 220Ω resistor
Fan LEDGPIO 27Blue LED + 220Ω resistor
BuzzerGPIO 25Passive buzzer
OLED SDAGPIO 21I2C Data (0x3C)
OLED SCLGPIO 22I2C Clock

🚀 Step-by-Step Instructions

Follow these steps to get the project running in Wokwi in under 5 minutes.

01

Open Wokwi Simulator

Go to wokwi.com/projects/new/esp32 and create a new ESP32 project.

02

Paste the Arduino Code

Copy the full .ino code from the section below and paste it into the Wokwi code editor (replacing the default sketch).

03

Replace diagram.json

Click the diagram.json tab in Wokwi, clear its contents, and paste the full diagram JSON from below to automatically place all components and wires.

04

Install Required Libraries

Click the ≡ menu → Library Manager and install: DHT sensor library, Adafruit GFX Library, and Adafruit SSD1306.

05

Start Simulation

Click the green ▶ Start Simulation button. Wait for the OLED to show "Smart Home" and the Serial Monitor to print the IP address.

06

Open the Web Control Panel

Open the Serial Monitor, copy the printed IP address, and paste it in the Wokwi browser tool to access the live control panel. 🎉

07

Interact with Sensors

Click the PIR sensor in the simulator to trigger motion. Drag the DHT22 temperature slider above 28°C to trigger the fan and buzzer automatically.

📡 WiFi Note: The code uses Wokwi-GUEST as the SSID (no password). This works automatically in the Wokwi simulator. For real hardware, replace with your own credentials.

💻 Full Arduino Code (.ino)

Complete, commented code ready to paste into Wokwi or Arduino IDE.

smart_home.ino
/*
 * ESP32 Smart Home Automation System
 * MakeMindz.com
 * Features: DHT22, PIR, LED Light, Fan LED, OLED, Web Server
 */

#include <WiFi.h>
#include <WebServer.h>
#include <DHT.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// WiFi Credentials (for Wokwi simulation)
const char* ssid     = "Wokwi-GUEST";
const char* password = "";

// Pin Definitions
#define DHT_PIN    15
#define PIR_PIN    14
#define LIGHT_PIN  26
#define FAN_PIN    27
#define BUZZER_PIN 25

#define DHT_TYPE   DHT22
DHT dht(DHT_PIN, DHT_TYPE);

// OLED Setup (128x64 SSD1306 via I2C)
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

WebServer server(80);

// State variables
float   temperature    = 0;
float   humidity       = 0;
bool    lightStatus    = false;
bool    fanStatus      = false;
bool    motionDetected = false;
bool    autoMode       = true;
unsigned long lastSensorRead = 0;
const long    sensorInterval = 2000;

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

  pinMode(PIR_PIN,    INPUT);
  pinMode(LIGHT_PIN,  OUTPUT);
  pinMode(FAN_PIN,    OUTPUT);
  pinMode(BUZZER_PIN, OUTPUT);

  dht.begin();

  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  }
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.println("Smart Home");
  display.println("Initializing...");
  display.display();
  delay(2000);

  WiFi.begin(ssid, password);
  Serial.print("Connecting to WiFi");
  display.clearDisplay();
  display.setCursor(0, 0);
  display.println("Connecting WiFi...");
  display.display();

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("\nWiFi connected");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  server.on("/",             handleRoot);
  server.on("/light/on",    handleLightOn);
  server.on("/light/off",   handleLightOff);
  server.on("/fan/on",      handleFanOn);
  server.on("/fan/off",     handleFanOff);
  server.on("/mode/auto",   handleAutoMode);
  server.on("/mode/manual", handleManualMode);
  server.on("/status",      handleStatus);

  server.begin();
  Serial.println("HTTP server started");
  updateDisplay();
}

void loop() {
  server.handleClient();
  unsigned long now = millis();
  if (now - lastSensorRead >= sensorInterval) {
    lastSensorRead = now;
    readSensors();
    if (autoMode) autoControl();
    updateDisplay();
  }
}

void readSensors() {
  temperature    = dht.readTemperature();
  humidity       = dht.readHumidity();
  motionDetected = digitalRead(PIR_PIN);
  if (isnan(temperature) || isnan(humidity)) {
    temperature = 0; humidity = 0;
  }
}

void autoControl() {
  // Light: motion-based
  if (motionDetected && !lightStatus) {
    lightStatus = true;
    digitalWrite(LIGHT_PIN, HIGH);
  } else if (!motionDetected && lightStatus) {
    lightStatus = false;
    digitalWrite(LIGHT_PIN, LOW);
  }
  // Fan: temperature-based
  if (temperature > 28 && !fanStatus) {
    fanStatus = true;
    digitalWrite(FAN_PIN, HIGH);
    tone(BUZZER_PIN, 1000, 200); // alert beep
  } else if (temperature <= 26 && fanStatus) {
    fanStatus = false;
    digitalWrite(FAN_PIN, LOW);
  }
}

void updateDisplay() {
  display.clearDisplay();
  display.setCursor(0, 0);
  display.setTextSize(1);
  display.println("SMART HOME");
  display.drawLine(0, 10, 128, 10, SSD1306_WHITE);
  display.setCursor(0, 14);
  display.print("Temp: ");  display.print(temperature, 1); display.println(" C");
  display.setCursor(0, 24);
  display.print("Humid: "); display.print(humidity, 1);    display.println(" %");
  display.setCursor(0, 34);
  display.print("Light: "); display.println(lightStatus ? "ON" : "OFF");
  display.setCursor(0, 44);
  display.print("Fan:   "); display.println(fanStatus   ? "ON" : "OFF");
  display.setCursor(0, 54);
  display.print("Mode:  "); display.println(autoMode   ? "AUTO" : "MANUAL");
  display.display();
}

/* -------- Web Handlers -------- */
void handleRoot() {
  String html = "<!DOCTYPE html><html><head>";
  html += "<meta name='viewport' content='width=device-width, initial-scale=1.0'>";
  html += "<style>body{font-family:Arial;text-align:center;background:#f0f0f0;padding:20px}";
  html += ".container{max-width:500px;margin:0 auto;background:white;padding:20px;border-radius:10px}";
  html += ".sensor{background:#e3f2fd;padding:15px;margin:10px 0;border-radius:5px}";
  html += ".button{display:inline-block;padding:15px 30px;margin:5px;font-size:16px;cursor:pointer;";
  html += "border:none;border-radius:5px;color:white;text-decoration:none}";
  html += ".on{background:#4CAF50}.off{background:#f44336}.mode{background:#2196F3}</style>";
  html += "</head><body><div class='container'><h1>🏠 Smart Home Control</h1>";
  html += "<div class='sensor'><h3>📊 Sensors</h3>";
  html += "<p>🌡️ Temp: <b>" + String(temperature,1) + " °C</b></p>";
  html += "<p>💧 Humidity: <b>" + String(humidity,1) + " %</b></p>";
  html += "<p>🚶 Motion: <b>" + String(motionDetected?"Detected":"None") + "</b></p></div>";
  html += "<div class='sensor'><h3>💡 Light — " + String(lightStatus?"ON":"OFF") + "</h3>";
  html += "<a href='/light/on' class='button on'>Turn ON</a>";
  html += "<a href='/light/off' class='button off'>Turn OFF</a></div>";
  html += "<div class='sensor'><h3>🌀 Fan — " + String(fanStatus?"ON":"OFF") + "</h3>";
  html += "<a href='/fan/on' class='button on'>Turn ON</a>";
  html += "<a href='/fan/off' class='button off'>Turn OFF</a></div>";
  html += "<div class='sensor'><h3>⚙️ Mode — " + String(autoMode?"AUTO":"MANUAL") + "</h3>";
  html += "<a href='/mode/auto' class='button mode'>AUTO</a>";
  html += "<a href='/mode/manual' class='button mode'>MANUAL</a></div>";
  html += "<p style='font-size:12px;color:#999'>IP: " + WiFi.localIP().toString() + "</p>";
  html += "</div></body></html>";
  server.send(200, "text/html", html);
}

void handleLightOn()  { lightStatus=true;  digitalWrite(LIGHT_PIN,HIGH); server.sendHeader("Location","/"); server.send(303); }
void handleLightOff() { lightStatus=false; digitalWrite(LIGHT_PIN,LOW);  server.sendHeader("Location","/"); server.send(303); }
void handleFanOn()    { fanStatus=true;   digitalWrite(FAN_PIN,HIGH);   server.sendHeader("Location","/"); server.send(303); }
void handleFanOff()   { fanStatus=false;  digitalWrite(FAN_PIN,LOW);    server.sendHeader("Location","/"); server.send(303); }
void handleAutoMode()   { autoMode=true;  server.sendHeader("Location","/"); server.send(303); }
void handleManualMode() { autoMode=false; server.sendHeader("Location","/"); server.send(303); }

void handleStatus() {
  String json = "{";
  json += "\"temperature\":" + String(temperature,1) + ",";
  json += "\"humidity\":"    + String(humidity,1)    + ",";
  json += "\"motion\":"      + String(motionDetected?"true":"false") + ",";
  json += "\"light\":"       + String(lightStatus?"true":"false") + ",";
  json += "\"fan\":"         + String(fanStatus?"true":"false")   + ",";
  json += "\"mode\":\""      + String(autoMode?"auto":"manual")   + "\"";
  json += "}";
  server.send(200, "application/json", json);
}

📐 diagram.json

Paste this into the diagram.json tab in Wokwi to auto-wire all components — ESP32, DHT22, PIR, LEDs, buzzer, and OLED.

diagram.json
{
  "version": 1,
  "author": "ESP32 Smart Home Automation — MakeMindz.com",
  "editor": "wokwi",
  "parts": [
    { "type": "wokwi-esp32-devkit-v1", "id": "esp",  "top": 0,      "left": 0,      "attrs": {} },
    { "type": "wokwi-dht22",           "id": "dht1", "top": -67.2,  "left": 105.6,  "attrs": { "temperature": "8.7", "humidity": "62.5" } },
    { "type": "wokwi-pir-motion-sensor","id": "pir1","top": -105.49,"left": 230.11, "attrs": {} },
    { "type": "wokwi-led",             "id": "led1", "top": -180,   "left": 340,    "attrs": { "color": "yellow", "lightColor": "yellow" } },
    { "type": "wokwi-resistor",        "id": "r1",   "top": -120,   "left": 345,    "rotate": 90, "attrs": { "value": "220" } },
    { "type": "wokwi-led",             "id": "led2", "top": -205.2, "left": 378.2,  "attrs": { "color": "blue",   "lightColor": "blue"   } },
    { "type": "wokwi-resistor",        "id": "r2",   "top": -120,   "left": 405,    "rotate": 90, "attrs": { "value": "220" } },
    { "type": "wokwi-buzzer",          "id": "bz1",  "top": -120,   "left": 480,    "attrs": { "volume": "0.5" } },
    { "type": "wokwi-ssd1306",         "id": "oled1","top": 121.9,  "left": 241.9,  "attrs": { "i2cAddress": "0x3C" } }
  ],
  "connections": [
    [ "esp:TX0",    "$serialMonitor:RX", "", [] ],
    [ "esp:RX0",    "$serialMonitor:TX", "", [] ],
    [ "dht1:VCC",   "esp:3V3",    "red",    ["v0"] ],
    [ "dht1:GND",   "esp:GND.1",  "black",  ["v0"] ],
    [ "dht1:SDA",   "esp:D15",    "green",  ["v0"] ],
    [ "pir1:VCC",   "esp:3V3",    "red",    ["v0"] ],
    [ "pir1:GND",   "esp:GND.1",  "black",  ["v0"] ],
    [ "pir1:OUT",   "esp:D14",    "orange", ["v0"] ],
    [ "led1:A",     "esp:D26",    "yellow", ["v-9.6","h-48"] ],
    [ "led1:C",     "r1:1",       "yellow", ["v0"] ],
    [ "r1:2",       "esp:GND.2",  "black",  ["h0"] ],
    [ "led2:A",     "esp:D27",    "blue",   ["v-9.6","h-96"] ],
    [ "led2:C",     "r2:1",       "blue",   ["v0"] ],
    [ "r2:2",       "esp:GND.2",  "black",  ["h0"] ],
    [ "bz1:1",      "esp:D25",    "green",  ["v0"] ],
    [ "bz1:2",      "esp:GND.2",  "black",  ["v0"] ],
    [ "oled1:VCC",  "esp:3V3",    "red",    ["h0"] ],
    [ "oled1:GND",  "esp:GND.2",  "black",  ["h0"] ],
    [ "oled1:SDA",  "esp:D21",    "blue",   ["h0"] ],
    [ "oled1:SCL",  "esp:D22",    "yellow", ["h0"] ]
  ],
  "dependencies": {}
}

▶ Try It Now in Wokwi

No hardware? No problem. Simulate the full project in your browser — interact with sensors, open the web panel, and see the OLED update live.

🚀 Launch Wokwi Simulator

📚 What You'll Learn

This project is a complete IoT curriculum in a single sketch. By building it, you'll gain hands-on experience with:

📡 WiFi Networking 🌐 HTTP Web Server 🔗 HTTP Route Handling 🔢 JSON API Responses 🌡️ DHT22 Sensor Integration 🚶 PIR Motion Sensing 📺 I2C OLED Display ⚡ Automation Algorithms 🗂️ IoT State Management 🔔 Buzzer Tone Control

🛠️ Advanced Improvements to Try

Once you've got the base project running, extend it with these ideas to level up your skills:

🔐 Login Authentication 📱 Mobile Dashboard Upgrade ☁️ Cloud Logging (Firebase / ThingSpeak) 📊 Real-Time Charts with AJAX 🎙️ Google Assistant Voice Control 📲 Telegram Alert Notifications ⚡ Relay for Real AC Devices 🗄️ Data History Logging 📡 MQTT Protocol Integration

🔗 More ESP32 Projects on MakeMindz

Hands-on Electronics & IoT Tutorials · makemindz.com

Built with ESP32 · Wokwi · Arduino IDE

Comments

try for free