Skip to Content

ESP32-CAM attivata dal movimento

ESP32-CAM attivata dal movimento

In questo tutorial imparerai a costruire una ESP32-CAM (AI-Thinker) alimentata a batteria e attivata dal movimento per scattare foto ogni volta che un sensore PIR rileva movimento. Discuteremo diversi sensori PIR, opzioni di alimentazione a batteria e le insidie da evitare.

Questo progetto è perfetto per applicazioni di sorveglianza, sicurezza o monitoraggio della fauna selvatica. Se vuoi registrare video invece di scattare singole foto, dai un’occhiata al nostro Surveillance Camera with ESP32-CAM tutorial.

Overview

Componenti necessari

Di seguito trovi i componenti necessari per realizzare il progetto. Alcuni elementi, come il cavo USB, la micro SD Card o il lettore di SD Card, potresti già averli: in tal caso non è necessario acquistarli, nessuno di questi è specifico per questo progetto. Tuttavia, la SD card non dovrebbe essere più grande di 16 GB; schede più piccole (4 GB o 8 GB) vanno comunque bene.

Ti serve o lo USB-TTL Shield o l’FTDI USB-TTL Adapter, non entrambi. Anche se il modulo ESP32-CAM è fornito con lo USB-TTL Shield, l’FTDI USB-TTL Adapter è più comodo per programmare.

Ho elencato due diversi tipi di sensori di movimento. Se vuoi un ingombro ridotto scegli l’AM312. Se invece vuoi attivare la camera solo di notte, opta per l’HC-SR501, perché può essere facilmente dotato di un sensore di luminosità.

ESP32-CAM con USB-TTL Shield

FTDI USB-TTL Adapter

Dupont wire set

Dupont Wire Set

AM312 PIR Motion Sensor

HC-SR501 PIR Motion Sensor

MicroSD Card 16GB

SD Card Reader

USB data cable

USB Data Cable

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.

Nozioni di base sui sensori di movimento PIR

Esistono molti metodi e sensori per rilevare oggetti in movimento, ma i sensori più comuni sono i PIR (Passive InfraRed) sensori di movimento che rilevano il movimento di oggetti caldi. Un tipico sensore PIR è composto da due Pyroelectric sensing elements e una Fresnel lens.

PIR Motion Sensor Working Principle
Principio di funzionamento del sensore di movimento PIR

Pyroelectric element

Gli elementi Pyroelectric rilevano il calore e sono disposti e collegati in modo che il passaggio di un oggetto generi un segnale di uscita positivo o negativo. Nel caso di un oggetto fermo, i segnali dei due elementi Pyroelectric si annullano a vicenda.

Fresnel lens

La Fresnel lens (cappuccio bianco) concentra la debole radiazione termica del corpo umano e rende il sensore più sensibile. È possibile usare un sensore PIR senza la Fresnel lens, ma sarà meno sensibile e potrebbe generare più falsi allarmi.

Fresnel Lens for PIR Sensor
Fresnel Lens for PIR Sensor

Nota che gli elementi PIR non funzionano dietro il vetro (finestre) e non possono rilevare oggetti alla stessa temperatura dell’ambiente in cui operano. Inoltre assicurati di montare il sensore in orizzontale per la massima sensibilità. Per ulteriori informazioni guarda here.

Tempo di calibrazione

I sensori PIR hanno tipicamente un tempo di calibrazione durante il quale si adattano alla temperatura ambiente corrente. Questo può durare fino a 15 secondi e durante tale periodo potresti ricevere falsi allarmi. Evita movimenti durante la calibrazione per permettere al sensore di adattarsi.

Tempo di blocco e di ritardo

Inoltre, i sensori PIR hanno unblocco e unritardo di tempo. Iltempo di blocco (locking time)di un sensore PIR è il periodo durante il quale il sensore ignora qualsiasi movimento rilevato dopo il trigger iniziale. Questo impedisce che il sensore rimanga costantemente attivato da movimenti continui, consentendo di resettarsi ed evitare falsi allarmi. Per esempio, se il tempo di blocco è impostato a 30 secondi, il sensore non rileverà alcun movimento durante questo intervallo, anche se c’è movimento nel suo raggio di rilevamento.

Tempo di ritardoè invece l’intervallo di tempo che il sensore aspetta prima di attivare un’azione dopo aver rilevato movimento. Questo ritardo può essere utile in situazioni in cui vuoi evitare risposte immediate al movimento, ad esempio accendere una luce solo dopo alcuni secondi di movimento continuo. Per esempio, se il tempo di ritardo è impostato a 10 secondi, il sensore aspetterà questa durata prima di attivare un dispositivo collegato o inviare un segnale.

Alcuni moduli PIR permettono di regolare il tempo di blocco e di ritardo, mentre altri hanno tempi fissi. Sebbene esistano molti moduli PIR, la maggior parte si basa sull’AS312 PIR Sensor, che discuteremo nella sezione successiva.

AS312 PIR Sensor

L’immagine qui sotto mostra un AS312 PIR Sensor e una vista dall’alto con la posizione dei due elementi Pyroelectric evidenziata. La Fresnel Lens è stata rimossa.

AS312 PIR Sensor
AS312 PIR Sensor

L’AS312 funziona a 2.7-3.3V e consuma pochissima corrente (15 μA). Ha un tempo di blocco e di ritardo di 2.3 secondi.

