Skip to Content

Telecamera di sorveglianza con ESP32-CAM

Telecamera di sorveglianza con ESP32-CAM

In questo tutorial imparerai come costruire un sistema di videosorveglianza attivato dal movimento con l’ESP32-CAM. Il sistema registrerà video ogni volta che viene rilevato un movimento e salverà il flusso video in un file sul tuo computer. Questo progetto è adatto per applicazioni di sorveglianza, sicurezza o monitoraggio della fauna selvatica.

Componenti necessari

Di seguito trovi i componenti necessari per realizzare il progetto. Ti serviranno un ESP32-CAM e lo USB-TTL Shield o l’adattatore FTDI USB-TTL per programmare la scheda.

Ho elencato due diversi tipi di sensori di movimento. Se vuoi una dimensione ridotta e un intervallo di attivazione più breve, scegli l’AM312. Se invece vuoi attivare la telecamera solo di notte, opta per l’HC-SR501, poiché può essere facilmente dotato di un sensore di luce. Per maggiori dettagli, vedi il Motion Activated ESP32-CAM tutorial.

ESP32-CAM con USB-TTL Shield

Adattatore FTDI USB-TTL

Dupont wire set

Set di fili Dupont

Sensore di movimento PIR AM312

Sensore di movimento PIR HC-SR501

USB data cable

Cavo dati USB

Makerguides is a participant in affiliate advertising programs designed to provide a means for sites to earn advertising fees by linking to Amazon, AliExpress, Elecrow, and other sites. As an Affiliate we may earn from qualifying purchases.

Architettura del sistema

In questo progetto implementeremo un sistema di videosorveglianza che utilizza l’ESP32-CAM, un sensore di movimento e un PC per ricevere e memorizzare i video di sorveglianza.

L’ESP32-CAM eseguirà un server di streaming video che trasmette i frame video via Wi-Fi, se un sensore PIR collegato all’ESP32-CAM rileva movimento. I frame video saranno ricevuti da un’applicazione Python in esecuzione su un PC che scrive i dati video in un file. L’immagine sotto illustra la configurazione:

Architecture of Surveillance System
Architettura del sistema di sorveglianza

Circuito di rilevamento movimento

Iniziamo costruendo il circuito di rilevamento movimento. Questo comporta il collegamento del sensore a infrarossi passivo (PIR) all’ESP32-CAM. In questo esempio userò il sensore PIR AM312, ma collegare il sensore PIR HC-SR501 è praticamente lo stesso. Vedi il Motion Activated ESP32-CAM tutorial.

Collegamento del sensore PIR all’ESP32-CAM

Collegare il modulo sensore PIR AM312 all’ESP32-CAM è semplice. Collega un’alimentazione (batteria) da 5V (fino a 12V) ai pin 5V e GND dell’ESP32-CAM come mostrato sotto (fili rossi e blu).

Connecting AM312 PIR Sensor to ESP32-CAM
Collegamento AM312 all’ESP32-CAM

Puoi fornire una tensione da 5V fino a 12V per alimentare la scheda. Non preoccuparti. Un regolatore di tensione è collegato al pin 5V e ridurrà la tensione di ingresso al livello richiesto dalla scheda.

Allo stesso modo, collega il modulo sensore PIR AM312 all’alimentazione (fili rossi e blu). Può gestire fino a 12V, ma fai attenzione alla polarità corretta, poiché l’AM312 non ha protezione di polarità. Poi collega l’uscita S o OUT dell’AM312 al pin GPIO13 dell’ESP32-CAM (filo verde).

Se usi il modulo sensore PIR HC-SR501 invece dell’AM312, collegalo allo stesso modo (GND a GND, VCC a 5V-12V).

Circuito su breadboard

Se programmi l’ESP32-CAM tramite lo USB-TTL Shield e vuoi provare il circuito su una breadboard, puoi alimentare l’ESP32-CAM e il sensore AM312 come mostrato sotto:

