Smart Parking System Using Ultrasonic Sensors WITH ESP 32

ESP32 Smart Parking System with WiFi & IoT | MakeMindz Tutorial
🅿️

ESP32 IoT Projects · Intermediate

ESP32 Smart Parking System with WiFi & IoT

Detect available parking slots in real time, control a servo barrier gate, display status on an LCD, and monitor everything from a live web dashboard.

⚡ ESP32 + WiFi 📡 3× HC-SR04 Sensors 🎯 Intermediate Level 🔧 Wokwi Ready

This project builds a fully intelligent parking management system on an ESP32. Three HC-SR04 ultrasonic sensors continuously monitor whether parking slots are occupied. A servo motor acts as a barrier gate, a 16×2 LCD shows real-time availability, and a beautiful web dashboard lets you monitor and control everything remotely from any browser.

The system also exposes a RESTful JSON API so mobile apps can query slot status and trigger the gate — making it a complete IoT foundation for real-world parking deployments.

ESP32 WiFi HC-SR04 Ultrasonic Sensor Servo Motor LCD 16×2 I2C RESTful API WebServer Buzzer Wokwi

🔧 Hardware

  • 3 parking slots with HC-SR04 ultrasonic sensors
  • 16×2 LCD display (I2C at 0x27)
  • Servo motor barrier gate (0° closed / 90° open)
  • 5 LEDs — 3× green slot, 1× red full, 1× blue WiFi
  • Buzzer for entry/exit alerts & full warning
  • ENTRY and EXIT push buttons (INPUT_PULLUP)

📡 Software & IoT

  • WiFi connectivity with auto-reconnect
  • Web dashboard with modern gradient UI
  • Mobile-ready responsive layout
  • Auto-refresh live updates every 2 seconds
  • RESTful JSON API endpoints
  • Entry/exit statistics & uptime tracking
  • Scalable architecture — add more slots easily
🚗
Auto Slot Detection 15 cm threshold triggers occupied/available status
🚧
Servo Barrier Gate Auto-closes after 3 seconds — no manual reset needed
🌐
Live Web Dashboard See slot status, open gate, view stats from browser
🔌
JSON REST API /api/status · /api/open · /api/stats endpoints
📊
Statistics Tracking Total entries, exits, uptime & WiFi signal strength
🔔
Buzzer Alerts Single beep for entry/exit, triple beep when full
ComponentQtyPurpose
ESP32 DevKit V11Main controller with WiFi / dual-core 240 MHz
HC-SR04 Ultrasonic Sensor3Detect car presence in each parking slot
Servo Motor (SG90)1Barrier gate — 0° closed, 90° open
16×2 LCD (I2C 0x27)1Show available/occupied count on-site
Passive Buzzer1Entry, exit & "parking full" audio alerts
LED Green3Slot available indicators (Slot 1, 2, 3)
LED Red1Parking full indicator
LED Blue1WiFi connected / heartbeat blink
220Ω Resistors5Current limiting for all LEDs
Push Buttons (Green/Red)2Manual ENTRY and EXIT triggers
💡
The HC-SR04 operates at 5V. In Wokwi it's connected to VIN (5V pin). In a real ESP32 build, use a voltage divider on the ECHO pin (5V → 3.3V) to protect the GPIO, or use a 3.3V-compatible sensor like the HC-SR04P.
ComponentESP32 PinWire Color
Ultrasonic 1 TRIGD13🟠 Orange
Ultrasonic 1 ECHOD12🟣 Purple
Ultrasonic 2 TRIGD14🟠 Orange
Ultrasonic 2 ECHOD27🟣 Purple
Ultrasonic 3 TRIGD26🟠 Orange
Ultrasonic 3 ECHOD25🟣 Purple
All Ultrasonics VCCVIN (5V)🔴 Red
Servo SIGD15🟠 Orange
Servo VCCVIN🔴 Red
LCD SDAD21🔵 Blue
LCD SCLD22🟡 Yellow
LCD VCC3V3🔴 Red
LED Slot 1 (Green)D16 via 220Ω🟢 Green
LED Slot 2 (Green)D17 via 220Ω🟢 Green
LED Slot 3 (Green)D18 via 220Ω🟢 Green
LED Full (Red)D19 via 220Ω🔴 Red
LED WiFi (Blue)D2 via 220Ω🔵 Blue
BuzzerD23🟠 Orange
ENTRY ButtonD32 (INPUT_PULLUP)🟢 Green
EXIT ButtonD33 (INPUT_PULLUP)🔴 Red
A