L’AS312 ha già molta elettronica integrata (vedi Datasheet) ma per usarlo all’interno di un circuito servirebbe una tensione di alimentazione stabile (regolatore di tensione) e qualche altro componente. Per questo sono disponibili vari moduli PIR che aggiungono i componenti necessari e offrono funzionalità aggiuntive come tempi di ritardo maggiori di 2.3 secondi e controllo della sensibilità.

Nella sezione successiva esamineremo tre moduli PIR comuni e fornirò alcune raccomandazioni su quali usare con l’ESP32-CAM.

AM312 PIR Module

L’AM312 PIR Module è il più semplice e compatto dei tre moduli PIR discussi. Ha un tempo fisso di ritardo e blocco di circa 2 secondi e non ha regolazione della sensibilità.

Pinout of AM312 PIR Module
Pinout of AM312 PIR Module

Consiste semplicemente dell’AS312 PIR Sensor, di un HT7530 regolatore di tensione e di una resistenza di uscita (20K). Vedi lo schema interno qui sotto. Nota che non c’è protezione di polarità e si può facilmente distruggere il sensore collegandolo nel verso sbagliato.

AM312 PIR Module Schematics
AM312 PIR Module Schematics

Il modulo ha tre pin: alimentazione positiva (VIN), massa (GND) e il pin di uscita (OUT). La tensione di alimentazione è compresa tra 2.7 e 12 Volt e l’uscita è 3.3 Volt (TTL) quando viene rilevato movimento. Il raggio di rilevamento è di 3-5 m e l’angolo di rilevamento è circa 100°.

Questo è il sensore che raccomando per l’ESP32-CAM attivato dal movimento. Ha un breve tempo di ritardo e di blocco (2 s), che ci permette di scattare foto circa ogni 4 secondi. Può essere collegato direttamente a un pin GPIO dell’ESP32-CAM e ha funzionato in modo affidabile nei miei test.

Tuttavia, se hai bisogno di un raggio di rilevamento maggiore e di rilevare solo di notte, consiglio l’HC-SR501, che vedremo nella sezione successiva.

HC-SR501 PIR Module

L’HC-SR501 è il sensore di movimento che si trova più spesso in applicazioni domestiche, come le luci notturne attivate dal movimento. Lo riconosci facilmente per la sua distintiva e relativamente grande Fresnel lens. Vedi l’immagine sotto.

HC-SR501 PIR Module
HC-SR501 PIR Module

Schematics of HC-SR501

Lo schema del modulo HC-SR501 è molto più complesso di quello dell’AM312, poiché offre sensibilità (raggio) e tempo di ritardo regolabili. Utilizza inoltre il RE200B PIR Sensor invece dell’AS312 PIR Sensor. Vedi gli schemi sotto.

HC-SR501 PIR Module Schematics
HC-SR501 PIR Module Schematics

Il tempo di ritardo può essere variato da circa 0,3 secondi fino a 300 secondi. Rimane comunque un tempo di blocco di circa 2,5 secondi. Tuttavia, l’HC-SR501 permette di scattare foto leggermente più frequentemente rispetto all’AS312 (3 secondi vs 4 secondi).

Impostare il ritardo minimo

Poiché controlleremo il tempo di ritardo via software, vogliamo impostare il ritardo hardware al minimo. Per farlo ruota il potenziometro sinistro in senso antiorario fino alla posizione mostrata sotto. Otterrai il tempo di ritardo minimo di circa 0,3 secondi.

Setting minimum delay time for HC-SR501
Impostare il ritardo minimo per HC-SR501

È meglio testare questo senza le complicazioni di un ESP32-CAM prima. Dai un’occhiata al nostro tutorialHow to use HC-SR501 PIR Motion Sensor.

L’altro potenziometro del modulo HC-SR501 consente di variare il raggio di rilevamento (sensibilità) da circa 2 m fino a un massimo di circa 7 m. L’HC-SR501 ha anche un jumper per cambiare la modalità di trigger. Per maggiori dettagli su questo vedi il nostro tutorial How to use HC-SR501 PIR Motion Sensor o questo Datasheet of the HC-SR501.

Attivazione notturna tramite LDR

Il vantaggio principale (oltre al maggiore raggio) dell’HC-SR501 rispetto all’AM312 è che puoi aggiungere un LDR (Light Detector) in modo che il sensore sia attivo solo di notte. Questo è ottimo per monitorare la fauna notturna. Questa funzione non è ben documentata, ma se rimuovi la Fresnel Lens vedi due fori passanti contrassegnati RL e RT. Vedi l’immagine sotto.

Light (RL) and Temperature (RT) ports on HC-SR501
Light (RL) and Temperature (RT) ports on HC-SR501

La RT (Resistor Temperature) permette di aggiungere un termistore, il che rende l’HC-SR501 meno soggetto a falsi allarmi dovuti a variazioni di temperatura ambiente. La RL (Resistor Light) permette di aggiungere un LDR (light dependent resistor), che garantisce che il rilevamento del movimento sia attivo solo di notte.

Il valore specifico della resistenza da usare per l’LDR dipende da quanto buia vuoi che sia l’area affinché il sensore si attivi. È qualcosa che dovrai determinare per tentativi. Ecco un link a un LDR kit with various resistor values che potresti provare. Come linea guida approssimativa, il partitore di tensione nello schema mostrato sopra ha una resistenza da 1MΩ. Probabilmente vorrai scegliere un LDR con un valore simile per cominciare.