Circuit on Breadboard
Circuito su breadboard

Dovrai creare un piccolo spazio tra l’ESP32-CAM e lo Shield di programmazione e poi collegare i fili ai pin esposti nello spazio:

Connect wires to pins in gap
Collega i fili ai pin nello spazio

Le connessioni sono come prima. Il pin GND è collegato al pin ‘-‘, il pin 5V è collegato al pin ‘+’ e GPIO13 è collegato al pin ‘s’ dell’AM312.

Codice per testare il sensore PIR

Prima di implementare il codice completo per il server di streaming video, testiamo il sensore PIR e il circuito. Carica il seguente codice sul tuo ESP32-CAM:

void setup() {
  Serial.begin(115200);
  pinMode(GPIO_NUM_13, INPUT);
}

void loop() {
  bool isMotion = digitalRead(GPIO_NUM_13);
  Serial.println(isMotion ? "ON" : "OFF");
  delay(1000);
}

Se apri il Monitor Seriale dovresti vedere il testo “ON” stampato quando il sensore PIR rileva movimento e “OFF” altrimenti. Se non fosse così, controlla il circuito. Potresti trovare utili suggerimenti nel Motion Activated ESP32-CAM tutorial.

Streaming video

In questa sezione implementiamo il server di streaming video sul modulo ESP32-CAM che trasmette i frame video se il sensore PIR rileva movimento. Dai un’occhiata veloce al codice completo qui sotto, poi ne discuteremo i dettagli.

#include "WebServer.h"
#include "WiFi.h"
#include "esp32cam.h"

const char* WIFI_SSID = "SSID";
const char* WIFI_PASS = "PASSWORD";
const char* URL = "/video";
const auto RESOLUTION = esp32cam::Resolution::find(800, 600);
const int FRAMERATE = 10;
const byte pinPIR = GPIO_NUM_13;
const byte pinFlash = GPIO_NUM_4;

WebServer server(80);

bool isMotion() {
  return digitalRead(pinPIR);
}

void handleStream() {
  static char head[128];
  WiFiClient client = server.client();

  server.sendContent("HTTP/1.1 200 OK\r\n"
                     "Content-Type: multipart/x-mixed-replace; "
                     "boundary=frame\r\n\r\n");

  while (client.connected()) {
    if (isMotion()) {
      analogWrite(pinFlash, 20);
      auto frame = esp32cam::capture();
      if (frame) {
        sprintf(head,
                "--frame\r\n"
                "Content-Type: image/jpeg\r\n"
                "Content-Length: %ul\r\n\r\n",
                frame->size());
        client.write(head, strlen(head));
        frame->writeTo(client);
        client.write("\r\n");
        delay(1000 / FRAMERATE);
      }
    } else {
      analogWrite(pinFlash, 0);
    }
  }
  analogWrite(pinFlash, 0);
}

void initCamera() {
  using namespace esp32cam;
  Config cfg;
  cfg.setPins(pins::AiThinker);
  cfg.setResolution(RESOLUTION);
  cfg.setBufferCount(2);
  cfg.setJpeg(80);
  Camera.begin(cfg);
}

void initWifi() {
  WiFi.persistent(false);
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  while (WiFi.status() != WL_CONNECTED) {
    delay(100);
  }
  Serial.printf("Stream at: http://%s%s\n",
                WiFi.localIP().toString().c_str(), URL);
}

void initServer() {
  server.on(URL, handleStream);
  server.begin();
}

void setup() {
  Serial.begin(115200);
  pinMode(pinPIR, INPUT);
  pinMode(pinFlash, OUTPUT);
  initWifi();
  initCamera();
  initServer();
}

void loop() {
  server.handleClient();
}

Librerie

Iniziamo includendo le librerie necessarie:

#include "WebServer.h"
#include "WiFi.h"
#include "esp32cam.h"

