Come creare un semplice sistema di videosorveglianza controllato da Telegram con ESP32 su PlatformIO

Introduzione

Abbiamo già visto come realizzare un semplice sistema di videosorveglianza con la board Freenove ESP32-WROVER CAM Board con fotocamera nell’articolo Come creare un semplice sistema di videosorveglianza con ESP32 su PlatformIO.

In quel progetto la board ci manda le immagini, tramite un web server incorporato, ad un certo URL apribile col nostro browser.

Ciò che vorremmo fare in questo articolo è realizzare un progetto dove la board, connessa alla rete WiFi, è controllabile in maniera remota tramite un bot Telegram. Ciò ci consentirà di mandare un comando al bot e ottenere come risposta una foto scattata dalla nostra Freenove. Inoltre il nostro dispositivo sarà equipaggiato con un sensore ad ultrasuoni HC-SR04 usato come rivelatore di presenza di un eventuale intruso. Quando il sensore avverte la presenza di una persona o, comunque, di qualcosa in movimento darà il comando di scattare una foto alla nostra board la quale ce la invierà tramite il bot.

Il sensore ad ultrasuoni HC-SR04, che abbiamo già utilizzato nell’articolo Distanziometro a ultrasuoni con LCD display su Arduino UNO, si comporta essenzialmente come un sonar: emette un suono ad alta frequenza, ben oltre ciò che l’orecchio umano può sentire, e attende l’eco.
Una volta captata l’eco, conta il tempo intercorso tra l’emissione del segnale ultrasonico e la cattura della sua eco, e in base a questo calcola, sapendo la velocità del suono nell’aria, la distanza approssimativa dell’oggetto che ha prodotto l’eco.

La funzione di rilevazione presenza può essere attivata o disattivata sempre tramite un comando mandato col bot Telegram. Sarà però sempre possibile scattare foto manualmente, tramite un apposito comando al bot. Tale impostazione verrà salvata sulla memoria EEPROM della board in modo da conservarla anche se dovesse mancare l’alimentazione. Per sapere come funziona la memoria EEPROM puoi dare un’occhiata al tutorial Come usare la memoria EEPROM sul NodeMCU ESP8266. Anche se è riferito alla board NodeMCU ESP8266 va bene anche per quella oggetto di questo tutorial.

Ecco come si presenta la Freenove ESP32 WROVER CAM
Ecco come si presenta la Freenove ESP32 WROVER CAM

Di che componenti abbiamo bisogno?

La lista dei componenti non è particolarmente lunga:

  • una breadboard per connettere la board Freenove ESP32-WROVER CAM Board con fotocamera agli altri componenti
  • alcuni fili DuPont (maschio – maschio, maschio – femmina, femmina – femmina)
  • un modulo HC-SR04
  • e, ovviamente, una board Freenove ESP32-WROVER CAM Board con fotocamera, acquistabile su Amazon a questo link!

Realizziamo il progetto

Lo schema di realizzazione

Vediamo innanzitutto il pinout della nostra board:

Il pinout della Freenove ESP32 WROVER CAM
Il pinout della Freenove ESP32 WROVER CAM

Non tutti i pin saranno utilizzabili liberamente in quanto sono impiegati dalla fotocamera (quelli contrassegnati dalle etichette celesti che cominciano con CAM). I GPIO che utilizzaremo in questo progetto sono il 32 e il 33, non utilizzati dalla fotocamera.

Di seguito puoi vedere lo schema Fritzing dei collegamenti:

Schema di montaggio
Schema di montaggio

L’alimentazione del modulo ad ultrasuoni è ricavata dai pin VCC e GND della board, mentre terminali per il trigger e l’echo sono collegati rispettivamente ai pin 33 e 32 della Freenove.

Creiamo il progetto per lo sketch su PlatformIO