Ingressi e uscite

Gli ingressi e le uscite dell’HC-SR501 sono sostanzialmente gli stessi dell’AM312. Devi fornire una tensione di alimentazione ai pin VCC e GND compresa tra 4.5V e 20V e il pin di uscita andrà alto (3.3V) quando viene rilevato movimento. L’immagine sotto mostra il Pinout.

Pinout of HC-SR501 PIR Module
Pinout of HC-SR501 PIR Module

In sintesi, se vuoi un sensore PIR piccolo, semplice ed economico scegli l’AM312. Funzionerà bene. Se vuoi un raggio migliore e limitare il rilevamento al periodo notturno, scegli l’HC-SR501.

Nella sezione successiva parlerò brevemente dell’HC-SR505, che si è rivelato inadatto e non può essere raccomandato per questa applicazione.

HC-SR505 PIR Module

L’HC-SR505 PIR Module è un po’ più lungo dell’AM312 ma utilizza lo stesso AS312 PIR Sensor e ha lo stesso Pinout. Vedi l’immagine sotto dell’HC-SR505

Pinout of HC-SR505 PIR Sensor
Pinout of HC-SR505 PIR Sensor

La tensione di alimentazione è compresa tra 4.5V e 20V e l’uscita è TTL (3.3V). Il raggio di rilevamento è di 3-4 metri (9-12 piedi) e il tempo di ritardo è fisso a circa 8 secondi.

A parte il lungo tempo di ritardo che ti limiterebbe a scattare una foto solo ogni 8 secondi, ho anche riscontrato che il sensore dava problemi quando ho usato una power bank 5V come alimentazione. Ho provato diversi sensori dello stesso tipo (HC-SR505) ma l’uscita restava sempre alta. Sospetto che il ripple ad alta frequenza della power bank abbia causato questo (ne parlerò più avanti).

L’HC-SR501 e l’AM312 non hanno avuto problemi con questa power bank, mentre l’HC-SR505 PIR Module si rifiutava di funzionare correttamente. Inoltre, anche alimentando l’ESP32-CAM con una batteria da 9V o con una coppia di 18650, che non hanno ripple, l’HC-SR505 non funzionava ed era sempre attivo. Di nuovo, sospetto che l’interferenza ad alta frequenza dell’ESP32-CAM con l’HC-SR505 sia la causa.

In breve, l’HC-SR505 PIR Module non è adatto per scattare foto attivate dal movimento con l’ESP32-CAM. Nota, comunque, che ho utilizzato l’HC-SR505 in altri progetti senza problemi.

Passiamo ora a dare rapidamente un’occhiata al modulo ESP32-CAM.

Presentazione dell’AI-Thinker ESP32-CAM

La scheda di sviluppo AI-Thinker ESP32-CAM è un modulo compatto che combina un chip ESP32-S, una camera, un flash integrato e uno slot per microSD. La scheda integra Wi‑Fi e Bluetooth e supporta una fotocamera OV2640 o OV7670 fino a 2 megapixel di risoluzione.

Back of ESP32-CAM
Front of ESP32-CAM
Front of ESP32-CAM

Puoi trovare più dettagli sulla scheda ESP32-CAM e in particolare su come caricarci il codice nel nostro tutorial Programming the ESP32-CAM. Leggilo assolutamente, perché caricare il codice sulla scheda ESP32-CAM è complicato. In questo tutorial mi concentrerò sull’implementazione dell’attivazione tramite movimento per l’ESP32-CAM.

Pinout

L’immagine seguente mostra il Pinout dell’ESP32-CAM. Nota che in teoria l’ESP32-CAM può funzionare a 3.3V, ma sono stati segnalati comportamenti instabili. Si possono usare da 5V fino a 15V, ma non andrei oltre i 12V e anche in quel caso il regolatore di tensione potrebbe scaldarsi molto. Discuteremo le diverse opzioni di alimentazione più avanti.

Pinout of the ESP32-CAM module
Pinout del modulo ESP32-CAM AI-Thinker (source)

Il pin P_OUT è etichettato come VCC su alcune schede. È un pin di uscita che fornisce 3.3V o 5V a seconda di un solder pad. Non puoi usare questo pin per alimentare la scheda! Usa invece il pin 5V per quello.

Nota che la maggior parte dei pin GPIO dell’ESP32-CAM sono già usati dalla camera e dal lettore di SD card. Inoltre, dovresti evitare di usare GPIO1, GPIO3 e GPIO0, poiché sono necessari per programmare la scheda. Inoltre, GPIO0 è collegato al pin XCLK della camera e dovrebbe essere lasciato flottante (non collegato) quando l’ESP32 è in funzione.

Infine, i pin GPIO 2, 4, 12, 13, 14 e 15 sono parzialmente utilizzati dal lettore di SD Card. Se non usi il lettore di SD Card sono disponibili come GPIO. Per maggiori dettagli vedi il nostro More GPIO pins for ESP32-CAM tutorial.

Nel seguito useremo GPIO 13 per l’attivazione al movimento. I dettagli su come collegare un sensore di movimento PIR all’ESP32-CAM sono descritti nella sezione successiva.

Collegare il sensore PIR all’ESP32-CAM