La WebServer.h library è usata per gestire le funzionalità del server HTTP, e la WiFi.h library permette all’ESP32 di connettersi a una rete wireless. La esp32cam library fornisce un’interfaccia semplice per configurare e usare il modulo camera sulla scheda ESP32-CAM. Dovrai installarla tramite il Library Manager:

esp32cam library installed via Library Manager
libreria esp32cam installata tramite Library Manager

Costanti

Successivamente definiamo diverse costanti per la configurazione:

const char* WIFI_SSID = "SSID";
const char* WIFI_PASS = "PASSWORD";
const char* URL = "/video";
const auto RESOLUTION = esp32cam::Resolution::find(800, 600);
const int FRAMERATE = 10;
const byte pinPIR = GPIO_NUM_13;
const byte pinFlash = GPIO_NUM_4;

Le variabili WIFI_SSID e WIFI_PASS memorizzano le credenziali della rete Wi-Fi. Dovrai sostituire i valori di esempio SSID e PASSWORD con quelli della tua rete Wi-Fi.

La variabile URL specifica il percorso sul server a cui i client accederanno per visualizzare lo streaming video. Puoi cambiarlo in un nome diverso, ad esempio “/video-frontdoor”, ma assicurati che il nome sul server (ESP32-CAM) e sul client (app Python) corrispondano.

La variabile RESOLUTION imposta la risoluzione della camera a 800 per 600 pixel. Anche questo è modificabile, ma la risoluzione sul server e sul client deve essere identica.

Puoi anche impostare il FRAMERATE, che definisce il numero di frame per secondo che il server tenterà di trasmettere. Come prima, i frame rate di server e client devono corrispondere.

Infine, le variabili pinPIR e pinFlash si riferiscono ai pin GPIO collegati rispettivamente al sensore di movimento PIR e al LED flash integrato.

Oggetti

Creiamo quindi un server web che ascolta sulla porta 80:

WebServer server(80);

Funzione isMotion

La funzione isMotion() verifica la rilevazione del movimento:

bool isMotion() {
  return digitalRead(pinPIR);
}

Questa funzione legge il segnale digitale dal sensore PIR. Se il sensore emette un segnale alto, è presente movimento e la funzione restituisce true. Ricorda che il sensore PIR ha un tempo di attivazione che può essere impostato per l’HC-SR501.

Funzione handleStream

La funzione handleStream() gestisce lo streaming video quando un client accede all’URL /video:

Iniziamo dichiarando un buffer chiamato head che conterrà gli header HTTP per ogni frame. Poi recuperiamo l’oggetto client associato alla richiesta HTTP corrente:

void handleStream() {
  static char head[128];
  WiFiClient client = server.client();

Il server risponde al client con un header HTTP che indica che invierà una serie di immagini JPEG separate da confini marcati come --frame. Questa tecnica è comunemente nota come streaming MJPEG (Motion JPEG).

  server.sendContent("HTTP/1.1 200 OK\r\n"
                     "Content-Type: multipart/x-mixed-replace; "
                     "boundary=frame\r\n\r\n");

Finché il client rimane connesso, il ciclo continua. All’interno del ciclo chiamiamo la funzione isMotion() per determinare se è stato rilevato movimento:

  while (client.connected()) {
    if (isMotion()) {
      analogWrite(pinFlash, 20);

Se sì, accendiamo il LED flash a bassa luminosità usando PWM scrivendo un duty cycle di 20 su pinFlash. Fai attenzione alla luminosità del flash. Se imposti il flash alla massima luminosità (255) per un periodo prolungato, il LED potrebbe bruciarsi!

Poi proviamo a catturare un frame dalla camera usando esp32cam::capture():

      auto frame = esp32cam::capture();

Se un frame viene catturato con successo, prepariamo gli header HTTP per il frame:

      if (frame) {
        sprintf(head,
                "--frame\r\n"
                "Content-Type: image/jpeg\r\n"
                "Content-Length: %ul\r\n\r\n",
                frame->size());
        client.write(head, strlen(head));
        frame->writeTo(client);
        client.write("\r\n");
        delay(1000 / FRAMERATE);
      }

La funzione sprintf() formatta una stringa contenente il marcatore di confine, il tipo di contenuto e la lunghezza del contenuto dell’immagine. Questo header viene scritto al client usando client.write(). L’immagine JPEG vera e propria è inviata usando frame->writeTo(client), seguita da un ritorno a capo e newline. Viene introdotto un breve ritardo basato sul frame rate desiderato per controllare la velocità dello streaming.

    } else {
      analogWrite(pinFlash, 0);
    }
  }
  analogWrite(pinFlash, 0);
}