Go to wokwi.com and create a new ESP32 project

Make sure you select ESP32 (not Arduino Uno). The library set is different and includes WiFi, WebServer, and ESP32Servo.

B

Paste the diagram.json content

Click the diagram.json tab in Wokwi and replace all content with the JSON from Section 6 below. This loads all components pre-wired.

C

Paste the sketch.ino code

Click the sketch.ino tab and replace with the code from Section 7. All libraries (WiFi, WebServer, LiquidCrystal_I2C, ESP32Servo) are auto-installed in Wokwi.

D

Press ▶ Start and check Serial Monitor

WiFi connects in ~10 seconds. The Serial Monitor shows the IP address. Click it to open the live web dashboard in a new browser tab.

📦
Required Libraries: LiquidCrystal_I2C and ESP32Servo. Install via Arduino Library Manager for real hardware builds. These come pre-installed in Wokwi.

Copy this into your diagram.json tab in Wokwi to instantly load the fully wired circuit with all 3 ultrasonic sensors, servo, LCD, LEDs, buttons, and buzzer.

diagram.json
{
  "version": 1,
  "author": "ESP32 Smart Parking",
  "editor": "wokwi",
  "parts": [
    { "type": "wokwi-esp32-devkit-v1", "id": "esp32", "top": 0, "left": 0, "attrs": {} },
    { "type": "wokwi-lcd1602", "id": "lcd1", "top": -150, "left": 115.2,
      "attrs": { "pins": "i2c" } },
    { "type": "wokwi-hc-sr04", "id": "ultrasonic1", "top": -240, "left": -150,
      "attrs": { "distance": "400" } },
    { "type": "wokwi-hc-sr04", "id": "ultrasonic2", "top": -240, "left": 0,
      "attrs": { "distance": "400" } },
    { "type": "wokwi-hc-sr04", "id": "ultrasonic3", "top": -240, "left": 150,
      "attrs": { "distance": "400" } },
    { "type": "wokwi-servo", "id": "servo1", "top": 140, "left": -144, "attrs": {} },
    { "type": "wokwi-led", "id": "led1", "top": 280, "left": -140,
      "attrs": { "color": "green" } },
    { "type": "wokwi-led", "id": "led2", "top": 280, "left": -50,
      "attrs": { "color": "green" } },
    { "type": "wokwi-led", "id": "led3", "top": 280, "left": 40,
      "attrs": { "color": "green" } },
    { "type": "wokwi-led", "id": "led4", "top": 280, "left": 130,
      "attrs": { "color": "red" } },
    { "type": "wokwi-resistor", "id": "r1", "top": 318, "left": -144.8, "rotate": 90,
      "attrs": { "value": "220" } },
    { "type": "wokwi-resistor", "id": "r2", "top": 318, "left": -54.8, "rotate": 90,
      "attrs": { "value": "220" } },
    { "type": "wokwi-resistor", "id": "r3", "top": 318, "left": 35.2, "rotate": 90,
      "attrs": { "value": "220" } },
    { "type": "wokwi-resistor", "id": "r4", "top": 318, "left": 125.2, "rotate": 90,
      "attrs": { "value": "220" } },
    { "type": "wokwi-buzzer", "id": "bz1", "top": 140, "left": 336, "attrs": {} },
    { "type": "wokwi-pushbutton", "id": "btn1", "top": 270, "left": 316.8,
      "attrs": { "color": "green", "label": "ENTRY" } },
    { "type": "wokwi-pushbutton", "id": "btn2", "top": 270, "left": 412.8,
      "attrs": { "color": "red", "label": "EXIT" } },
    { "type": "wokwi-led", "id": "led5", "top": 140, "left": 240,
      "attrs": { "color": "blue", "label": "WiFi" } },
    { "type": "wokwi-resistor", "id": "r5", "top": 178, "left": 235.2, "rotate": 90,
      "attrs": { "value": "220" } }
  ],
  "connections": [
    ["esp32:TX0", "$serialMonitor:RX", "", []],
    ["esp32:RX0", "$serialMonitor:TX", "", []],
    ["lcd1:GND", "esp32:GND.1", "black", ["h0"]],
    ["lcd1:VCC", "esp32:3V3", "red", ["h0"]],
    ["lcd1:SDA", "esp32:D21", "blue", ["h0"]],
    ["lcd1:SCL", "esp32:D22", "yellow", ["h0"]],
    ["ultrasonic1:VCC", "esp32:VIN", "red", ["h0"]],
    ["ultrasonic1:GND", "esp32:GND.1", "black", ["h0"]],
    ["ultrasonic1:TRIG", "esp32:D13", "orange", ["h0"]],
    ["ultrasonic1:ECHO", "esp32:D12", "purple", ["h0"]],
    ["ultrasonic2:VCC", "esp32:VIN", "red", ["h0"]],
    ["ultrasonic2:GND", "esp32:GND.1", "black", ["h0"]],
    ["ultrasonic2:TRIG", "esp32:D14", "orange", ["h0"]],
    ["ultrasonic2:ECHO", "esp32:D27", "purple", ["h0"]],
    ["ultrasonic3:VCC", "esp32:VIN", "red", ["h0"]],
    ["ultrasonic3:GND", "esp32:GND.1", "black", ["h0"]],
    ["ultrasonic3:TRIG", "esp32:D26", "orange", ["h0"]],
    ["ultrasonic3:ECHO", "esp32:D25", "purple", ["h0"]],
    ["servo1:V+", "esp32:VIN", "red", ["h0"]],
    ["servo1:GND", "esp32:GND.2", "black", ["h0"]],
    ["servo1:SIG", "esp32:D15", "orange", ["h0"]],
    ["led1:A", "r1:1", "green", ["v0"]],
    ["r1:2", "esp32:D16", "green", ["v0"]],
    ["led1:C", "esp32:GND.1", "black", ["v0"]],
    ["led2:A", "r2:1", "green", ["v0"]],
    ["r2:2", "esp32:D17", "green", ["v0"]],
    ["led2:C", "esp32:GND.1", "black", ["v0"]],
    ["led3:A", "r3:1", "green", ["v0"]],
    ["r3:2", "esp32:D18", "green", ["v0"]],
    ["led3:C", "esp32:GND.1", "black", ["v0"]],
    ["led4:A", "r4:1", "red", ["v0"]],
    ["r4:2", "esp32:D19", "red", ["v0"]],
    ["led4:C", "esp32:GND.1", "black", ["v0"]],
    ["led5:A", "r5:1", "blue", ["v0"]],
    ["r5:2", "esp32:D2", "blue", ["v0"]],
    ["led5:C", "esp32:GND.2", "black", ["v0"]],
    ["bz1:1", "esp32:D23", "orange", ["h0"]],
    ["bz1:2", "esp32:GND.2", "black", ["h0"]],
    ["btn1:1.l", "esp32:D32", "green", ["h0"]],
    ["btn1:2.l", "esp32:GND.1", "black", ["h0"]],
    ["btn2:1.l", "esp32:D33", "red", ["h0"]],
    ["btn2:2.l", "esp32:GND.1", "black", ["h0"]]
  ],
  "dependencies": {}
}
sketch.ino
/*
 * ESP32 SMART PARKING SYSTEM WITH WiFi & IoT
 * MakeMindz.com — IoT Project Series
 *
 * Features: 3× HC-SR04 slots, WiFi web server,
 *           LCD (I2C), Servo gate, LEDs, Buzzer,
 *           Entry/Exit buttons, JSON REST API
 */