Collegare l’AM312 PIR Sensor Module all’ESP32-CAM è molto semplice. Collega un’alimentazione (batteria) da 5V (fino a 12V) al pin 5V e al GND dell’ESP32-CAM come mostrato sotto (fili rosso e blu).

Connecting AM312 PIR Sensor to ESP32-CAM
Connecting AM312 to ESP32-CAM

Puoi alimentare la scheda con più di 5V. Non preoccuparti: un regolatore di tensione è collegato al pin 5V e ridurrà la tensione d’ingresso al livello richiesto dalla scheda. Ma non superare i 12V, altrimenti il regolatore potrebbe surriscaldarsi.

Allo stesso modo, collega l’AM312 PIR Sensor Module all’alimentazione (fili rosso e blu). 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).

Non collegare l’AM312 al pin 3.3V per l’alimentazione. In teoria dovrebbe andare bene, ma in pratica ho avuto problemi di rilevamento quando l’AM312 era alimentato a 3.3V. Se usi l’HC-SR501 PIR Sensor Module invece dell’AM312, collegalo nello stesso modo (GND a GND, VCC a 5V-12V).

Sia l’AM312 sia l’HC-SR501 possono gestire una tensione di alimentazione da 5V a 12V. Quindi puoi alimentare sia l’ESP32-CAM sia il sensore PIR con la stessa batteria e la stessa tensione.

Circuito con transistore

Nota che esistono molti tutorial che propongono un circuito con transistore per collegare un sensore PIR all’ESP32-CAM. Questo NON è necessario! L’uscita del sensore PIR (anche quella debole dell’AM312) può pilotare facilmente l’ingresso GPIO. Collegare il sensore PIR direttamente all’ESP32-CAM va bene, funziona e è molto più semplice.

Caricare il codice

Se usi un FTDI USB-TTL Adapter puoi tenere il sensore PIR collegato mentre carichi e testi il codice. Se usi lo USB-TTL Shield, invece, devi scollegare e ricollegare il sensore PIR ogni volta che carichi ed esegui nuovo codice, il che è piuttosto fastidioso.

Perciò raccomando vivamente di usare un FTDI USB-TTL Adapter. L’immagine sotto mostra come appare. Non hai nemmeno bisogno di una breadboard; bastano dei fili Dupont.

FTDI Adapter and PIR Sensor connected to ESP32-CAM
FTDI Adapter and PIR Sensor connected to ESP32-CAM

I dettagli su come collegare l’FTDI USB-TTL Adapter e come caricare il codice si trovano nel nostro tutorial Programming the ESP32-CAM.

Nella sezione successiva ti mostrerò il codice per l’ESP32-CAM attivato dal movimento.

Codice per l’ESP32-CAM attivato dal movimento

Il codice seguente è un’implementazione completa per un’ESP32-CAM attivata dal movimento. Dai prima un’occhiata rapida per farti un’idea generale, prima di entrare nei dettagli.

// Motion activated ES32-CAM
// Makerguides.com

#include "esp_camera.h"
#include "soc/rtc_cntl_reg.h"
#include "driver/rtc_io.h"
#include "SD_MMC.h"
#include "EEPROM.h"

// 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

void configCamera() {
  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_sscb_sda = SIOD_GPIO_NUM;
  config.pin_sscb_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_UXGA;
  config.jpeg_quality = 10;
  config.fb_count = 2;
  esp_err_t err = esp_camera_init(&config);

  sensor_t* s = esp_camera_sensor_get();
  s->set_brightness(s, 0);
  s->set_contrast(s, 0);
  s->set_saturation(s, 0);
  s->set_special_effect(s, 0);
  s->set_whitebal(s, 1);
  s->set_awb_gain(s, 1);
  s->set_wb_mode(s, 0);
  s->set_exposure_ctrl(s, 1);
  s->set_aec2(s, 0);
  s->set_ae_level(s, 0);
  s->set_aec_value(s, 300);
  s->set_gain_ctrl(s, 1);
  s->set_agc_gain(s, 0);
  s->set_gainceiling(s, (gainceiling_t)0);
  s->set_bpc(s, 0);
  s->set_wpc(s, 1);
  s->set_raw_gma(s, 1);
  s->set_lenc(s, 1);
  s->set_hmirror(s, 0);
  s->set_vflip(s, 0);
  s->set_dcw(s, 1);
  s->set_colorbar(s, 0);
}

unsigned int incCounter() {
  unsigned int cnt = 0;
  EEPROM.get(0, cnt);
  EEPROM.put(0, cnt + 1);
  EEPROM.commit();
  return cnt;
}

void enableFlash(bool enable) {
  if (enable) {
    rtc_gpio_hold_dis(GPIO_NUM_4);
  } else {
    pinMode(GPIO_NUM_4, OUTPUT);
    digitalWrite(GPIO_NUM_4, LOW);
    rtc_gpio_hold_en(GPIO_NUM_4);
  }
}

void skipPictures(int n) {
  for(int i=0; i<n; i++) {
    camera_fb_t* fb = esp_camera_fb_get();
    esp_camera_fb_return(fb);
  }
}

void takePicture() {
  camera_fb_t* fb = esp_camera_fb_get();
  unsigned int cnt = incCounter();
  String path = "/img" + String(cnt) + ".jpg";
  File file = SD_MMC.open(path.c_str(), FILE_WRITE);
  file.write(fb->buf, fb->len);
  file.close();
  esp_camera_fb_return(fb);
}