Se non viene rilevato movimento, spegniamo il LED flash. Dopo che il ciclo termina, cosa che accade se il client si disconnette, spegniamo di nuovo il flash per assicurarci che non rimanga acceso.

Funzione initCamera

La funzione initCamera() inizializza l’hardware ESP32-CAM:

void initCamera() {
  using namespace esp32cam;
  Config cfg;
  cfg.setPins(pins::AiThinker);
  cfg.setResolution(RESOLUTION);
  cfg.setBufferCount(2);
  cfg.setJpeg(80);
  Camera.begin(cfg);
}

All’interno di questa funzione viene creato un oggetto Config chiamato cfg. Il metodo setPins() viene chiamato con pins::AiThinker per configurare i pin GPIO per il modello AI Thinker dell’ESP32-CAM. Puoi usare il codice anche per altre schede camera scegliendo una configurazione pin diversa. Vedi il Stream Video with with XIAO-ESP32-S3-Sense e il Stream Video with ESP32-WROVER CAM, per esempio.

La risoluzione è impostata usando il valore definito in precedenza. Il conteggio del buffer è impostato a 2, permettendo il double buffering. La qualità della compressione JPEG è impostata all’80%. Infine, la camera viene avviata con Camera.begin(cfg).

Funzione initWifi

L’inizializzazione del Wi-Fi avviene nella funzione initWifi():

void initWifi() {
  WiFi.persistent(false);
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  while (WiFi.status() != WL_CONNECTED) {
    delay(100);
  }
  Serial.printf("Stream at: http://%s%s\n",
                WiFi.localIP().toString().c_str(), URL);
}

La persistenza Wi-Fi è disabilitata per evitare di memorizzare le credenziali nella flash. L’ESP32 è impostato in modalità station e inizia a connettersi alla rete Wi-Fi specificata. Il ciclo attende finché la connessione non è stabilita. Una volta connesso, il dispositivo stampa l’URL dello stream sul monitor seriale:

Stream at: http://192.168.2.42/video

Dovrai usare questo URL nell’applicazione client (app Python) che registra il flusso video in un file.

Nota che puoi testare lo streaming video incollando questo URL nella barra degli indirizzi del tuo browser web. Ma assicurati di usare o l’app client O il browser web, ma non entrambi, poiché solo un client alla volta può connettersi allo stream.

Funzione initServer

Il server HTTP viene configurato nella funzione initServer():

void initServer() {
  server.on(URL, handleStream);
  server.begin();
}

Questa funzione registra l’endpoint /video con la funzione handleStream() e avvia il server.

Funzione setup

La funzione setup() prepara l’ESP32-CAM per l’operazione:

void setup() {
  Serial.begin(115200);
  pinMode(pinPIR, INPUT);
  pinMode(pinFlash, OUTPUT);
  initWifi();
  initCamera();
  initServer();
}

La comunicazione seriale è inizializzata a 115200 baud. Il pin del sensore PIR è configurato come input, e il pin del LED flash come output. La connessione Wi-Fi, la configurazione della camera e il server web sono tutti inizializzati in sequenza.

Funzione loop

Infine, la funzione loop() contiene la logica principale di esecuzione:

void loop() {
  server.handleClient();
}

Questa funzione chiama continuamente server.handleClient() per gestire eventuali richieste HTTP in arrivo dai client.