#include <WiFi.h>
#include <WebServer.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <ESP32Servo.h>

// ── WiFi Credentials ──────────────────────────
const char* ssid     = "Wokwi-GUEST";
const char* password = "";

// ── Ultrasonic Sensors ─────────────────────────
#define TRIG1 13  #define ECHO1 12   // Slot 1
#define TRIG2 14  #define ECHO2 27   // Slot 2
#define TRIG3 26  #define ECHO3 25   // Slot 3

// ── LEDs ──────────────────────────────────────
#define LED_SLOT1 16   // Green — Slot 1 available
#define LED_SLOT2 17   // Green — Slot 2 available
#define LED_SLOT3 18   // Green — Slot 3 available
#define LED_FULL  19   // Red   — Parking full
#define LED_WIFI  2    // Blue  — WiFi heartbeat

// ── Other Peripherals ─────────────────────────
#define SERVO_PIN  15
#define BUZZER_PIN 23
#define ENTRY_BTN  32
#define EXIT_BTN   33
// I2C: SDA = D21, SCL = D22 (ESP32 default)

// ── Global Objects ────────────────────────────
LiquidCrystal_I2C lcd(0x27, 16, 2);
Servo barrierGate;
WebServer server(80);

// ── State Variables ───────────────────────────
bool slot1Occupied = false, slot2Occupied = false, slot3Occupied = false;
int  availableSlots = 3;
const int totalSlots = 3;
const int THRESHOLD_DISTANCE = 15; // cm