void deepSleep(int atleast) {
  esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
  rtc_gpio_pulldown_en(GPIO_NUM_13);
  rtc_gpio_pullup_dis(GPIO_NUM_13);
  esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, 1);
  delay(atleast);
  esp_deep_sleep_start();
}

void setup() {
  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
  enableFlash(true);
  EEPROM.begin(8);
  SD_MMC.begin();
  configCamera();
  skipPictures(10);
  takePicture();
  enableFlash(false);
  deepSleep(5000);
}

void loop() {
}

Questo codice mette l’ESP32-CAM in deep sleep e attende un segnale su GPIO13 che indica che il sensore PIR ha rilevato movimento. Se viene rilevato movimento, l’ESP32-CAM si risveglia, scatta una singola foto, la salva sulla SD card con un numero progressivo e torna in sleep.

Analizziamo il codice passo passo per capire come funziona la configurazione della camera e il processo di acquisizione delle immagini.

Librerie incluse

#include "esp_camera.h"
#include "soc/rtc_cntl_reg.h"
#include "driver/rtc_io.h"
#include "SD_MMC.h"
#include "EEPROM.h"

Nella prima parte includiamo le librerie necessarie per controllare la camera, la SD card e l’EEPROM. Inoltre servono alcune funzioni relative al real time clock (RTC) durante il deep sleep.

Costanti model definitions Esistono vari modelli di schede ESP32-CAM. Questo codice è specifico per il modello AI-Thinker ma funzionerà con la maggior parte delle altre schede camera basate su ESP32, a condizione che abbiano PSRAM (vedi pin definitions).

Nella sezione di codice sotto definiamo i pin specifici per il modello AI-Thinker. Se hai una scheda ESP32-CAM diversa probabilmente dovrai modificare queste costanti. Qui puoi trovare il per altri modelli supportati.

// 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

Configurazione della camera

La configCamera() funzione configura la camera con impostazioni specifiche come il canale LEDC, i pin per le linee dati, i segnali di clock e le impostazioni immagine come formato, dimensione e qualità. Se non sei soddisfatto della qualità dell’immagine dell’ESP32-CAM, prova a modificare questi parametri.

void configCamera() {
  sensor_t* s = esp_camera_sensor_get();
  s->set_brightness(s, 0);
  s->set_contrast(s, 0);
  ...
  s->set_colorbar(s, 0);
}

Incremento del contatore

La incCounter() funzione legge e incrementa un contatore memorizzato nella memoria EEPROM. Questo contatore viene usato per assegnare nomi sequenziali alle immagini catturate. Ogni volta che viene chiamata incrementa il contatore. Il contatore deve essere memorizzato in EEPROM

unsigned int incCounter() {
  unsigned int cnt = 0;
  EEPROM.get(0, cnt);
  EEPROM.put(0, cnt + 1);
  EEPROM.commit();
  return cnt;
}