Abbiamo già visto in un articolo precedente come creare un progetto usando l’ottimo IDE PlatformIO. Creiamo quindi il nostro progetto seguendo le indicazioni dell’articolo Come creare un progetto per NodeMCU ESP8266 con PlatformIO. Anche se si riferisce alla board ESP8266, la procedura è simile.
Semplicemente, nella scelta della piattaforma dovremo scegliere la Espressif ESP-WROVER-KIT.

Delle librerie descritte dall’articolo, installiamo solo la UniversalTelegramBot in quanto l’altra che ci serve (WifiManager) la aggiungeremo in maniera diversa.

Il file platformio.ini, che troverai nel progetto scaricabile dal link più sotto, dovrà essere modificato in modo che contenga le seguenti righe (dopo l’intestazione commentata):

[env:esp-wrover-kit]
platform = espressif32
board = esp-wrover-kit
framework = arduino
monitor_speed = 115200
upload_speed = 921600
board_build.partitions = huge_app.csv
build_flags = -DBOARD_HAS_PSRAM
lib_deps = 
	https://github.com/tzapu/WiFiManager.git
	witnessmenow/UniversalTelegramBot@^1.3.0

Con queste impostazioni stiamo definendo la piattaforma (esp-wrover-kit), la velocità del Serial Monitor (115200), la velocità di caricamento dello sketch (921600), il tipo di partizione di memoria da usare (huge_app.csv), la presenza di una PSRAM (-DBOARD_HAS_PSRAM), la libreria UniversalTelegramBot e la libreria WiFiManager direttamente dal suo repository (https://github.com/tzapu/WiFiManager.git).

Ovviamente abbiamo bisogno anche del progetto, scaricabile dal link sotto:

Sovrascrivi il file main.cpp con quello appena scaricato e copia nella cartella src il file app_httpd.cpp e nella cartella include i file camera_index.h e camera_pins.h.

Compila ora il progetto e caricalo sulla board. Se non ci sono errori, il prossimo passo sarà quello di connettere la board alla rete WiFi.

Come connettere la board ad Internet

Dopo aver caricato lo sketch sulla board, apri il Serial Monitor per vedere i messaggi provenienti dal dispositivo.

Per prima cosa la board va in modalità Access Point e ci fornirà un indirizzo IP che useremo a breve. Questa operazione serve per connettere la board ad Internet senza dover inserire nel codice i parametri della rete WiFi (SSID e password).

La board ci fornisce il suo indirizzo IP
La board ci fornisce il suo indirizzo IP

In questo caso l’indirizzo IP è 192.168.4.1.

A questo punto la Freenove è in modalità Access Point (con SSID AutoConnectAP) e dobbiamo connettere il nostro computer alla rete AutoConnectAP. Se andiamo nel menu delle reti del nostro computer, dovremmo vedere anche la rete AutoConnectAP nell’elenco delle reti wireless.

Lista delle reti WiFi disponibili
Lista delle reti WiFi disponibili

Connetti il computer alla rete AutoConnectAP. Quindi vai sul tuo browser e inserisci l’IP precedentemente fornito dalla Freenove: 192.168.4.1

Vedrai una schermata come questa:

La schermata del browser per scegliere la rete
La schermata del browser per scegliere la rete

Clicca il bottone ConfigureWiFi. Ti mostrerà le reti disponibili:

Lista delle reti disponibili
Lista delle reti disponibili

Scegli la SSID della tua rete:

Scegli la tua rete
Scegli la tua rete

Inserisci la password della tua rete e clicca il bottone save:

Inserisci la password
Inserisci la password

La risposta della board
La risposta della board

Il modulo Freenove conserva memorizzati i parametri di accesso anche se lo spegni, li ricorderà al riavvio e si ricollegherà automaticamente senza dover ripetere questa procedura. Solo se lo resetti rimuovendo il commento da questa riga

// wm.resetSettings();

perderà i parametri di connessione.

Nota Bene: il dispositivo può memorizzare solo una rete. Se successivamente lo colleghi a un’altra rete, dimenticherà le impostazioni della rete precedente.

Come creare un bot Telegram

Telegram è un’applicazione di messaggistica istantanea e VoIP che può essere installata sul tuo smartphone (Android e iPhone) o computer (PC, Mac e Linux). Telegram ti consente di creare bot con cui il nostro dispositivo può interagire.

Creiamo ora il nostro bot!

Se non hai già Telegram, installalo e poi cerca il bot botFather. Fai clic sull’elemento visualizzato. Apparirà la seguente schermata:

Prima schermata del bot botFather
Prima schermata del bot botFather

Digita il comando /start per leggere le istruzioni:

Le istruzioni per la creazione del bot
Le istruzioni per la creazione del bot

Ora digita il comando /newbot per creare il tuo bot. Dagli un nome e uno username:

La creazione del nuovo bot
La creazione del nuovo bot

Se il tuo bot è stato creato con successo, riceverai un messaggio con un link per accedere al bot e al token del bot.
Salva il token del bot perché ti servirà in seguito affinché la board possa interagire con il bot.

Ecco come appare la schermata in cui è scritto il token del bot:

Il token del bot
Il token del bot

Chiunque conosca il nome utente del tuo bot può interagire con esso. Per filtrare i messaggi in modo da ignorare quelli che non provengono dal tuo account Telegram, devi utilizzare il tuo ID utente Telegram. Pertanto, quando il tuo bot Telegram riceve un messaggio, il nostro Freenove saprà se proviene da noi (e quindi lo elaborerà) o da altri (e quindi lo ignorerà). Ma…..come troviamo questo ID?

Nel tuo account Telegram, cerca IDBot e avvia una conversazione con quel bot:

La prima schermata di IDBot
La prima schermata di IDBot

Quindi digita il comando /getid e lui ti risponderà col tuo ID:

Il risultato del comando /getid
Il risultato del comando /getid

A questo punto abbiamo creato il nostro bot e abbiamo tutti gli elementi per interfacciarlo con il nostro dispositivo: lo username, il token e lo userid.

Lo sketch

Analizziamo ora il codice che abbiamo caricato sulla board.

Inizialmente includiamo le librerie necessarie:

#include <Arduino.h>

#include "esp_camera.h"
#include <WiFiManager.h>
#include <WiFiClientSecure.h>

#include <UniversalTelegramBot.h>   // Universal Telegram Bot Library written by Brian Lough: https://github.com/witnessmenow/Universal-Arduino-Telegram-Bot
#include <ArduinoJson.h>


#include <EEPROM.h>                // EEPROM

Le usiamo per gestire la EEPROM, la fotocamera, la connessione WiFi e la connessione al bot di Telegram. La libreria ArduinoJson è una dipendenza della libreria UniversalTelegramBot.

// Initialize Telegram BOT
String BOTtoken = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";  // your Bot Token (Get from Botfather)

// Use @myidbot to find out the chat ID of an individual or a group
// Also note that you need to click "start" on a bot before it can
// message you
String CHAT_ID = "YYYYYYYYYYYY";

Qui dobbiamo inserire i parametri token e Telegram User ID che abbiamo ottenuto nel passaggio precedente quando abbiamo creato il bot di Telegram.

// Checks for new messages every 1 second.
int botRequestDelay = 1000;
unsigned long lastTimeBotRan;

WiFiClientSecure client;
UniversalTelegramBot bot(BOTtoken, client);

In questo pezzo definiamo le variabili che gestiscono la ricezione dei messaggi dal bot e definiamo il client WiFi e il bot di Telegram.

#define CAMERA_MODEL_WROVER_KIT // Has PSRAM

#include "camera_pins.h"

Qui viene definito il modello di fotocamera utilizzata e viene incluso il file che descrive i pin utilizzati dalla fotocamera.

int triggerPort = 33;             // GPIO33
int echoPort = 32;                // GPIO32
float distanceTrigger = 3.0;
int checkDistanceTime = 2000;      // milliseconds

Qui vengono definiti i GPIO utilizzati dal sensore a ultrasuoni (triggerPort e echoPort), la distanza entro la quale la board deve rilevare un movimento (distanceTrigger) e quindi scattare la foto e la variabile checkDistanceTime che definisce ogni quanto tempo il sensore ad ultrasuoni deve fare una misura. È raccomandabile non scendere sotto il valore impostato (2 secondi) per non provocare malfunzionamenti (la fotocamera impiega un certo tempo a scattare una foto e mandarla al bot).

Nota Bene: il sensore ad ultrasuoni HC-SR04 non è in grado di misurare distanze maggiori di 4 metri quindi ti consiglio di dare alla variabile distanceTrigger un valore non superiore a 3.

bool sendPhoto = false;
String alarmStatusEE = "";
int alarmStatusEE_address = 2;

Questa parte inizializza la variabile sendPhoto (che quando è messa a true provoca lo scatto della foto) e inizializza la variabile alarmStatusEE che conserva lo stato dell’allarme (se in automatico o in manuale) e l’indirizzo della EEPROM in cui verrà salvato per conservarlo in caso di interruzione della alimentazione.

La funzione handleNewMessages gestisce i messaggi scambiati col bot. In particolare:

if (text == "/help") {

    String welcome = "Welcome, " + from_name + ".\n";
    welcome += "Use the following commands to control your outputs:\n\n";
    welcome += "/photo takes a picture manually\n\n";
    welcome += "/aon to turn automatic mode ON\n\n";
    welcome += "/aoff to turn automatic mode OFF\n\n";
    welcome += "/aget gets the status of the alarm (automatic or manual mode)\n\n";

    bot.sendMessage(chat_id, welcome, "");
} 

fa apparire un messaggio di welcome con i possibili comandi e le loro spiegazioni quando viene mandato il comando /help.

else if (text == "/photo") {
         sendPhoto = true;
         bot.sendMessage(chat_id, "Sending a picture....");
    }   

Qui viene gestito il comando /photo che setta la variabile sendPhoto che quando è messa a true provoca lo scatto della foto e fa mandare un messaggio di notifica.

else if (text == "/aon") {
          alarmStatusEE = "1";
          EEPROM.write(alarmStatusEE_address, alarmStatusEE[0]);
          EEPROM.commit();     
          bot.sendMessage(chat_id, "Alarm set to ON (automatic mode).", "");    
    } 

Qui viene gestito il comando /aon che setta il dispositivo in modalità automatica e salva questo stato nella EEPROM. In questa modalità è sempre possibile scattare una foto manualmente dando il comando /photo.

else if (text == "/aoff") {
          alarmStatusEE = "0";
          EEPROM.write(alarmStatusEE_address, alarmStatusEE[0]);
          EEPROM.commit();   
          bot.sendMessage(chat_id, "Alarm set to OFF (manual mode).", "");     
    } 

Qui viene gestito il comando /aoff che setta il dispositivo in modalità manuale e salva questo stato nella EEPROM. In questa modalità non vengono scattate foto automaticamente ma solo in maniera manuale (sempre col comando /photo).

else if (text == "/aget") {
      alarmStatusEE = char(EEPROM.read(alarmStatusEE_address));
      if (alarmStatusEE == "1") {
        bot.sendMessage(chat_id, "Alarm set to ON (automatic mode).", "");
      } else if (alarmStatusEE == "0"){
        bot.sendMessage(chat_id, "Alarm set to OFF (manual mode).", ""); 
      }
      else {
        bot.sendMessage(chat_id, "Alarm set to unknown state!!", "");
      }
    }

In questa parte viene gestito il comando /aget che restituisce lo stato del dispositivo (automatico o manuale).

else {
       bot.sendMessage(chat_id, "Unrecognized message. Please retry...", "");
    }

Infine viene gestito il caso in cui il comando non venga riconosciuto perché diverso da quelli previsti.

La funzione sendPhotoTelegram provvede a scattare una foto e mandarla al bot:

const char* myDomain = "api.telegram.org";
String getAll = "";
String getBody = "";

In questa prima parte vengono definiti l’URL di Telegram verso il quale mandare la foto e due variabili di servizio.

camera_fb_t * fb = NULL;
  fb = esp_camera_fb_get();
  esp_camera_fb_return(fb); // dispose the buffered image
  fb = NULL; // reset to capture errors
  fb = esp_camera_fb_get(); // get fresh image

  if(!fb) {
    Serial.println("Camera capture failed");
    delay(1000);
    ESP.restart();
    return "Camera capture failed";
  }  else {
    Serial.println("Camera capture OK");
  }

Qui viene scattata la foto e gestito un eventuale malfunzionamento della fotocamera col riavvio della board.

if (client.connect(myDomain, 443)) {
    Serial.println("Connection successful");
    
    String head = "--Techrm\r\nContent-Disposition: form-data; name=\"chat_id\"; \r\n\r\n" + CHAT_ID + "\r\n--Techrm\r\nContent-Disposition: form-data; name=\"photo\"; filename=\"esp32-cam.jpg\"\r\nContent-Type: image/jpeg\r\n\r\n";
    String tail = "\r\n--Techrm--\r\n";

    uint16_t imageLen = fb->len;
    uint16_t extraLen = head.length() + tail.length();
    uint16_t totalLen = imageLen + extraLen;
  
    client.println("POST /bot"+BOTtoken+"/sendPhoto HTTP/1.1");
    client.println("Host: " + String(myDomain));
    client.println("Content-Length: " + String(totalLen));
    client.println("Content-Type: multipart/form-data; boundary=Techrm");
    client.println();
    client.print(head);
    
  
    uint8_t *fbBuf = fb->buf;
    size_t fbLen = fb->len;
    Serial.println(fbLen);

    for (size_t n=0;n<fbLen;n=n+1024) {
      if (n+1024<fbLen) {
        client.write(fbBuf, 1024);
        fbBuf += 1024;
      }
      else if (fbLen%1024>0) {
        size_t remainder = fbLen%1024;
        client.write(fbBuf, remainder);
      }
    }  
    
    client.print(tail);

    
    esp_camera_fb_return(fb);
    
    int waitTime = 10000;   // timeout 10 seconds
    long startTimer = millis();
    boolean state = false;
    
    while ((startTimer + waitTime) > millis()){
      Serial.print(".");
      delay(100);      
      while (client.available()) {
        char c = client.read();
        if (state==true) getBody += String(c);        
        if (c == '\n') {
          if (getAll.length()==0) state=true; 
          getAll = "";
        } 
        else if (c != '\r')
          getAll += String(c);
        startTimer = millis();
      }
      if (getBody.length()>0) break;
    }
    client.stop();
    Serial.println(getBody);
  }
  else {
    getBody="Connected to api.telegram.org failed.";
    Serial.println("Connected to api.telegram.org failed.");
  }
  return getBody;

Questa parte di codice è quella che effettivamente manda la foto al bot Telegram.

La funzione setup si occupa, come al solito, delle inizializzazioni delle periferiche:

pinMode( triggerPort, OUTPUT );     // sets the pin as OUTPUT for the ultrasonic sensor
pinMode( echoPort, INPUT );         // sets the pin as INPUT for the ultrasonic sensor

Vengono settati i pin triggerPort e echoPort che gestiscono il sensore ad ultrasuoni rispettivamente come OUTPUT e INPUT.

WiFi.mode(WIFI_STA); // explicitly set mode, esp defaults to STA+AP
  // it is a good practice to make sure your code sets wifi mode how you want it.

  Serial.begin(115200);

  EEPROM.begin(512);  //Initializes EEPROM

  //WiFiManager, Local intialization. Once its business is done, there is no need to keep it around
  WiFiManager wm;

Questa parte inizializza la porta seriale, la EEPROM e la gestione del WiFi.

bool res;
  // res = wm.autoConnect(); // auto generated AP name from chipid
  // res = wm.autoConnect("AutoConnectAP"); // anonymous ap
  res = wm.autoConnect("AutoConnectAP","password"); // password protected ap

  if(!res) {
      Serial.println("Failed to connect");
      // ESP.restart();
  } 
  else {
      //if you get here you have connected to the WiFi    
      Serial.println("Connected...yeey :)");
  }

Questa parte gestisce la connessione iniziale della board come Access Point.

client.setCACert(TELEGRAM_CERTIFICATE_ROOT); // Add root certificate for api.telegram.org

  config_init();   // configures the cam


  bot.sendMessage(CHAT_ID, "Hi! I'm online!", "");

  bot.sendMessage(CHAT_ID, "Ready to operate. Type /help to see the command list.", "");

Infine viene aggiunto il certificato per Telegram, viene configurata la fotocamera ed inviati i messaggi di benvenuto iniziali verso il bot.

Vediamo ora la funzione loop.

if (sendPhoto) {
    Serial.println("Preparing photo");
    sendPhotoTelegram(); 
    sendPhoto = false; 
 }

Questo primo pezzo di codice controlla lo stato della variabile sendPhoto; se è true allora viene scattata la foto e rimessa a false.

if (millis() > lastTimeBotRan + botRequestDelay)  {
    int numNewMessages = bot.getUpdates(bot.last_message_received + 1);

    while(numNewMessages) {
      Serial.println("got response");
      handleNewMessages(numNewMessages);
      numNewMessages = bot.getUpdates(bot.last_message_received + 1);
    }
    lastTimeBotRan = millis();
  }

Questa parte si occupa di gestire la tempistica di ricezione dei messaggi dal bot.

if(millis() - lastRefreshTime >= checkDistanceTime)
	{
		lastRefreshTime += checkDistanceTime;
    Serial.println(lastRefreshTime);

    digitalWrite(triggerPort, LOW);			// set to LOW trigger's output
    digitalWrite(triggerPort, HIGH);		// send a 10us pulse to the trigger
    delayMicroseconds(10);
    digitalWrite(triggerPort, LOW);
    
    long duration = pulseIn(echoPort, HIGH);
    
    long r = 3.4 * duration / 2;			// here we calculate the distance using duration

    float distance = r / 100.00;

    float distanceMeters = distance / 100;

    
    Serial.print("duration: ");
    Serial.print(duration);
    Serial.print(" , ");
    Serial.print("distance: ");
    

    if( (duration > 38000) or (duration == 0) ) Serial.println("out of reach");		// if duration in greather than 38ms, the obstacle is out of reach. If the duration equals 0 the sensor is in error
    else { 
      Serial.print(distance); Serial.print("cm, ");
      Serial.print(distance/100); Serial.println("m");

      if((distanceMeters <= distanceTrigger) and (alarmStatusEE == "1"))
      {
        bot.sendMessage(CHAT_ID, "Intruder detected!", "");
        sendPhoto = true;
      }
    }
	}  

Questa parte si occupa di fare le misurazioni di distanza ogni checkDistanceTime secondi e decidere se scattare la foto.

La foto sarà scattata solo se il dispositivo è settato su automatico (la variabile alarmStatusEE è settata a “1”) e la distanza appena misurata dell’oggetto in movimento (distanceMeters) è minore di quella settata all’inizio dello sketch (distanceTrigger).

Infine, la funzione config_init configura i pin della fotocamera, la inizializza ed imposta alcune caratteristiche dell’immagine da riprendere:

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.frame_size = FRAMESIZE_QVGA;
config.pixel_format = PIXFORMAT_JPEG; // for streaming
//config.pixel_format = PIXFORMAT_RGB565; // for face detection/recognition
config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
config.fb_location = CAMERA_FB_IN_PSRAM;
//config.jpeg_quality = 12;
//config.fb_count = 1;

//init with high specs to pre-allocate larger buffers
if(psramFound()){
config.frame_size = FRAMESIZE_UXGA;
config.jpeg_quality = 10;  //0-63 lower number means higher quality
config.fb_count = 1;
} else {
config.frame_size = FRAMESIZE_SVGA;
config.jpeg_quality = 12;  //0-63 lower number means higher quality
config.fb_count = 1;
}

// camera init
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x", err);
return;
} else {
Serial.println("Camera init OK");
}