bool          gateOpen     = false;
unsigned long gateOpenTime = 0;
const unsigned long GATE_AUTO_CLOSE = 3000;
const int GATE_CLOSED = 0, GATE_OPEN = 90;

unsigned long totalEntries = 0, totalExits = 0, systemUptime = 0;
bool wifiConnected = false;

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

  // LCD
  lcd.init(); lcd.backlight(); lcd.clear();
  lcd.setCursor(0,0); lcd.print("ESP32 PARKING");
  lcd.setCursor(0,1); lcd.print("Initializing...");

  // Pins
  pinMode(TRIG1,OUTPUT); pinMode(ECHO1,INPUT);
  pinMode(TRIG2,OUTPUT); pinMode(ECHO2,INPUT);
  pinMode(TRIG3,OUTPUT); pinMode(ECHO3,INPUT);
  pinMode(LED_SLOT1,OUTPUT); pinMode(LED_SLOT2,OUTPUT);
  pinMode(LED_SLOT3,OUTPUT); pinMode(LED_FULL,OUTPUT);
  pinMode(LED_WIFI,OUTPUT);
  pinMode(BUZZER_PIN,OUTPUT);
  pinMode(ENTRY_BTN,INPUT_PULLUP);
  pinMode(EXIT_BTN,INPUT_PULLUP);

  barrierGate.attach(SERVO_PIN);
  barrierGate.write(GATE_CLOSED);

  testLEDs();
  connectWiFi();
  setupWebServer();

  lcd.clear();
  lcd.setCursor(0,0); lcd.print("SYSTEM READY!");
  lcd.setCursor(0,1);
  if (wifiConnected) { lcd.print("IP:"); lcd.print(WiFi.localIP().toString().substring(0,11)); }
  else               { lcd.print("WiFi: Offline"); }
  delay(2000);
  systemUptime = millis();
}

// ──────────────────────────────────────────────
// LOOP
// ──────────────────────────────────────────────
void loop() {
  server.handleClient();
  checkParkingSlots();
  updateLCD();
  updateLEDs();

  // Entry button
  if (digitalRead(ENTRY_BTN) == LOW) {
    delay(50);
    if (digitalRead(ENTRY_BTN) == LOW) { handleEntry(); while(digitalRead(ENTRY_BTN)==LOW); }
  }
  // Exit button
  if (digitalRead(EXIT_BTN) == LOW) {
    delay(50);
    if (digitalRead(EXIT_BTN) == LOW) { handleExit(); while(digitalRead(EXIT_BTN)==LOW); }
  }
  // Auto-close gate after 3 seconds
  if (gateOpen && (millis() - gateOpenTime > GATE_AUTO_CLOSE)) closeGate();

  // WiFi LED heartbeat blink every 1 second
  static unsigned long lastBlink = 0;
  if (wifiConnected && millis() - lastBlink > 1000) {
    digitalWrite(LED_WIFI, !digitalRead(LED_WIFI));
    lastBlink = millis();
  }
  delay(200);
}