in modo che non venga perso durante il deep sleep.EEPROM.get(0, cnt)Il codice è molto semplice. Prima otteniamo il contatore corrente tramite EEPROM.put(0, cnt + 1, poi memorizziamo un contatore incrementato tramite EEPROM.commit() e confermiamo il cambiamento usando

. Infine, ritorniamo il contatore corrente. La prossima volta che la funzione viene chiamata restituirà il contatore incrementato che abbiamo appena memorizzato e lo incrementerà di nuovo.

Nota che dobbiamo riservare memoria per il contatore in EEPROM. Questo viene fatto più avanti, chiamando EEPROM.begin(8) nella funzione setup(). Il contatore è un valore unsigned integer di 4 byte. Ma per sicurezza riservo 8 byte di memoria, tanto per essere sicuri.

Un contatore unsigned integer a 4 byte può contare fino a 4.294.967.295 prima di andare in overflow. È sicuramente sufficiente per enumerare in modo univoco tutte le immagini che vogliamo salvare sulla SD card.

Controllo del flash

La enableFlash() enable funzione abilita o disabilita il flash in base al parametro. Questo è un punto delicato. Il problema con l’ESP32-CAM è che la scrittura sulla SD Card fa accendere il LED del flash e quando si entra in deep sleep successivamente il LED del flash rimane acceso.

Semplicemente impostare GPIO4 su LOW, dove è collegato il LED del flash, non è sufficiente. Durante il deep sleep questo livello di uscita viene perso. Per mantenere rtc_gpio_hold_en(GPIO_NUM_4), che indica all’ESP32 di preservare lo stato di GPIO4 durante il deep sleep.

Ma GPIO4 fa anche parte dell’interfaccia SD Card, e quindi non possiamo lasciarlo bloccato a quel livello. Quindi, quando l’ESP32-CAM si risveglia disabilitiamo il mantenimento di GPIO4 tramite rtc_gpio_hold_dis(GPIO_NUM_4) e lasciamo che l’ESP32-CAM lo controlli per scattare una foto e scrivere sulla SD card.

Prima di mettere l’ESP32-CAM in deep sleep chiamiamo enableFlash(false), che spegne il LED del flash e preserva quello stato durante il deep sleep.

void enableFlash(bool enable) {
  if (enable) {
    rtc_gpio_hold_dis(GPIO_NUM_4);
  } else {
    pinMode(GPIO_NUM_4, OUTPUT);
    digitalWrite(GPIO_NUM_4, LOW);
    rtc_gpio_hold_en(GPIO_NUM_4);
  }
}

Saltare le immagini

La funzione SkipPictures(n) acquisisce n immagini e le scarta. Il motivo per cui facciamo questo è il seguente: la camera ha diverse funzioni automatiche integrate, ad esempio l’auto bilanciamento del bianco e altre che impiegano tempo e più fotogrammi per adattarsi all’ambiente. Dopo un riavvio dal deep sleep, quindi, dobbiamo dare alla camera un po’ di tempo per adattarsi.

void skipPictures(int n) {
  for(int i=0; i<n; i++) {
    camera_fb_t* fb = esp_camera_fb_get();
    esp_camera_fb_return(fb);
  }
}

Se scatti la prima immagine dopo un riavvio noterai che è di qualità pessima. Tipicamente con una forte dominante blu o troppo scura o troppo chiara. Tuttavia, scartando i primi fotogrammi nella maggior parte dei casi (ma non sempre) ottieni immagini di buona qualità.

Puoi anche provare a disabilitare l’auto bilanciamento del bianco e altre funzioni automatiche nelle impostazioni della camera, ma in quel caso avrai bisogno di un ambiente abbastanza stabile per poter regolare gli altri parametri. Altrimenti sarà difficile ottenere immagini di buona qualità.

Scattare foto

La funzione takePicture() acquisisce un’immagine usando la camera e la salva sulla SD card con un nome file unico basato sul valore del contatore. Per prima cosa creiamo un frame buffer fb chiamando esp_camera_fb_get(). Poi creiamo un nome file unico per l’immagine e salviamo il frame buffer come file JPG (img{cnt}.jpg) sulla SD card. Infine liberiamo la memoria usata dal frame buffer chiamando esp_camera_fb_return.

void takePicture() {
  camera_fb_t* fb = esp_camera_fb_get();
  unsigned int cnt = incCounter();
  String path = "/img" + String(cnt) + ".jpg";
  File file = SD_MMC.open(path.c_str(), FILE_WRITE);
  file.write(fb->buf, fb->len);
  file.close();
  esp_camera_fb_return(fb);
}

Deep Sleep

La funzione deepSleep() mette l’ESP32 in modalità deep sleep per una durata specificata dopo aver catturato l’immagine. Questo aiuta a risparmiare energia quando il dispositivo non sta scattando foto.

Le tre righe all’inizio (esp_sleep_pd_config, rtc_gpio_pulldown_en, rtc_gpio_pullup_dis ) abilitano la resistenza di pull-down interna su GPIO13, dove è collegato il sensore PIR. Il codice/ESP32-CAM funziona anche senza usare la resistenza di pull-down interna, ma qui ho preferito essere prudente.

Dopo di ciò specifichiamo la sorgente di wakeup tramite esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, 1). Questo significa che se GPIO13 va a livello alto (1 = il sensore PIR ha rilevato movimento), risvegliamo l’ESP32-CAM dal deep sleep.

Prima di andare in deep sleep, noi delay per alcuni secondi (atleast) per evitare di scattare foto troppo frequentemente. Io ho usato 5 secondi e non puoi andare molto più veloce a causa dei tempi di blocco e ritardo del sensore PIR. Ma puoi certamente aumentare il tempo, ad esempio 10 o 60 secondi, se vuoi ridurre il numero di foto scattate.

void deepSleep(int atleast) {
  esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
  rtc_gpio_pulldown_en(GPIO_NUM_13);
  rtc_gpio_pullup_dis(GPIO_NUM_13);
  esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, 1);
  delay(atleast);
  esp_deep_sleep_start();
}

Funzione setup

La funzione setup() è dove mettiamo tutto insieme. Prima chiamiamo WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0) per disabilitare la rilevazione di brownout. Se l’alimentazione è instabile o l’ESP32-CAM assorbe temporaneamente troppa corrente all’avvio del WiFi o durante la scrittura sulla SD card, questo evita un reset automatico. Per maggiori dettagli vedi questo post del blog Disabling the ESP32 Brownout detector.

Io non ho avuto problemi di brownout e probabilmente puoi disabilitare quella riga. Il vantaggio della rilevazione brownout è che riduce il rischio di corruzione della SD card. Lo svantaggio è che potrebbe causare reset accidentali e indesiderati. La scelta dipenderà dall’alimentazione che stai usando, quale sia preferibile.

Dopo aver specificato la gestione del brownout, abilitiamo il LED del flash tramite enableFlash(true). Poi riserviamo 8 byte in EEPROM per memorizzare il contatore dei file, inizializziamo la SD card con SD_MMC.begin() e configuriamo la Camera.

Infine, scattiamo effettivamente la foto chiamando la nostra funzione takePicture(). Dopo ciò disabilitiamo il LED del flash e mandiamo l’ESP32-CAM in deep sleep (per almeno 5 secondi).

void setup() {
  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
  enableFlash(true);
  EEPROM.begin(8);
  SD_MMC.begin();
  configCamera();
  takePicture();
  enableFlash(false);
  deepSleep(5000);
}

Funzione loop

La funzione loop() è vuota in questo codice poiché la funzionalità principale è implementata nella funzione setup. L’ESP32 eseguirà la setup, poi entrerà in deep sleep, si risveglierà quando viene rilevato movimento ed eseguirà di nuovo la setup. La funzione loop non viene mai eseguita.