sensor_t * s = esp_camera_sensor_get();
s->set_vflip(s, 0);        //1-Upside down, 0-No operation
s->set_hmirror(s, 0);      //1-Reverse left and right, 0-No operation
s->set_brightness(s, 1);   //up the blightness just a bit
s->set_saturation(s, -1);  //lower the saturation
s->set_framesize(s, FRAMESIZE_CIF);  // UXGA|SXGA|XGA|SVGA|VGA|CIF|QVGA|HQVGA|QQVGA

Ed ecco un video dimostrativo del sistema di videosorveglianza in funzione

Nel video sottostante è possibile vedere una piccola dimostrazione del funzionamento del nostro semplice sistema di videosorveglianza:

Breve demo del sistema di videosorveglianza controllato con Telegram

Nello schermo si possono vedere a sinistra la ripresa della scena fatta dalla webcam del mio computer portatile, a destra la schermata del bot di Telegram creato prima (si tratta di Telegram per desktop cioè la versione per computer).

Inizialmente la stanza è vuota e il dispositivo è impostato su manuale. Io, che faccio la parte dell’intruso, sono fuori scena e ho in mano il mio cellulare con cui interagisco con il Telegram installato su di esso e che è collegato allo stesso bot. Impartisco il comando /help in modo da far apparire la schermata di istruzioni, do il comando /photo per farmi mandare uno screenshot della stanza vuota, controllo lo stato di funzionamento (manuale o automatico) col comando /aget che mi dà conferma che la modalità di funzionamento è impostata su manuale.

