ESP32-CAM Security Camera with Motion Detection (DIY Affordable IP Camera Project)

ESP32-CAM Security Camera with PIR Motion Detection | Wokwi Tutorial – MakeMindz
🔒 Security & Surveillance 📷 ESP32-CAM 📡 IoT 🟢 Wokwi Simulated

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.

~20 min build 6 Components Arduino C++ / ESP-IDF Beginner Friendly
🟢
System State
Armed
👁️
PIR Sensor
GPIO 13
🔔
Alert Duration
5 Seconds
📡
WiFi
ESP32-CAM
🔬 System Logic

How the Security System Works

🟢 STANDBY MODE
Green LED lit · Red LED off · Buzzer silent · PIR actively scanning · System armed and monitoring
🔴 ALERT MODE
Red LED on · Green LED off · Buzzer beeps 3× · Event logged · Returns to standby after 5 seconds
@media (max-width: 480px) { .state-grid { grid-template-columns: 1fr; } }
Motion Detection Sequence
👁️
PIR Sensor Detects Motion
GPIO 13 goes HIGH — passive infrared detects heat signature of moving person
🔴
Red LED Activates
GPIO 12 HIGH → Red LED on. GPIO 14 LOW → Green LED off. Visual alert immediate.
🔔
Buzzer Beeps 3 Times
GPIO 27 pulses: 200ms ON / 100ms OFF × 3. Audible alert for occupants.
📋
Event Logged to Serial Monitor
Event number, timestamp (millis), and status written to 115200 baud Serial Monitor.
⏱️
Standby After 5 Seconds
Timer resets if motion continues. Once clear for 5 seconds, system returns to Green LED standby mode.

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.

0 Requirements

Components Required

📷
ESP32-CAM / ESP32 DevKit
WiFi + camera support
👁️
PIR Motion Sensor
HC-SR501, GPIO 13
🔴
Red LED
Motion alert, GPIO 12
🟢
Green LED
Standby ready, GPIO 14
🔔
Active Buzzer
3× beep alert, GPIO 27
🔘
Reset Button
INPUT_PULLUP, GPIO 15
〰️
2× 220Ω Resistors
LED current limiting

💡 In Wokwi, the wokwi-pir-motion-sensor component simulates the real HC-SR501. Click it during simulation to trigger a motion detection event.

1 Wiring

Pin Connections

ComponentPin/TerminalESP32 GPIOModeWire
PIR Motion Sensor VCC3.3VRed
GNDGND.1Black
OUT (Signal)GPIO 13INPUTGreen
Red LED (Motion) Anode (+)GPIO 12 → R1 (220Ω)OUTPUTRed
Cathode (−)GND.1Black
Green LED (Standby) Anode (+)GPIO 14 → R2 (220Ω)OUTPUTGreen
Cathode (−)GND.1Black
Active Buzzer Positive (+)GPIO 27OUTPUTOrange
Negative (−)GND.1Black
Reset Button Terminal 1GPIO 15INPUT_PULLUPBlue
Terminal 2GND.1Black
📖 Tutorial

Step-by-Step Wokwi Guide

1
Open Wokwi Simulator

Go to wokwi.com and click "New Project". Select "ESP32" as the board type (use wokwi-esp32-devkit-v1 which simulates the ESP32 platform).

2
Load the diagram.json

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.

3
Add the Arduino Code

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.

4
Start the Simulation

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!"

5
Trigger Motion Detection

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.

6
Watch Standby Return

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".

7
Test the Reset Button

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.

8
Deploy on Real ESP32-CAM (Optional)

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.

2 Wokwi Config

diagram.json

Copy this entire block and paste it into the diagram.json tab in your Wokwi project to instantly wire all components.

diagram.json — Wokwi circuit file
{
  "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": {}
}
3 Code

Arduino Code (sketch.ino)

Copy this into the sketch.ino tab in Wokwi. Set the Serial Monitor to 115200 baud.

sketch.ino — Arduino C++ / ESP32
/*
 * 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");
}
✨ Features

Key Features

Live video streaming (web server mode)
PIR motion detection alerts
Image capture & microSD storage
Red LED — motion detected indicator
Green LED — standby ready indicator
3× buzzer beep alarm pattern
Reset button with debouncing
Serial Monitor event logging
5-second alert auto-clear timer
Motion event counter tracking
Night vision via IR LEDs (optional)
Face recognition (advanced mode)
💡 Hardware Choice

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.

📶
Built-in WiFi
2.4GHz 802.11 b/g/n for remote streaming
📷
OV2640 Camera
2MP sensor, up to 1600×1200 resolution
💾
MicroSD Slot
Store captured images locally on card
Low Power
Deep sleep mode for battery operation
💰
Affordable
Under $10 — fraction of CCTV system cost
🧠
Face Recognition
Built-in support via ESP-WHO framework
📚 Skills

Learning Outcomes

GPIO handling on ESP32
PIR motion sensor integration
LED & buzzer alert systems
Event logging via Serial Monitor
Input debouncing in code
Embedded automation state logic
Basics of IoT surveillance systems
Cloud-connected camera foundation
Timer-based auto-reset logic
WiFi camera web server setup
🌍 Use Cases

Real-World Applications

🏠 Home security system
👶 Baby monitoring camera
🐾 Pet surveillance
🏭 Warehouse monitoring
🏢 Office security
🚪 Smart door monitoring
🌿 Garden / outdoor camera
🎓 STEM learning projects

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.

Launch Simulation

More ESP32 Projects at MakeMindz

📡 ESP32 Projects

Comments

try for free