E questo è il lato server. Nella prossima sezione implementiamo il client che riceve lo stream video e lo salva in un file.

Registrazione video

Il client è implementato come uno script Python che si connette allo stream MJPEG fornito da un ESP32-CAM e scrive il video in arrivo in un file locale .avi. La registrazione è automaticamente segmentata in file giornalieri—uno per ogni giorno del calendario. Lo script opzionalmente mostra anche lo stream live in una finestra.

Di seguito il codice completo. Dai un’occhiata veloce e poi analizziamo i dettagli:

import cv2
import requests
import numpy as np
import datetime
import os

# Replace with your ESP32-CAM stream URL
stream_url = 'http://192.168.2.42/video' 

# match your ESP32-CAM setting
frame_width = 800  
frame_height = 600
fps = 10
fourcc = cv2.VideoWriter_fourcc(*'XVID')

def get_output_filename():
    date_str = datetime.datetime.now().strftime("%Y-%m-%d")
    return f'recording_{date_str}.avi'

# Initialize variables
current_date = datetime.date.today()
output_file = get_output_filename()
out = cv2.VideoWriter(output_file, fourcc, fps, (frame_width, frame_height))

# Connect to MJPEG stream
print(f"Connecting to {stream_url}")
stream = requests.get(stream_url, stream=True)

if stream.status_code != 200:
    print(f"Failed to connect to ESP32-CAM. Status code: {stream.status_code}")
    exit()

bytes_buffer = b''
try:
    for chunk in stream.iter_content(chunk_size=1024):
        bytes_buffer += chunk
        a = bytes_buffer.find(b'\xff\xd8')  # JPEG start
        b = bytes_buffer.find(b'\xff\xd9')  # JPEG end
        if a != -1 and b != -1 and b > a:
            jpg = bytes_buffer[a:b+2]
            bytes_buffer = bytes_buffer[b+2:]

            # Decode the JPEG image to OpenCV format
            img_array = np.frombuffer(jpg, dtype=np.uint8)
            frame = cv2.imdecode(img_array, cv2.IMREAD_COLOR)

            if frame is not None:
                new_date = datetime.date.today()
                if new_date != current_date:
                    out.release()
                    current_date = new_date
                    output_file = get_output_filename()
                    out = cv2.VideoWriter(output_file, fourcc, fps, (frame_width, frame_height))
                    print(f"Started new file: {output_file}")

                out.write(frame)

                # Optional: Show live video
                cv2.imshow('ESP32-CAM Stream', frame)
                if cv2.waitKey(1) & 0xFF == ord('q'):
                    break
except KeyboardInterrupt:
    pass
finally:
    out.release()
    cv2.destroyAllWindows()
    print(f"Video saved to {output_file}")

Librerie

Lo script inizia importando le librerie necessarie:

import cv2
import requests
import numpy as np
import datetime
import os

Il modulo cv2 (OpenCV) è usato per gestire operazioni su immagini e video. La libreria requests permette allo script di stabilire una connessione allo stream HTTP MJPEG dell’ESP32-CAM. La libreria numpy è usata per convertire dati byte grezzi in un array di immagini. Il modulo datetime gestisce tempo e data, particolarmente per organizzare i file video giornalieri. Infine, os è importato per eventuali manipolazioni di percorsi file, anche se non è usato in questo script specifico.

Dovrai installare le librerie cv2, requests e numpy sul tuo computer, preferibilmente in un ambiente virtuale. Vedi il Object Detection with ESP32-CAM and YOLO per un esempio con più dettagli.

Costanti

L’indirizzo IP dell’ESP32-CAM è definito nella variabile stream_url:

stream_url = 'http://192.168.2.42/video'

Questo URL corrisponde all’endpoint definito nello sketch Arduino (specificamente const char* URL = "/video"). L’ESP32-CAM deve essere accessibile a questo indirizzo IP affinché lo script funzioni.

Le seguenti costanti definiscono la risoluzione della camera e le impostazioni di registrazione:

frame_width = 800  
frame_height = 600
fps = 10
fourcc = cv2.VideoWriter_fourcc(*'XVID')

I valori frame_width e frame_height devono corrispondere alla risoluzione impostata nell’ESP32-CAM (esp32cam::Resolution::find(800, 600)). La variabile fps specifica il frame rate, che dovrebbe corrispondere all’impostazione FRAMERATE dell’ESP32-CAM. La variabile fourcc definisce il formato del codec video; qui è usato XVID, un codec comune per file .avi.

Funzione get_output_filename

Definiamo una funzione di supporto per generare nomi di file basati sulla data corrente:

def get_output_filename():
    date_str = datetime.datetime.now().strftime("%Y-%m-%d")
    return f'recording_{date_str}.avi'

Questa funzione usa il modulo datetime per creare una stringa nel formato YYYY-MM-DD, che viene poi usata per nominare il file di output, ad esempio recording_2025-06-01. Questo assicura che ogni registrazione sia salvata in un file nominato con la data di registrazione e mantiene la dimensione del file limitata. Altrimenti potresti ritrovarti con un file video enorme se la camera si attiva frequentemente.

Variabili

Lo script quindi inizializza variabili per gestire la segmentazione video giornaliera:

current_date = datetime.date.today()
output_file = get_output_filename()
out = cv2.VideoWriter(output_file, fourcc, fps, (frame_width, frame_height))

La variabile current_date memorizza la data odierna. La variabile output_file contiene il nome del file generato da get_output_filename(). L’oggetto out è un OpenCV VideoWriter, usato per scrivere i singoli frame nel file .avi.

Connessione allo stream

Lo script si connette allo stream video dall’ESP32-CAM:

print(f"Connecting to {stream_url}")
stream = requests.get(stream_url, stream=True)

Viene inviata una richiesta GET all’ESP32-CAM. Il parametro stream=True assicura che la risposta sia trattata come uno stream, permettendo di ricevere dati a pezzi.

Controllo stato

Subito dopo il tentativo di connessione, controlliamo lo stato della risposta:

if stream.status_code != 200:
    print(f"Failed to connect to ESP32-CAM. Status code: {stream.status_code}")
    exit()

Se il codice HTTP non è 200 (OK), lo script stampa un messaggio di errore ed esce. In questo caso verifica che l’ESP32-CAM sia acceso, connesso al Wi-Fi e che URL e indirizzo IP per server e client corrispondano, ad esempio http://192.168.2.42/video

Buffer

Lo script inizializza un buffer di byte vuoto per contenere i dati in arrivo dallo stream:

bytes_buffer = b''

Questo buffer sarà usato per accumulare i dati dello stream ed estrarre singole immagini JPEG.

Ciclo principale

Il ciclo principale inizia in un blocco try:

try:
    for chunk in stream.iter_content(chunk_size=1024):
        bytes_buffer += chunk

Lo script legge lo stream in blocchi da 1024 byte e aggiunge ogni blocco a bytes_buffer. Questo approccio gestisce lo stream come una sequenza continua di byte.

All’interno del ciclo, lo script cerca i marcatori di inizio e fine di un’immagine JPEG:

        a = bytes_buffer.find(b'\xff\xd8')  # JPEG start
        b = bytes_buffer.find(b'\xff\xd9')  # JPEG end

Il formato JPEG inizia con la sequenza di byte 0xFF 0xD8 e termina con 0xFF 0xD9. Questi marcatori permettono allo script di isolare immagini JPEG complete dal flusso di byte.

Se entrambi i marcatori sono trovati e nell’ordine corretto, lo script estrae l’immagine JPEG:

        if a != -1 and b != -1 and b > a:
            jpg = bytes_buffer[a:b+2]
            bytes_buffer = bytes_buffer[b+2:]

La porzione jpg contiene l’immagine JPEG grezza. La parte processata viene rimossa dal buffer così lo script può gestire l’immagine successiva.