Ad un certo punto do il comando /aon e il dispositivo entra in modalità automatica. Da questo momento è operativa la funzione di rilevazione del movimento tramite il sensore ad ultrasuoni. Come entro nella stanza il sensore avverte la mia presenza, la board inizia a scattare foto ogni 2 secondi (fintanto che mi trovo nel raggio di azione del sensore) e a mandarmele tramite Telegram. Al minuto 1:57 disattivo la modalità automatica col comando /aoff. Da questo momento in poi il sensore di movimento ad ultrasuoni è disattivato e si possono scattare foto solo manualmente col comando /photo.

Considerazioni finali

Come puoi vedere il progetto non è particolarmente complesso ed anche il suo funzionamento è abbastanza semplice, non potendo essere paragonato ad un apparecchio commerciale. Ma questo, come tutti i progetti presentati in questo blog, è un esperimento e, come tale, può essere perfezionato ed ampliato con nuove e più complesse funzionalità (il limite è solo la fantasia).

Il sensore ad ultrasuoni non è precisissimo in quanto talvolta rileva movimenti anche quando non ce ne sono dando luogo a falsi positivi (e quindi a foto poco rappresentative).

La ESP32, per poter spedire le foto, ha bisogno di una rete WiFi stabile e veloce. In caso contrario la board rischia di bloccarsi sull’invio della immagine. Questo è uno dei motivi per cui è bene che l’intervallo tra una misurazione e l’altra da parte del sensore ad ultrasuoni non sia inferiore ai 2 secondi.

Newsletter

Se vuoi essere aggiornato sui nuovi articoli, iscriviti alla newsletter. Prima dell’iscrizione alla newsletter leggi la pagina Privacy Policy (UE)

Se ti vuoi disiscrivere dalla newsletter clicca sul link che troverai nella mail della newsletter.

Inserisci il tuo nome
Inserisci la tua email
0 0 votes
Valutazione articolo
guest
0 Commenti
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
Torna in alto