// ── Ultrasonic Distance Reading ────────────────
long getDistance(int trig, int echo) {
  digitalWrite(trig, LOW);  delayMicroseconds(2);
  digitalWrite(trig, HIGH); delayMicroseconds(10);
  digitalWrite(trig, LOW);
  long dur = pulseIn(echo, HIGH, 30000);
  return dur * 0.034 / 2;
}

// ── Check All Parking Slots ───────────────────
void checkParkingSlots() {
  bool p1 = slot1Occupied, p2 = slot2Occupied, p3 = slot3Occupied;
  slot1Occupied = (getDistance(TRIG1,ECHO1) > 0 && getDistance(TRIG1,ECHO1) < THRESHOLD_DISTANCE);
  slot2Occupied = (getDistance(TRIG2,ECHO2) > 0 && getDistance(TRIG2,ECHO2) < THRESHOLD_DISTANCE);
  slot3Occupied = (getDistance(TRIG3,ECHO3) > 0 && getDistance(TRIG3,ECHO3) < THRESHOLD_DISTANCE);
  if (p1!=slot1Occupied) logSlotChange(1,slot1Occupied);
  if (p2!=slot2Occupied) logSlotChange(2,slot2Occupied);
  if (p3!=slot3Occupied) logSlotChange(3,slot3Occupied);
  availableSlots = (!slot1Occupied) + (!slot2Occupied) + (!slot3Occupied);
  if (availableSlots == 0) alertParkingFull();
}

// ── LCD Update ────────────────────────────────
void updateLCD() {
  lcd.clear();
  lcd.setCursor(0,0); lcd.print("Available: "); lcd.print(availableSlots); lcd.print("/"); lcd.print(totalSlots);
  lcd.setCursor(0,1);
  lcd.print("S1:"); lcd.print(slot1Occupied ? "X" : "O");
  lcd.print(" S2:"); lcd.print(slot2Occupied ? "X" : "O");
  lcd.print(" S3:"); lcd.print(slot3Occupied ? "X" : "O");
}

// ── LED Update ────────────────────────────────
void updateLEDs() {
  digitalWrite(LED_SLOT1, !slot1Occupied);
  digitalWrite(LED_SLOT2, !slot2Occupied);
  digitalWrite(LED_SLOT3, !slot3Occupied);
  digitalWrite(LED_FULL,  availableSlots == 0);
}

// ── Entry Handler ─────────────────────────────
void handleEntry() {
  totalEntries++;
  if (availableSlots > 0) {
    openGate();
    digitalWrite(BUZZER_PIN, HIGH); delay(200); digitalWrite(BUZZER_PIN, LOW);
    lcd.clear(); lcd.setCursor(0,0); lcd.print("WELCOME!");
    lcd.setCursor(0,1); lcd.print("Gate Opening..."); delay(1500);
  } else {
    lcd.clear(); lcd.setCursor(0,0); lcd.print("SORRY!");
    lcd.setCursor(0,1); lcd.print("PARKING FULL");
    for (int i=0; i<3; i++) { digitalWrite(BUZZER_PIN,HIGH); delay(200); digitalWrite(BUZZER_PIN,LOW); delay(200); }
    delay(1000);
  }
}

// ── Exit Handler ──────────────────────────────
void handleExit() {
  totalExits++;
  openGate();
  digitalWrite(BUZZER_PIN,HIGH); delay(200); digitalWrite(BUZZER_PIN,LOW);
  lcd.clear(); lcd.setCursor(0,0); lcd.print("THANK YOU!");
  lcd.setCursor(0,1); lcd.print("Please Exit..."); delay(1500);
}