I dati JPEG vengono poi convertiti in un’immagine OpenCV:

            img_array = np.frombuffer(jpg, dtype=np.uint8)
            frame = cv2.imdecode(img_array, cv2.IMREAD_COLOR)

I byte grezzi sono trasformati in un array NumPy di interi senza segno a 8 bit. Questo array è decodificato usando cv2.imdecode() in un frame immagine reale adatto per la visualizzazione o il salvataggio.

Se si ottiene un frame valido, lo script verifica se la data è cambiata:

            if frame is not None:
                new_date = datetime.date.today()
                if new_date != current_date:
                    out.release()
                    current_date = new_date
                    output_file = get_output_filename()
                    out = cv2.VideoWriter(output_file, fourcc, fps, (frame_width, frame_height))
                    print(f"Started new file: {output_file}")

Confronta la data corrente con quella memorizzata precedentemente. Se è iniziato un nuovo giorno, il file video corrente viene chiuso usando out.release(). Viene generato un nuovo nome file e viene inizializzato un nuovo VideoWriter per iniziare a registrare nel nuovo file.

Il frame corrente viene quindi scritto nel video di output:

                out.write(frame)

Inoltre, lo script mostra il video in una finestra di anteprima in tempo reale:

                cv2.imshow('ESP32-CAM Stream', frame)
                if cv2.waitKey(1) & 0xFF == ord('q'):
                    break

Il frame è visualizzato usando la funzione imshow() di OpenCV. Se l’utente preme il tasto ‘q’, il ciclo termina, fermando lo stream.

Gestione delle eccezioni

Analogamente, se il client viene interrotto da un’interruzione da tastiera, ad esempio con Ctrl+C, lo script assicura nel blocco finally che il file di output e la finestra OpenCV vengano chiusi:

except KeyboardInterrupt:
    pass
finally:
    out.release()
    cv2.destroyAllWindows()
    print(f"Video saved to {output_file}")

E questo è il server! Se ora avvii l’ESP32-CAM (server) e poi il client (app Python) hai un sistema di sorveglianza che cattura video quando viene rilevato movimento e scrive il flusso video in un file con data per una successiva ispezione.

Conclusioni

In questo tutorial hai imparato come costruire un sistema di videosorveglianza attivato dal movimento con l’ESP32-CAM, un sensore di movimento PIR e un PC.

L’ESP32-CAM funziona come un server motion-activated MJPEG video streaming server. Quando un client visita l’URL /video, il server inizia a trasmettere i frame video. Tuttavia, i frame sono catturati e inviati solo quando il sensore PIR rileva movimento. Per maggiori informazioni sul rilevamento del movimento vedi il Motion Activated ESP32-CAM tutorial.

Oltre ad avviare lo streaming video, il LED flash viene attivato per aiutare con l’illuminazione. Se hai problemi a controllare il LED flash dai un’occhiata al Control ESP32-CAM Flash LED tutorial.

Sul lato client uno script Python riceve lo stream video MJPEG attivato dal movimento dall’ESP32-CAM e scrive ogni frame in un file locale .avi. Crea un nuovo file ogni giorno del calendario, facilitando l’organizzazione e l’archiviazione dei filmati. Lo script opzionalmente mostra anche il feed video live e può essere interrotto pulitamente dall’utente.

Se vuoi ricevere notifiche ogni volta che viene rilevato movimento, dai un’occhiata al nostro ESP32 send Telegram Message tutorial, che ti insegna come inviare messaggi all’app Telegram sul tuo telefono.

Se vuoi rilevare oggetti all’interno dello stream video dai un’occhiata al Object Detection with ESP32-CAM and YOLO tutorial. E se ti servono più pin GPIO per altri ingressi o uscite, il More GPIO pins for ESP32-CAM potrebbe avere qualche consiglio utile.

Sentiti libero di lasciare le tue domande nella sezione commenti.

Buon divertimento con il tinkering ; )