ESP32-CAM Security Camera
with PIR Motion Detection
Build a WiFi-enabled smart surveillance system using the ESP32-CAM microcontroller. Features PIR motion detection, tri-color LED status indicators, buzzer alarm, and real-time serial event logging — all testable in the Wokwi simulator before deploying on real hardware.
How the Security System Works
The RESET button (GPIO 15, INPUT_PULLUP) clears all alerts immediately, resets the motion counter, and blinks both LEDs 3× to confirm the reset. Press it anytime to return to armed standby.
Components Required
💡 In Wokwi, the wokwi-pir-motion-sensor component simulates the real HC-SR501. Click it during simulation to trigger a motion detection event.
Pin Connections
| Component | Pin/Terminal | ESP32 GPIO | Mode | Wire |
|---|---|---|---|---|
| PIR Motion Sensor | VCC | 3.3V | — | Red |
| GND | GND.1 | — | Black | |
| OUT (Signal) | GPIO 13 | INPUT | Green | |
| Red LED (Motion) | Anode (+) | GPIO 12 → R1 (220Ω) | OUTPUT | Red |
| Cathode (−) | GND.1 | — | Black | |
| Green LED (Standby) | Anode (+) | GPIO 14 → R2 (220Ω) | OUTPUT | Green |
| Cathode (−) | GND.1 | — | Black | |
| Active Buzzer | Positive (+) | GPIO 27 | OUTPUT | Orange |
| Negative (−) | GND.1 | — | Black | |
| Reset Button | Terminal 1 | GPIO 15 | INPUT_PULLUP | Blue |
| Terminal 2 | GND.1 | — | Black |
Step-by-Step Wokwi Guide
Go to wokwi.com and click "New Project". Select "ESP32" as the board type (use wokwi-esp32-devkit-v1 which simulates the ESP32 platform).
Click the diagram.json tab in Wokwi. Delete all existing content and paste the complete diagram.json from the section below. This auto-places all components — PIR sensor, LEDs, buzzer, resistors, and reset button.
Click the sketch.ino tab. Delete all existing code and paste the complete code from the Code section below. The Serial Monitor runs at 115200 baud.
Click the green ▶ Start Simulation button. Watch the Serial Monitor — it will print the startup sequence with the 5-second PIR warm-up countdown, then display "✓ System Armed!"
Click the PIR sensor component in the simulation. The red LED lights up, the buzzer beeps 3 times, and the Serial Monitor logs: Event #, Timestamp, Status: MOTION ACTIVE.
After 5 seconds with no continued motion, the system automatically deactivates the alert — red LED off, green LED on — and logs "✓ Alert cleared - System back to standby".
Click the blue RESET button component at any time to manually clear all alerts. Both LEDs blink 3 times to confirm. The motion counter resets to zero and the system re-arms.
For real hardware, install the ESP32 board package in Arduino IDE, select AI Thinker ESP32-CAM, and add camera initialization code using the esp_camera.h library. The GPIO logic remains identical.
diagram.json
Copy this entire block and paste it into the diagram.json tab in your Wokwi project to instantly wire all components.
{
"version": 1,
"author": "Arduino Security Project",
"editor": "wokwi",
"parts": [
{
"type": "wokwi-esp32-devkit-v1",
"id": "esp", "top": 0, "left": 0, "attrs": {}
},
{
"type": "wokwi-pir-motion-sensor",
"id": "pir1", "top": -67.2, "left": 124.8,
"attrs": {}
},
{
"type": "wokwi-led",
"id": "led1", "top": -34.8, "left": 278.2,
"attrs": { "color": "red" }
},
{
"type": "wokwi-led",
"id": "led2", "top": 14.4, "left": 278.2,
"attrs": { "color": "green" }
},
{
"type": "wokwi-resistor",
"id": "r1", "top": -25.2, "left": 230.4,
"attrs": { "value": "220" }
},
{
"type": "wokwi-resistor",
"id": "r2", "top": 24, "left": 230.4,
"attrs": { "value": "220" }
},
{
"type": "wokwi-buzzer",
"id": "bz1", "top": 96, "left": 240,
"attrs": {}
},
{
"type": "wokwi-pushbutton",
"id": "btn1", "top": 163.2, "left": 124.8,
"attrs": { "color": "blue", "label": "RESET" }
}
],
"connections": [
[ "esp:TX0", "$serialMonitor:RX", "", [] ],
[ "esp:RX0", "$serialMonitor:TX", "", [] ],
[ "pir1:VCC", "esp:3V3", "red", [ "h0" ] ],
[ "pir1:GND", "esp:GND.1", "black", [ "h0" ] ],
[ "pir1:OUT", "esp:D13", "green", [ "h0" ] ],
[ "led1:A", "r1:2", "red", [ "v0" ] ],
[ "r1:1", "esp:D12", "red", [ "h0" ] ],
[ "led1:C", "esp:GND.1", "black", [ "v0" ] ],
[ "led2:A", "r2:2", "green", [ "v0" ] ],
[ "r2:1", "esp:D14", "green", [ "h0" ] ],
[ "led2:C", "esp:GND.1", "black", [ "v0" ] ],
[ "bz1:1", "esp:D27", "orange", [ "h0" ] ],
[ "bz1:2", "esp:GND.1", "black", [ "h0" ] ],
[ "btn1:1.l", "esp:D15", "blue", [ "h0" ] ],
[ "btn1:2.l", "esp:GND.1", "black", [ "h0" ] ]
],
"dependencies": {}
}
Arduino Code (sketch.ino)
Copy this into the sketch.ino tab in Wokwi. Set the Serial Monitor to 115200 baud.
/* * ESP32-CAM Security Camera with Motion Detection * * Hardware: ESP32 DevKit / ESP32-CAM * Features: PIR sensor | LED indicators | Buzzer | Reset button * Serial: 115200 baud * Wokwi sim: https://wokwi.com/projects/459534543279902721 * * For real ESP32-CAM: add esp_camera.h initialization for video stream */ // ── PIN DEFINITIONS ─────────────────────────────────────────── #define PIR_PIN 13 // PIR motion sensor output #define RED_LED 12 // Red LED → Motion detected #define GREEN_LED 14 // Green LED → Standby / ready #define BUZZER_PIN 27 // Active buzzer #define RESET_BTN 15 // Manual reset (INPUT_PULLUP) // ── SYSTEM STATE ────────────────────────────────────────────── bool motionDetected = false; bool systemArmed = true; unsigned long lastMotionTime = 0; unsigned long alertDuration = 5000; // ms before auto-clear int motionCount = 0; void setup() { Serial.begin(115200); Serial.println("\n\n================================="); Serial.println(" ESP32-CAM Security System"); Serial.println(" Motion Detection Active"); Serial.println("=================================\n"); pinMode(PIR_PIN, INPUT); pinMode(RED_LED, OUTPUT); pinMode(GREEN_LED, OUTPUT); pinMode(BUZZER_PIN, OUTPUT); pinMode(RESET_BTN, INPUT_PULLUP); // Initial state: system ready (green on) digitalWrite(GREEN_LED, HIGH); digitalWrite(RED_LED, LOW); digitalWrite(BUZZER_PIN, LOW); Serial.println("✓ System Initialized"); Serial.println("✓ Sensors Ready"); Serial.println("✓ Monitoring Started\n"); // PIR warm-up countdown (real sensors need ~30s; shortened for demo) Serial.println("Warming up PIR sensor..."); for (int i = 5; i > 0; i--) { Serial.print(i); Serial.print("... "); delay(1000); } Serial.println("\n✓ System Armed!\n"); } void loop() { int pirState = digitalRead(PIR_PIN); // Motion detected — first trigger only if (pirState == HIGH && systemArmed && !motionDetected) { motionDetected = true; lastMotionTime = millis(); motionCount++; activateAlert(); logMotionEvent(); } // Extend alert while motion continues if (motionDetected && pirState == HIGH) { lastMotionTime = millis(); } // Auto-clear after alertDuration with no motion if (motionDetected && (millis() - lastMotionTime > alertDuration)) { deactivateAlert(); motionDetected = false; } // Reset button (debounced) if (digitalRead(RESET_BTN) == LOW) { delay(50); if (digitalRead(RESET_BTN) == LOW) { resetSystem(); while (digitalRead(RESET_BTN) == LOW); // wait for release } } delay(100); } // ── ALERT FUNCTIONS ─────────────────────────────────────────── void activateAlert() { digitalWrite(RED_LED, HIGH); digitalWrite(GREEN_LED, LOW); // 3× beep pattern: 200ms on / 100ms off for (int i = 0; i < 3; i++) { digitalWrite(BUZZER_PIN, HIGH); delay(200); digitalWrite(BUZZER_PIN, LOW); delay(100); } Serial.println("\n╔════════════════════════════════╗"); Serial.println("║ ⚠️ MOTION DETECTED! ⚠️ ║"); Serial.println("╚════════════════════════════════╝"); } void deactivateAlert() { digitalWrite(RED_LED, LOW); digitalWrite(GREEN_LED, HIGH); digitalWrite(BUZZER_PIN, LOW); Serial.println("\n✓ Alert cleared — back to standby\n"); } void logMotionEvent() { Serial.println("--- Motion Event Log ---"); Serial.print("Event #: "); Serial.println(motionCount); Serial.print("Timestamp: "); Serial.print(millis() / 1000); Serial.println(" seconds"); Serial.println("Status: MOTION ACTIVE"); Serial.println("Action: Alert triggered — buzzer × 3"); Serial.println("------------------------\n"); } void resetSystem() { Serial.println("\n>>> SYSTEM RESET <<<"); digitalWrite(RED_LED, LOW); digitalWrite(GREEN_LED, LOW); digitalWrite(BUZZER_PIN, LOW); // Confirmation blink: both LEDs 3× for (int i = 0; i < 3; i++) { digitalWrite(RED_LED, HIGH); digitalWrite(GREEN_LED, HIGH); delay(200); digitalWrite(RED_LED, LOW); digitalWrite(GREEN_LED, LOW); delay(200); } motionDetected = false; motionCount = 0; digitalWrite(GREEN_LED, HIGH); // Return to standby Serial.println("✓ System reset complete"); Serial.println("✓ Motion counter cleared"); Serial.println("✓ System re-armed\n"); } void printSystemStatus() { Serial.println("\n=== SYSTEM STATUS ==="); Serial.print("Armed: "); Serial.println(systemArmed ? "YES" : "NO"); Serial.print("Motion Detected: "); Serial.println(motionDetected ? "YES" : "NO"); Serial.print("Total Detections: "); Serial.println(motionCount); Serial.print("Uptime: "); Serial.print(millis() / 1000); Serial.println(" s"); Serial.println("====================\n"); }
Key Features
Why Choose ESP32-CAM?
The ESP32-CAM is one of the best microcontrollers for building IoT security cameras — delivering commercial-grade features at a fraction of the cost.
Learning Outcomes
Real-World Applications
This project is ideal for building a DIY IP camera using ESP32 at a fraction of the cost of commercial CCTV systems.
🟢 Try It Now — Free Wokwi Simulation
The complete circuit is ready to run in your browser. Click PIR sensor to trigger motion, watch LEDs & buzzer react, and read real-time logs in the Serial Monitor.
Comments
Post a Comment