void loop() {
  // Empty loop
}

E questo è tutto. Ecco il codice completo per un’ESP32-CAM attivata dal movimento.

Quando esegui il codice potresti notare che il contatore dei file parte da un numero arbitrario e non da zero. Puoi resettare il contatore dei file eseguendo il codice seguente.

Resettare il contatore dei file

Caricando ed eseguendo il codice qui sotto resetterai il contatore dei file memorizzato all’indirizzo 0 a zero. Dopo di ciò dovrai caricare nuovamente il codice originale per lo scatto delle foto.

#include "EEPROM.h"
  
void setup() {
  EEPROM.begin(512);
  unsigned int cnt = 0;
  EEPROM.put(0, cnt);
  EEPROM.commit();
}

void loop() {
}

Abbiamo il codice e i collegamenti, ora parliamo dell’alimentazione per il progetto.

ESP32-CAM alimentata a batteria

Spesso si desidera far funzionare un’ESP32-CAM attivata dal movimento a batteria, ad esempio per il monitoraggio della fauna. Trovare la sorgente di alimentazione giusta si rivela piuttosto complicato. Di seguito ti mostro quattro opzioni che ho esplorato.

Power Bank USB 1

La prima opzione è usare una comune USB Power Bank. Chiunque abbia un telefono tende ad averne una per ricaricare il telefono in emergenza. Ho provato a usare la Power Bank mostrata sotto.

USB Power Bank with automatic Shutdown
USB Power Bank con spegnimento automatico

Questa è una Power Bank da 30000mAh che potrebbe alimentare l’ESP32-CAM per molto tempo. Tuttavia, questa Power Bank ha uno spegnimento automatico. Se il carico sull’uscita è molto basso (<80mA), cosa che accade quando l’ESP32-CAM va in deep sleep (6mA), la Power Bank si spegne.

L’ESP32-CAM funzionava per circa 10-15 secondi, scattava qualche foto e poi non si risvegliava più. Mi ci è voluto molto tempo per capirlo, pensando che il mio codice o i collegamenti fossero difettosi 🙁

Lezione imparata: non usare una Power Bank con spegnimento automatico per questo.

Power Bank USB 2

Avevo una seconda Power Bank mostrata sotto, con capacità 10000mAh.

USB Power Bank without automatic Shutdown
USB Power Bank senza spegnimento automatico

Questa Power Bank non si spegne automaticamente, ma provandola con l’HC-SR505 PIR Module non sono riuscito a far funzionare correttamente il sensore. L’uscita del sensore restava sempre alta, anche usando il modulo sensore in isolamento (senza l’ESP32-CAM), con solo l’alimentazione e un LED.

Un’osservazione con l’oscilloscopio ha rivelato che questa Power Bank presenta un ripple evidente sulla sua uscita 5V con una frequenza di circa 160Hz e un’ampiezza di 88mV. Sospetto che ciò abbia causato i problemi con l’HC-SR505 PIR Module, visto che questo sensore funzionava correttamente alimentato, per esempio, con una batteria da 9V.

Ripple della tensione d’uscita della Power Bank USB 5V

Sebbene l’ESP32-CAM con un sensore HC-SR501 o AM312 abbia funzionato bene con questa Power Bank durante i test, ero un po’ preoccupato per il comportamento a lungo termine. Sarebbe affidabile questo setup se lasciato in funzione per giorni o settimane?

Motion-activated ESP32-CAM powered by USB Power Bank
Motion-activated ESP32-CAM powered by USB Power Bank

Penso che la soluzione migliore sia usare una batteria ricaricabile semplice che non abbia il circuito boost interno di una USB Power Bank, che provoca questi ripple sulla tensione d’uscita.

Batteria ricaricabile 9V

Per alimentare l’ESP32-CAM insieme al sensore PIR puoi usare semplicemente una batteria da 9V. Qui ho usato una batteria ricaricabile 9V da 1000mAh collegata direttamente al pin 5V della scheda ESP32-CAM e al pin VCC del sensore PIR.

Motion-activated ESP32-CAM powered by 9V battery

Questo setup funziona bene ma l’autonomia non è eccezionale. Mentre l’ESP32-CAM consuma solo 6mA in deep sleep, può arrivare fino a 240mA quando è attivo. Quindi in deep sleep potremmo funzionare per 1000mAh / 6mA = 166,67 ore = 6,9 giorni, il che non è male. Ma se scattiamo foto frequentemente l’autonomia sarà molto più breve.

Il breve video qui sotto dimostra che l’ESP32-CAM con un AM312 PIR Sensor Module può funzionare con una batteria da 9V.

Motion-activated ESP32-CAM powered by 9V battery in Action
Motion-activated ESP32-CAM powered by 9V battery in Action

Nella sezione successiva esaminiamo batterie con capacità maggiori per aumentare l’autonomia.

Pacco batteria 18650 ricaricabile

Prendiamo quindi una batteria più grande. Una 18650 al litio ha una tensione nominale di 3.6V e una capacità che va da 1800mAh a 2800mAh. Due in serie ci danno 7.2V di uscita, che è un valore comodo per l’ESP32-CAM e lascia anche un margine per il calo di tensione.

Motion-activated ESP32-CAM powered by two 18650 batteries
Motion-activated ESP32-CAM powered by two 18650 batteries