// ── Gate Control ──────────────────────────────
void openGate() {
  if (!gateOpen) { barrierGate.write(GATE_OPEN); gateOpen=true; gateOpenTime=millis(); }
}
void closeGate() {
  if (gateOpen) { barrierGate.write(GATE_CLOSED); gateOpen=false; }
}

// ── Alerts & Logging ──────────────────────────
void alertParkingFull() {
  static unsigned long lastAlert=0;
  if (millis()-lastAlert > 5000) {
    Serial.println("⚠️ PARKING LOT FULL!");
    for(int i=0;i<2;i++){digitalWrite(LED_FULL,HIGH);delay(200);digitalWrite(LED_FULL,LOW);delay(200);}
    digitalWrite(LED_FULL,HIGH); lastAlert=millis();
  }
}
void logSlotChange(int slot, bool occupied) {
  Serial.printf("Slot %d → %s | Available: %d/%d\n", slot, occupied?"OCCUPIED":"FREE", availableSlots, totalSlots);
}

// ── LED Test on Boot ──────────────────────────
void testLEDs() {
  digitalWrite(LED_SLOT1,HIGH); digitalWrite(LED_SLOT2,HIGH); digitalWrite(LED_SLOT3,HIGH);
  digitalWrite(LED_FULL,HIGH); digitalWrite(LED_WIFI,HIGH); delay(500);
  digitalWrite(LED_SLOT1,LOW); digitalWrite(LED_SLOT2,LOW); digitalWrite(LED_SLOT3,LOW);
  digitalWrite(LED_FULL,LOW); digitalWrite(LED_WIFI,LOW); delay(500);
}

// ── WiFi Connection ───────────────────────────
void connectWiFi() {
  WiFi.mode(WIFI_STA); WiFi.begin(ssid, password);
  int attempts=0;
  while (WiFi.status()!=WL_CONNECTED && attempts<20) { delay(500); attempts++; }
  wifiConnected = (WiFi.status()==WL_CONNECTED);
  if (wifiConnected) {
    digitalWrite(LED_WIFI,HIGH);
    Serial.println("✓ WiFi: " + WiFi.localIP().toString());
  }
}

// ── Web Server Setup ──────────────────────────
void setupWebServer() {
  if (!wifiConnected) return;
  server.on("/",           handleRoot);
  server.on("/api/status", handleAPIStatus);
  server.on("/api/open",   handleAPIOpen);
  server.on("/api/stats",  handleAPIStats);
  server.begin();
  Serial.println("✓ Web server at http://" + WiFi.localIP().toString());
}

// ── API: Status JSON ──────────────────────────
void handleAPIStatus() {
  String json = "{";
  json += "\"available\":"  + String(availableSlots) + ",";
  json += "\"occupied\":"   + String(totalSlots-availableSlots) + ",";
  json += "\"slot1\":"      + String(slot1Occupied?"true":"false") + ",";
  json += "\"slot2\":"      + String(slot2Occupied?"true":"false") + ",";
  json += "\"slot3\":"      + String(slot3Occupied?"true":"false") + ",";
  json += "\"gate\":\""     + String(gateOpen?"open":"closed") + "\"";
  json += "}";
  server.send(200, "application/json", json);
}

// ── API: Open Gate ────────────────────────────
void handleAPIOpen() {
  if (availableSlots > 0) { openGate(); server.send(200, "text/plain", "Gate opened!"); }
  else                     { server.send(403, "text/plain", "Parking full!"); }
}

// ── API: Stats JSON ───────────────────────────
void handleAPIStats() {
  String json = "{";
  json += "\"totalEntries\":" + String(totalEntries) + ",";
  json += "\"totalExits\":"   + String(totalExits)   + ",";
  json += "\"uptime\":"       + String((millis()-systemUptime)/1000) + ",";
  json += "\"wifiRSSI\":"     + String(WiFi.RSSI())  + ",";
  json += "\"freeHeap\":"     + String(ESP.getFreeHeap()) + "}";
  server.send(200, "application/json", json);
}

