Cirkit Designer LogoCirkit DesignerYour all-in-one circuit design IDE Launch Cirkit Designer App

ESP32-CAM Wi-Fi Controlled Motion Detection Security Camera

View and Edit Project In Cirkit DesignerImage of ESP32-CAM Wi-Fi Controlled Motion Detection Security Camera

Circuit Documentation

Summary

This circuit involves an ESP32 CAM module, an FTDI Programmer, and a PIR sensor. The ESP32 CAM is used for capturing images and sending them over WiFi. The FTDI Programmer is used for programming the ESP32 CAM, and the PIR sensor is used for motion detection. The ESP32 CAM is programmed to capture images when motion is detected and send them to a server for analysis.

Component List

ESP32 CAM

FTDI Programmer

PIR Sensor

Wiring Details

ESP32 CAM

FTDI Programmer

PIR Sensor

Code Documentation

Overview

The code for the ESP32 CAM is written in Arduino and includes libraries for WiFi, HTTP, camera control, and WebSockets. The main functionality includes initializing the camera and WiFi, detecting motion using the PIR sensor, capturing images, and sending them to a server for analysis.

Code Breakdown

Libraries and Configuration

#include <Arduino.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <esp_camera.h>
#include <base64.h>
#include <ArduinoJson.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <WebSocketsClient.h>

// WiFi Configuration
#define WIFI_SSID "Gagan A Ayi"
#define WIFI_PASSWORD "29842984"
#define WEBSOCKET_SERVER "ws://localhost:12345"
#define SERVER_URL "http://localhost/fras/api"

// ESP32-CAM Pin Configuration
#define CAMERA_MODEL_AI_THINKER
#define PWDN_GPIO_NUM     32
#define RESET_GPIO_NUM    -1
#define XCLK_GPIO_NUM      0
#define SIOD_GPIO_NUM     26
#define SIOC_GPIO_NUM     27
#define Y9_GPIO_NUM       35
#define Y8_GPIO_NUM       34
#define Y7_GPIO_NUM       39
#define Y6_GPIO_NUM       36
#define Y5_GPIO_NUM       21
#define Y4_GPIO_NUM       19
#define Y3_GPIO_NUM       18
#define Y2_GPIO_NUM        5
#define VSYNC_GPIO_NUM    25
#define HREF_GPIO_NUM     23
#define PCLK_GPIO_NUM     22

// Sensor Configurations
#define PIR_SENSOR_PIN 13
#define LED_INDICATOR_PIN 4

// System Configuration
#define CONFIDENCE_THRESHOLD 0.7
#define NO_MOTION_TIMEOUT 5000  // 5 seconds to confirm no motion

// Global Variables
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org");
WebSocketsClient webSocket;

String currentClassroom = "";
String currentSubject = "";
String assignedTeacher = "";
unsigned long lastMotionTime = 0;
bool isCameraActive = false;

Function Prototypes

bool initializeCamera();
bool initializeWiFi();
void captureAndSendFrame();
bool noHumansInFrame();
void syncClassroomContext();

Setup Function

void setup() {
  Serial.begin(115200);
  
  // Initialize Pins
  pinMode(PIR_SENSOR_PIN, INPUT);
  pinMode(LED_INDICATOR_PIN, OUTPUT);
  
  // Initialize Components
  if (!initializeCamera()) {
    Serial.println("Camera initialization failed!");
    return;
  }
  
  if (!initializeWiFi()) {
    Serial.println("WiFi connection failed!");
    return;
  }
  
  // Initialize Time Client
  timeClient.begin();
  timeClient.setTimeOffset(19800);  // Indian Standard Time

  // Initialize WebSocket
  String host = "localhost";
  uint16_t port = 12345;
  String url = "/";
  String protocol = "arduino";
  webSocket.begin(host, port, url, protocol);
}

Loop Function

void loop() {
  // Periodically sync classroom context
  static unsigned long lastContextSync = 0;
  if (millis() - lastContextSync > 300000) {  // Every 5 minutes
    syncClassroomContext();
    lastContextSync = millis();
  }
  
  // Motion Detection
  if (!isCameraActive && digitalRead(PIR_SENSOR_PIN) == HIGH) {
    // Turn on the camera and LED indicator
    lastMotionTime = millis();
    digitalWrite(LED_INDICATOR_PIN, HIGH);
    isCameraActive = true;
    captureAndSendFrame();
  }
  
  // Check for turning off the camera and LED indicator
  if (isCameraActive && millis() - lastMotionTime > NO_MOTION_TIMEOUT) {
    if (noHumansInFrame()) {
      digitalWrite(LED_INDICATOR_PIN, LOW);
      isCameraActive = false;
      Serial.println("No humans detected, turning off camera and LED");
    } else {
      lastMotionTime = millis();  // Reset the timer if a human is detected
    }
  }
  
  webSocket.loop();
}

Initialize Camera Function

bool initializeCamera() {
  camera_config_t config;
  config.ledc_channel = LEDC_CHANNEL_0;
  config.ledc_timer = LEDC_TIMER_0;
  config.pin_d0 = Y2_GPIO_NUM;
  config.pin_d1 = Y3_GPIO_NUM;
  config.pin_d2 = Y4_GPIO_NUM;
  config.pin_d3 = Y5_GPIO_NUM;
  config.pin_d4 = Y6_GPIO_NUM;
  config.pin_d5 = Y7_GPIO_NUM;
  config.pin_d6 = Y8_GPIO_NUM;
  config.pin_d7 = Y9_GPIO_NUM;
  config.pin_xclk = XCLK_GPIO_NUM;
  config.pin_pclk = PCLK_GPIO_NUM;
  config.pin_vsync = VSYNC_GPIO_NUM;
  config.pin_href = HREF_GPIO_NUM;
  config.pin_sccb_sda = SIOD_GPIO_NUM;
  config.pin_sccb_scl = SIOC_GPIO_NUM;
  config.pin_pwdn = PWDN_GPIO_NUM;
  config.pin_reset = RESET_GPIO_NUM;
  
  config.xclk_freq_hz = 20000000;
  config.pixel_format = PIXFORMAT_JPEG;
  config.frame_size = FRAMESIZE_SVGA;
  config.jpeg_quality = 10;
  config.fb_count = 2;
  
  return esp_camera_init(&config) == ESP_OK;
}

Initialize WiFi Function

bool initializeWiFi() {
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  
  int attempts = 0;
  while (WiFi.status() != WL_CONNECTED && attempts < 20) {
    delay(500);
    Serial.print(".");
    attempts++;
  }
  
  return WiFi.status() == WL_CONNECTED;
}

Capture and Send Frame Function

void captureAndSendFrame() {
  camera_fb_t* fb = esp_camera_fb_get();
  if (!fb) {
    Serial.println("Camera capture failed");
    return;
  }
  
  // Base64 encode image
  String encodedImage = base64::encode(fb->buf, fb->len);
  
  // Send to server
  webSocket.sendTXT(encodedImage);
  
  esp_camera_fb_return(fb);
}

No Humans in Frame Function

bool noHumansInFrame() {
  camera_fb_t* fb = esp_camera_fb_get();
  if (!fb) {
    Serial.println("Camera capture failed");
    return false;
  }
  
  // Base64 encode image
  String encodedImage = base64::encode(fb->buf, fb->len);
  esp_camera_fb_return(fb);

  // Send to server for analysis
  HTTPClient http;
  http.begin(SERVER_URL + String("/analyze"));
  http.addHeader("Content-Type", "application/json");

  DynamicJsonDocument payload(512);
  payload["image"] = encodedImage;