Con una capacità di 2800mAh possiamo quasi triplicare l’autonomia (rispetto alla batteria da 1000mAh). E se serve ancora più capacità possiamo semplicemente aggiungere una seconda coppia di 18650 e raddoppiare di nuovo l’autonomia.

Ma fai attenzione alla polarità corretta quando colleghi le batterie al circuito. Le 18650 possono erogare correnti elevate e io ho bruciato uno dei miei sensori PIR facendo questo errore.

Nella sezione seguente cerco di ottenere una stima migliore dell’autonomia.

Autonomia

Ho misurato il consumo in deep sleep dell’ESP32-CAM con l’AM312 PIR Sensor collegato e ho ottenuto 3.6mA in deep sleep. Quando è attivo e scatta una foto il consumo è stato di circa 120mA.

Se usiamo le due 18650 lithium-ion batteries 18650 in serie con una capacità totale di 2800mAh, otteniamo 2800mAh / 3.6mA = 777,7 ore = 32 giorni di funzionamento in deep sleep. È un mese di autonomia ma senza scattare alcuna foto.

Supponiamo di scattare 100 foto durante il periodo. Poiché l’ESP32-CAM è attiva per 5 secondi ogni volta che scattiamo una foto, questo corrisponde a 100 * 120mA * 5sec / 60 = 1000mAh.

Se sottraiamo quei 1000mAh dalla capacità della batteria di 2800mAh, rimangono 1800mAh che danno un’autonomia di 1800mAh / 3.6mA = 500 ore = 20 giorni. Quasi tre settimane; penso sia discreto. Ovviamente temperature esterne basse o un numero maggiore di foto possono ridurre drasticamente l’autonomia. D’altra parte, aggiungere una seconda coppia di 18650 è semplice e raddoppia l’autonomia.

Conclusioni

In questo tutorial abbiamo costruito con successo un’ESP32-CAM attivata dal movimento usando un sensore PIR. Abbiamo imparato le basi dei sensori di movimento PIR e come collegarli all’AI-Thinker ESP32-CAM. Implementando il codice fornito, la nostra ESP32-CAM può ora catturare immagini ogni volta che viene rilevato movimento.

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.

Inoltre, abbiamo esplorato la possibilità di alimentare l’ESP32-CAM con batterie per una soluzione più portatile. Questo progetto apre diverse possibilità per creare sistemi di sorveglianza, fotocamere per la fauna selvatica o qualsiasi applicazione che richieda rilevamento di movimento e acquisizione di immagini.

Le lezioni principali sono che bisogna fare attenzione nella scelta dei sensori PIR e nella soluzione di alimentazione a batteria. Far funzionare l’ESP32-CAM non è facile, ma il risultato finale vale lo sforzo.

Buon divertimento!

Domande frequenti

Ecco alcune domande comuni e soluzioni per aiutarti nel troubleshooting:

D: Ci sono sensori PIR specifici che funzionano meglio con l’ESP32-CAM?

R: Sì, usa l’HC-SR501 o l’AM312. Non usare l’HC-SR505, perché il suo tempo di ritardo è troppo lungo e causa problemi quando collegato all’ESP32-CAM.

D: Come posso regolare la sensibilità del sensore PIR?

R: Alcuni sensori PIR (incluso l’HC-SR501) sono dotati di un potenziometro che permette di regolare la sensibilità. Ruotando il potenziometro puoi affinare il raggio di rilevamento del sensore.

D: Posso alimentare l’ESP32-CAM con una batteria?

R: Sì, puoi alimentare l’ESP32-CAM con una batteria per una soluzione portatile. Se usi una USB Power Bank assicurati che non abbia lo spegnimento automatico. L’opzione migliore è una coppia di batterie 18650 o qualsiasi altra soluzione che fornisca alimentazione stabile nell’intervallo 5V–12V.

D: Devo modificare il codice per sensori PIR diversi?

R: Il codice fornito in questo tutorial è generico e dovrebbe funzionare con la maggior parte dei sensori PIR.

D: Qual è il raggio di un sensore PIR per rilevare il movimento?

R: Dipende dal sensore specifico e dalle condizioni ambientali, ma tipicamente è intorno a 5 metri. Nota che non puoi posizionare il rivelatore dietro il vetro e non rileverà oggetti alla stessa temperatura dell’ambiente.

D: Ci sono sensori di movimento alternativi che possono essere usati con l’ESP32-CAM?

R: Sì, ci sono altri sensori di movimento come sensori ad ultrasuoni, barriere fotoelettriche o sensori a microonde che possono essere usati con l’ESP32-CAM.

D: Come posso estendere la durata della batteria dell’ESP32-CAM?

R: Per estendere la durata della batteria dell’ESP32-CAM puoi aumentare il tempo di ritardo. Inoltre, usare una batteria con capacità maggiore prolunga l’autonomia.

D: Perché le immagini scattate dall’ESP32-CAM hanno una dominante blu dopo un riavvio?

R: La camera ha funzioni automatiche, ad esempio l’auto bilanciamento del bianco, che richiedono tempo per adattarsi all’ambiente. Senza questo otterrai immagini con dominante blu o molto scure o molto chiare. Un modo semplice per evitarlo è scattare diverse immagini dopo un riavvio e ignorarle. Vedi la funzione skipPictures() nel tutorial che fa esattamente questo.