// ── Root Web Dashboard ────────────────────────
void handleRoot() {
  // Full HTML dashboard with slot cards, stats, live fetch, entry/exit buttons
  // Auto-updates every 2 seconds via fetch('/api/status')
  // See the Wokwi simulation for the complete HTML source
  String html = "<!DOCTYPE html><html><head>";
  html += "<meta name='viewport' content='width=device-width,initial-scale=1'>";
  html += "<title>ESP32 Smart Parking</title>";
  html += "<script>setInterval(()=>fetch('/api/status').then(r=>r.json()).then(d=>{";
  html += "document.getElementById('av').textContent=d.available;";
  html += "document.getElementById('oc').textContent=d.occupied;";
  html += "}),2000);</script></head><body style='font-family:sans-serif;padding:20px'>";
  html += "<h2>🅿️ Smart Parking</h2>";
  html += "<p>Available: <strong id='av'>" + String(availableSlots) + "</strong> / 3</p>";
  html += "<p>Occupied: <strong id='oc'>"  + String(totalSlots-availableSlots) + "</strong></p>";
  html += "<p>IP: " + WiFi.localIP().toString() + " | Uptime: " + String((millis()-systemUptime)/1000) + "s</p>";
  html += "<button onclick=\"fetch('/api/open').then(r=>r.text()).then(alert)\">Open Gate</button>";
  html += "</body></html>";
  server.send(200, "text/html", html);
}
🟢 Slot LED ON That slot is free & available
Slot LED OFF That slot is occupied by a car
🔴 Red LED ON Parking lot full — entry denied
🔵 Blue LED Blink WiFi connected — 1 sec heartbeat
🔔 1× Buzzer Beep Successful entry or exit
🚨 3× Buzzer Beeps Entry denied — parking full
1

▶ Start the Simulation

Click Play in Wokwi. All 5 LEDs flash once (LED test). The LCD shows "Initializing…" then "SYSTEM READY!". WiFi connects within ~10 seconds.

2

📋 Find the IP Address

Open the Serial Monitor tab (bottom of Wokwi). Look for the line: ✓ WiFi: 10.0.0.2. Click that link to open the web dashboard.

3

🚗 Simulate a Car in Slot 1

Click the HC-SR04 ultrasonic1 sensor in Wokwi. Change the distance value from 400 cm to 10 cm. Slot 1's green LED turns OFF, the LCD updates to "Available: 2/3", and the web dashboard reflects the change in 2 seconds.

4

🚧 Fill All Slots

Set all three ultrasonic sensors to 10 cm. The red FULL LED turns ON, the LCD shows "Available: 0/3", and pressing ENTRY triggers 3 buzzer beeps with "PARKING FULL" on LCD.

5

🟢 Press the ENTRY Button

With a free slot available, press the green ENTRY button. The buzzer beeps once, LCD shows "WELCOME! Gate Opening…", and the servo rotates to 90°. It auto-closes after 3 seconds.

6

🔴 Press the EXIT Button

Press the red EXIT button. The buzzer beeps, LCD shows "THANK YOU! Please Exit…", and the gate opens then auto-closes. The exit counter increments in /api/stats.

7

🌐 Use the REST API

Access /api/status for live slot JSON, /api/open to trigger the gate remotely, and /api/stats for entry/exit totals, uptime, WiFi RSSI, and free heap memory.


▶ Try it Live in Wokwi Simulator

No hardware required — run the full smart parking simulation instantly in your browser. Adjust ultrasonic distances, press buttons, and watch the web dashboard update live.

🔗 Open Free Simulation
💡
Pro Tip: After starting the simulation, click each HC-SR04 sensor individually to change its distance value. Set to 10 cm to mark a slot occupied, and 400 cm to make it available again. Watch the LCD, LEDs, and web dashboard all update in real time.

MakeMindz — Hands-on Electronics & IoT Tutorials

makemindz.com · ESP32 Project Series

Simulation powered by Wokwi

Comments

try for free