Guida alla board ESP32 con Microcamera: ESP32-CAM

Realizziamo una microcamera wireless con tanto di controllo PAN/TILT, utilizzando il modulo ESP32 e una telecamera da 2Mpx.

L’ESP32-CAM Development Board è una scheda elettronica basata su un SoC (System On Chip) ESP32S, equipaggiata con una videocamera da 2MPixel (OV2640) e uno slot per una memoria miniSD fino a 4GByte.

Sulla scheda è presente un LED ad alta luminosità che può essere impiegato come flash o come illuminatore per la scena da riprendere e alcune linee GPIO per interfacciarsi con il mondo esterno.

L’elettronica permette di impostare diversi frame-rate, ma per ottenere dei risultati accettabili bisogna arrivare, come vedremo dettagliatamente nel corso dell’articolo, ad un compromesso.

Con questo modulo (Fig. 1) realizzeremo un’applicazione sfruttando le librerie che la Espressif ha da poco rilasciato per la programmazione con l’IDE di Arduino; prima occorreva il sistema di sviluppo (toolchain) dedicato.

Fig. 1 La scheda ESP32-CAM completa di telecamera

Schema elettrico ESP32-CAM

Elenco Componenti:

R1: 0 ohm
R2, R7: -
R3, R4: 1 kohm
R5, R6: 10 kohm
R10, R11: 47 kohm
R12: 10 kohm
R13, R15: 1 kohm
R14, R19: 10 kohm
R8, R9: 47 kohm
R16, R17, R18: 4,7 kohm
C1: 100 nF ceramico
C2: 10 µF ceramico
C3: 100 nF ceramico
C4: 100 µF tantalio
C5: 10 µF ceramico
C6: 1 µF ceramico
C7, C9, C12, C14: 100 nF ceramico
C8, C10, C11: 10 µF ceramico
C13: 15 pF ceramico
K1: Pulsante NO
LED_FLASH: LED bianco
LED1: LED verde
Q1: S8050
Q2: P-MOS
SD1: Slot micro-SD-Card
CAM1: Connettore 24 vie per camera
M1: ESP32S
U1: XC6206-2.8V
U2: AMS1117-33
U3: XC6206-1.2V
U5: PSRAM
- Camera OV2640
- Strip maschio 8 vie (2 pz.)
- Circuito stampato

Schema elettrico SCHEDA BASE

Abbiamo ricavato e pubblichiamo lo schema elettrico del modulo, che descriviamo per comprenderne il funzionamento. Il modulo ESP32-CAM non è dotato di porta USB per ragioni di costo e dimensioni, quindi per poter caricare il nostro Sketch sul modulo dovremo dotarci di un convertitore USB/TTL che fornisca l’alimentazione a 5V e permetta di impostare i livelli logici di RX e TX a 3,3 V.

Ricordiamo che il modulo SOC ESP32 non è 5V tolerant, quindi i segnali da applicare ai pin GPIO devono essere tassativamente tutti nel limite dei 3,3V.

Nello schema sono presenti tre regolatori lineari: un AMS1117-3.3 che si occupa di convertire i 5V provenienti dall’alimentazione esterna ai 3,3V necessari per il modulo ESP32S; a valle è presente un MOSFET comandato dal segnale CAM_POWER il quale controlla (tramite la libreria Espressif) l’applicazione dei 3,3V ad altri due regolatori, uno da 2,8V ed uno da 1,2V (usati entrambi per alimentare la videocamera). Notiamo inoltre la presenza di un chip PSRAM impiegato per poter utilizzare il modulo con delle risoluzioni più elevate.

È presente anche uno slot per la miniSD che può essere utilizzato per memorizzare immagini acquisite dalla camera. Per il funzionamento della microSD servono diversi segnali, alcuni dei quali sono esposti sul connettore del modulo ESP32-CAM, ma se impiegati per la card non si possono utilizzare per altro.

Quanto ai LED, il primo (indicato come LED) è collegato al pin GPIO33 e si trova sul lato opposto rispetto alla camera; impegna un pin che non è neppure esposto esternamente.

L’altro LED è posizionato frontalmente ed è ad alta luminosità (LED_FLASH) gestito dal GPIO4 e controllato tramite un transistore NPN (Q1). Il GPIO33 tuttavia è condiviso (HS2_DATA1) con la scheda microSD e quindi lampeggerà mentre la SD sarà in attività. È possibile utilizzare questo LED per illuminare la scena e lo useremo nel nostro progetto.

A bordo del modulo ESP32-CAM è presente un pulsante di reset del ESP32S collegato a pin E32_RST. Purtroppo questo pin non è stato reso accessibile dall’esterno.

I due pin U0TXD (TX) e U0RXD (RX) che ci permettono di caricare il nostro codice sul modulo ESP32-CAM sono, invece, esposti sul connettore esterno, sul quale è presente anche una seconda seriale U2RXD (RX) utilizzabile nel caso in cui serva ricevere dati tramite seriale. La piedinatura completa del modulo è illustrata nella Fig. 2.

Fig. 2 Pin-out del modulo ESP32-CAM

 

A bordo si trova un’antenna WiFi integrata nel PCB, ma c’è la possibilità di collegare un’antenna esterna tramite un micro connettore IPEX (U.FL) che si trova sul lato inferiore del PCB, in prossimità dell’antenna integrata (Fig. 3).

Fig. 3 Ponticello da fare

 

Per attivare l’antenna esterna è necessario spostare un ponticello realizzato con un resistore SMD da 0 Ohm che deve essere spostato dal collegamento con l’antenna integrata a quello con il connettore IPEX.

Questa operazione (viste le dimensioni del resistore SMD e delle piazzole) è molto delicata, quindi se non avete mano ferma, una lente di ingrandimento ed un buon saldatore con punta sottile, evitatela.

Per l’alimentazione si applica una tensione di 5V all’ingresso 5V, che fa capo al regolatore AMS1117. Notate che il pin 4 (P_OUT) è marcato come 3,3V/5V, infatti nello schema elettrico potete notare due resistenze da 0 ohm collegate tra il pin 4 e la tensione 5V e 3,3V.

Naturalmente sarà possibile collegare solo un resistore alla volta per definire quale sia la tensione presente sul pin, pena un cortocircuito tra le due tensioni e la distruzione del SoC.

Questa è una modifica che difficilmente dovrete fare, ma è bene comprendere lo schema. Normalmente il resistore presente è R1, quindi sul P_OUT è presente la tensione a valle del regolatore AMS1117, ossia 3,3V.
Il segnale di reset della microcamera è derivato da una rete RC composta da R16 e R12 e quindi la camera si resetta automaticamente nella fase di applicazione della tensione di alimentazione.

Potrebbe succedere che la porta del nostro PC non sia in grado di alimentare in modo corretto il modulo stesso e quindi una volta caricato lo sketch è preferibile rimuovere il collegamento con il PC e alimentare il modulo tramite un alimentatore che possa erogare 5V con una corrente massima di almeno 1A (un buon caricatore USB per mobile è più che sufficiente) oppure tramite un PowerBank.

Quello che può accadere alimentando il modulo dalla porta USB è che, a causa della poca corrente erogabile, presenti un comportamento inaspettato con ripetuti riavvii, blocchi o malfunzionamenti.

Il progetto

Ci proponiamo di realizzare con il modulo ESP32-CAM una piccolissima webcam che può essere utilizzata per il monitoraggio remoto, eventualmente mossa da un sistema PAN-TILT.

L’immagine può essere vista in tempo reale in un browser web e quindi anche da un dispositivo mobile; tramite il mouse oppure in modo touch è possibile orientare la webcam.

È anche possibile integrare la camera in progetti di domotica come Home Assistant https://www.home-assistant.io.

Naturalmente si possono realizzare delle webcam molto più performanti tramite Raspberry Pi Zero W, ma il “lampone” richiede dei tempi di boot sicuramente maggiori, soffre di corruzione del file-system (nel caso di improvvisa interruzione ripetuta dell’alimentazione) e sicuramente il costo di un modulo ESP32-CAM non è paragonabile con quello della Raspberry Pi Zero.

Il modulo ESP32-CAM costa poco, non ha un file-system su SD che può corrompersi, ha un tempo di avvio molto basso: insomma, è il candidato perfetto per realizzare il nostro progetto.

Inoltre, ha ulteriori funzionalità che qui non abbiamo implementato, come il riconoscimento facciale (offline), la possibilità di riconoscere QR-Code.

Per utilizzare in modo agevole il modulo abbiamo realizzato una scheda base che può essere utilizzata per programmare e alimentare l’ESP32-CAM.

Come mostra lo schema elettrico, sulla nostra scheda abbiamo predisposto i due connettori femmina per innestare il modulo, il connettore per il collegamento del programmatore tramite USB, un jumper per settare la modalità programmazione, dei condensatori di disaccoppiamento e due connettori per comandare i due servomotori per il controllo PAN e TILT della camera.

Abbiamo previsto anche un pulsante per il reset della configurazione WiFi che non useremo in questo progetto ma che riguarda la modalità di configurazione del WiFi tramite SmartConfig.

Il Modulo ESP32-CAM nell’IDE Arduino

Per programmare l’ESP32-CAM occorre installare il core dei moduli SoC ESP32; allo scopo consigliamo di utilizzare una versione recente dell’IDE di Arduino: diciamo almeno una 1.8.x.

Apriamo quindi il menu File e clicchiamo su Impostazioni (Fig. 4) poi individuiamo la casella di testo “URL aggiuntive per il gestore di schede” e clicchiamo sul pulsante a destra per aprire una finestra (Fig. 5) nella quale inserire l’url di definizione dei core SoC fornito da Espressif https://dl.espressif.com/dl/package_esp32_index.json ed inseriamolo (aggiungendolo ad altri eventualmente presenti) nella casella di testo e salviamo con OK.

Riavviamo quindi L’IDE di Arduino e poi dal menu Strumenti selezioniamo la voce Gestore schede.

 

Fig. 4 Finestra di dialogo Impostazioni

 

Fig. 5 Inserimento dell’URL aggiuntiva per caricare il modulo ESP32-CAM

 

Digitiamo ESP32 nella casella di testo e dopo una breve attesa dovrebbe apparire la voce visibile in Fig. 6; selezioniamo la versione più recente del pacchetto (nel nostro caso 1.0.3) e clicchiamo su Installa.

Fig. 6 Caricamento della ESP32-CAM

 

Una barra di progressione apparirà per informarci sull’avanzare dell’installazione, al termine della quale potremo riavviare L’IDE e alla prossima apertura troveremo una nuova serie di schede basate sul chip SoC ESP32 installate sul nostro ambiente di sviluppo (Fig. 7).

Fig. 7 Scelta della scheda

 

Il modulo che dobbiamo selezionare per il progetto corrente dovrà essere “ESP32 Wrover Module”, che adesso sarà visualizzato nel sotto-menu.

Per il progetto di questo articolo avremo necessità di aggiungere le seguenti librerie aggiuntive:
ArduinoWebsockets:
https://github.com/gilmaimon/ArduinoWebsockets
ESPAsyncWebServer:
https://github.com/me-no-dev/ESPAsyncWebServer
ArduinoJson:
https://github.com/bblanchon/ArduinoJson
AsyncTCP:
https://github.com/me-no-dev/AsyncTCP

Nel caso le abbiate già presenti nel vostro ambiente, assicuratevi di aggiornarle all’ultima versione. Per inserire le librerie, utilizziamo lo strumento Gestione Librerie dell’IDE per ArduinoWebsockets (Fig. 8) e ArduinoJson (Fig. 9) mentre per ESPAsyncWebServer (non essendo tuttora disponibile nel repository di Arduino) dovremo inserirla a mano nella cartella Libraries di Arduino.

 

 

Fig. 8 Gestore librerie

 

Fig. 9 Installazione ArduinoJson

 

Dovremo quindi scaricare il file zippato ESPAsyncWebServer-master.zip dal rispettivo repository GitHub, scompattarle la cartella, rimuovere il suffisso –master dal nome della cartella e spostare la stessa dentro la cartella che solitamente si trova in: C:\Program Files(x86)\Arduino\libraries a questo punto siamo pronti per testare il codice.

Vi anticipiamo che in questo articolo non useremo lo schetch CameraWebServer.ino di esempio che solitamente viene usato per presentare il funzionamento del modulo ESP32-CAM che si può trovare normalmente nel percorso C:\Users\NomeUtente\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.3\libraries\ESP32\examples\Camera\CameraWebServer.

Lo sketch standard è molto generico, contiene del codice per gestire sia la camera ov2640 che ov3660 in diverse risoluzioni e modalità di funzionamento, permettendo anche di sfruttare il riconoscimento facciale. Però è carente da altri punti di vista: per esempio non permette di gestire l’accensione del LED ad alta luminosità dall’interfaccia web integrata e presenta qualche instabilità del funzionamento.

Per brevità di spazio non possiamo descrivere anche questo sketch, che vi invitiamo comunque a installare per testare altre funzionalità interessanti del modulo ESP32-CAM; qui utilizzeremo una versione realizzata da noi anche nell’interfaccia, che utilizza sempre la libreria base di Espressif esp_camera.h. ma per il resto il funzionamento è completamente diverso.

Non riporteremo lo sketch completo ma solo le parti salienti: nel Listato 1 vediamo la parte di importazione delle librerie.

 Listato 1

#include <ESPAsyncWebServer.h> 
#include <ArduinoWebsockets.h> 
#include <ArduinoJson.h>
#include <WiFi.h>
#include <ESPmDNS.h>
#include “esp_camera.h”

#include “soc/soc.h” 
#include “soc/rtc_cntl_reg.h”

#include “index.html.h” 
#include “error404.html.h”

Il cuore della nostra applicazione è chiaramente la libreria esp_camera.h resa disponibile da Espressif che espone il funzionamento della scheda ESP32-CAM.

Le altre librerie degne di nota sono ESPAsyncWebServer.h un webserver che gestisce le chiamate asincrone, poi a seguire i ArduinoWebsockets per utilizzare i WebSocket, la Libreria WiFi.h per la gestione del Wi-Fi, ArduinoJson.h per interpretare i comandi provenienti dalla pagina Web. Mentre la libreria ESPmDNS.h permette di implementare il protocollo mDNS (ZeroConfig); in breve, sarà possibile assegnare al dispositivo un nome che potrà essere utilizzato in alternativa all’indirizzo IP assegnato dal Router tramite servizio DHCP. Vedremo poi come configurare e utilizzare questa caratteristica.

Le ultime due inclusioni index.html.h e error404.html.h in effetti non sono delle librerie ma dei file Html che devono trovarsi nella stessa cartella dello schetch e che sono la versione compressa (Gzipped) e codificata in binario della interfaccia web che abbiamo realizzato per il progetto.

Nel Listato 2 vediamo la definizione della connessione WiFi a cui il dispositivo ESP32-CAM dovrà collegarsi, quindi sostituite il valore di “Nome_Rete” e “Password_Rete” con quelle della vostra rete WiFi.

Listato 2

const char* ssid = “Nome_Rete”;
const char* password = “Password_Rete”;
const char* mDNS_NAME = “esp32-cam”;
#define LED 4
#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
camera_fb_t * fb = NULL; 
using namespace websockets;
WebsocketsServer WSserver;
AsyncWebServer webserver(80);
int n_attempts;

 

Poi abbiamo il nome (“esp32-cam”) con cui vogliamo identificare il dispositivo tramite servizio mDNS.

A seguire viene elencata una serie di parametri legati ai pin GPIO che definiscono la configurazione della scheda e dei collegamenti SoC ESP32-S con la videocamera e miniSD. Questi parametri non devono essere alterati altrimenti lo sketch non funzionerà.

Nelle ultime righe vediamo la definizione degli oggetti Frame Buffer della camera camera_fb, WebSocket e del server web Asincrono, notiamo anche la definizione della porta canonica (80) del server web.

Nel Listato 3 è possibile vedere la sezione di setup del codice Arduino. La prima istruzione disabilita il Brown_Out, in pratica rimuove il controllo sulla sotto-alimentazione del chip SoC che potrebbe condurre al reset lo stesso se la tensione di alimentazione accidentalmente scendesse sotto un certo livello.

Listato 3

void setup() {
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
Serial.begin(115200);
pinMode(LED, OUTPUT);
ledcSetup(2, 50, 16); 
ledcAttachPin(2, 2); 
ledcSetup(4, 50, 16);
ledcAttachPin(12, 4);
camera_config_t config;
config.ledc_channel = LEDC_CHANNEL_0;

esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf(“Camera init failed with error 0x%x”, err);
delay(500);
ESP.restart(); 
}
sensor_t * s = esp_camera_sensor_get();
s->set_framesize(s, FRAMESIZE_QVGA);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(“.”);
n_attempts++;
if (n_attempts > 5) {
Serial.println(“Restarting”);
ESP.restart();
} 
}
Serial.println(“”);
Serial.print(“Connected to “);
Serial.print(“IP address: “);
Serial.println(WiFi.localIP());
if (!MDNS.begin(“esp32”)) {
Serial.println(“Error setting up MDNS responder!”);
while(1) {
delay(1000);
}
}
Serial.println(“mDNS responder started”);
webserver.on(“/”, HTTP_GET, [](AsyncWebServerRequest * request) {
AsyncWebServerResponse *response = request->beginResponse_P(200, “text/html”, index_html_gz, sizeof(index_html_gz));
response->addHeader(“Content-Encoding”, “gzip”);
request->send(response);
});
webserver.begin(); 
WSserver.listen(82);
MDNS.addService(“http”, “tcp”, 80);
}

 

Questo per prevenire reset accidentali nel caso in cui la tensione di alimentazione subisse anche per poco tempo delle piccole variazioni. A seguire abbiamo l’inizializzazione della porta seriale, la configurazione come del GPIO del LED ad alta intensità, la configurazione di due porte GPIO come pseudo PWM per il comando dei due servocontrolli PAN e TILT.

Poi abbiamo la definizione della variabile interna di configurazione della camera che dovrà essere valorizzata assegnando i rispettivi valori assegnati ai parametri definiti precedentemente e di cui abbiamo omesso la trascrizione per esigenze di spazio. Viene poi verificato se l’inizializzazione della camera nel caso in cui questo non succeda, viene inviato un messaggio di debug sulla seriale e vien resettato dopo 500 ms il chip per re inizializzarlo.

Se tutto è andato a buon fine, viene settato il Frame Size della camera. Poi abbiamo l’inizializzazione con i parametri di accesso della connessione Wi-Fi.

Qui abbiamo un Loop ogni 500 ms che viene terminato quando la connessione è stata completata con successo oppure dopo 5 tentativi viene eseguito il Restart del SoC. Se la connessione è terminata con successo viene inviata sulla porta seriale un messaggio indicando anche L’indirizzo IP acquisito. Troviamo poi l’inizializzazione del servizio mDNS.

Subito dopo viene inizializzato il server web asincrono che a fronte di una richiesta della Homepage (“/”) invia il contenuto del file memorizzato in binario nella variabile “index_html_gz” specificando che si tratta di un contenuto Gzipped. Al termine della procedura di setup troviamo l’inizializzazione del Webserver Asincrono e del WebSocket sulla porta 82.

L’ultimo blocco di codice Specifica il tipo di servizio, il protocollo e la porta per la risoluzione del nome del dispositivo tramite mDNS.

Nel Listato 4 vediamo la procedura contenuta nel Loop del codice di Arduino. Seguendo l’ordine del listato abbiamo la definizione del Client WebSocket, la definizione della procedura handle_message che si occupa di interpretare i comandi ricevuti dal browser tramite il canale WebSocket.

Listato 4

void loop() { 
auto client = WSserver.accept();
client.onMessage(handle_message);
while (client.available()) {
client.poll();
fb = esp_camera_fb_get();
client.sendBinary((const char *)fb->buf, fb->len);
esp_camera_fb_return(fb);
fb = NULL;
} 
}

E poi il loop vero e proprio che fintanto che il client è disponibile esegue il ciclo acquisendo il frame dalla camera tramite la funzione esp_camera_fb_get(); ed inviandoli (in formato binario) sempre tramite il canale WebSocket (che ricordiamo essere bidirezionale) al browser Web che si occuperà di aggiornare l’immagine della camera. Tutto questo con poche righe di codice.

Nel Listato 5 abbiamo la procedura che si occupa di interpretare i comandi ricevuti tramite il canale WebSocket provenienti dalla interfaccia del browser web e che abbiamo “agganciato” nella precedente sezione di Loop.

Listato 5

void handle_message(WebsocketsMessage msg) {
String PinName;
int PinValue;
int panValue ;
int tiltValue;
String message= msg.data();
StaticJsonDocument<200> doc; 
DeserializationError error = deserializeJson(doc, message);
if (error) {
Serial.println(“deserialization Failed”);
return;
}
Serial.println(“deserialization OK”);
if(message.startsWith(“{xy:”)){
Serial.println(“XY”);
panValue = doc[“xy”][0];
tiltValue = doc[“xy”][1]; 
Serial.print(“pan:”);
Serial.print(panValue);
Serial.print(“tilt:”);
Serial.print(tiltValue);
panValue = map(panValue, -90, 90, 0, 180); // 0-180
tiltValue = map(tiltValue, -90, 90, 180, 0); // 0-180 reversed
ledcAnalogWrite(2, panValue); 
ledcAnalogWrite(4, tiltValue); 
}
if(message.startsWith(“{pin:”)){
Serial.println(“PIN”);
const char* pin = doc[“pin”];
PinValue = doc[“value”];
Serial.println(“PinName:”);
Serial.println(PinName);
Serial.println(“PinValue:”);
Serial.println(PinValue);
digitalWrite(LED, PinValue); 
}
}

 

In particolare abbiamo l’interpretazione dei comandi PAN e TILT che servono ad orientare la posizione della camera e il controllo della accensione del LED ad alta luminosità che possiamo accendere per illuminare la scena da riprendere se non vi è sufficiente illuminazione ambientale.

Nell’interfaccia web abbiamo predisposto altri controlli web oltre al PAN, TILT e accensione del LED; se volete estendere le funzionalità dovete modificare la funzione handle_message.

Notate che il formato dei dati ricevuti tramite il canale WebSocket è JSON; se non lo conoscete, potete approfondire all’indirizzo web https://arduinojson.org/. Nel Listato 6 trovate il dettaglio della funzione ledcAnalogWrite () che permette di implementare una sorta di PWM sul modulo ESP32-CAM; il controllo dei servomotori avviene tramite un segnale PWM.

Listato 6

void ledcAnalogWrite(uint8_t channel, uint32_t value, uint32_t valueMax = 180) {
uint32_t duty = (8191 / valueMax) * min(value, valueMax);
ledcWrite(channel, duty);
}

Carichiamo lo sketch sul modulo

Come primo passo compiliamo il codice: clicchiamo su Strumenti nel menu e settiamo le varie voci evidenziate come in Fig. 10 e la porta seriale assegnata.

Fig. 10 Impostazioni per compilare il codice

 

Chiaramente dovremo poi mantenere le stesse impostazioni quando avvieremo il processo di caricamento.

Terminata la configurazione cliccate sul pulsante con il segno di spunta. Se il processo di compilazione si è concluso con successo, possiamo passare al caricamento dello sketch.

Per caricare lo sketch sul modulo, dobbiamo per prima cosa collegare (prestando attenzione alla piedinatura e alle impostazioni dei livelli di tensione) il convertitore USB/seriale alla porta USB del nostro PC e al connettore che abbiamo predisposto sulla piccola motherboard; quindi occorre settare in modalità programmazione il modulo chiudendo con un ponticello il connettore SV5, che fa capo al GPIO0.

Il modulo convertitore USB/seriale, che proponiamo nella Fig. 11, ha una pin-out che si adatta al connettore della nostra scheda, ma non è scontato che sia sempre così; quindi se avete un convertitore diverso prestate attenzione.

Fig. 11 Il modulo convertitore

 

Poi dobbiamo cliccare sul pulsante di upload dell’IDE di Arduino e dopo qualche secondo pigiare il pulsante di reset che si trova sotto il modulo.

Se tutto procede in modo corretto vedremo apparire nella parte inferiore della IDE dei messaggi di log che ci informano dello stato del caricamento. Terminato il quale saremo invitati a cliccare nuovamente sul pulsante di reset, dobbiamo però prima rimuovere il ponticello sul GPIO0 che setta la modalità d programmazione.

Rimosso il ponticello, apriamo il monitor seriale e pigiamo il pulsante di reset: dopo qualche secondo dovrebbe apparire un messaggio di log, come quello visibile nella Fig. 12.

Fig. 12 Messaggio di log

 

L’ultima riga del messaggio ci informa che possiamo aprire il browser utilizzando l’indirizzo IP (naturalmente il vostro indirizzo IP sarà diverso da quello indicato nell’esempio) oppure impiegare un indirizzo letterale molto più semplice e non soggetto a modifiche dovute ad eventuali variazioni di assegnazione dell’IP da parte del DHCP del Router.

L’interfaccia web della Camera ESP32-CAM

Una volta che il modulo ha terminato la procedura di avvio, potremo quindi accedere alla pagina web inserendo sul browser l’url (ad esempio http://192.168.1.47 ) e ci apparirà istantaneamente la scena inquadrata dalla fotocamera (Fig. 13).

Fig. 13 Interfaccia web e schermata di Serial Monitor

 

Oppure, grazie al server mDNS potremmo usare http://esp32-cam.local. Se utilizzate un router Fritzbox è probabile che non sia possibile risolvere il nome del dispositivo con suffisso local, in tal caso dovreste potrete raggiungere il dispositivo con il seguente url: http://esp32-cam.

Se clicchiamo con il mouse sulla superficie della immagine ripresa, ci apparirà il cursore di controllo di TILT e PAN che è possibile trascinare sulla superficie per muovere l’inquadratura della camera. Se rilasciamo il cursore, dopo qualche secondo il controllo TILT e PAN scomparirà per lasciare spazio alla inquadratura, e riapparirà nell’ultima posizione lasciata se clicchiamo nuovamente sulla superficie. Nella zona inferiore della camera abbiamo un piccolo pannello di controllo.

Tuttavia l’unico controllo che attualmente è funzionante è quello di controllo del LED di bordo. Abbiamo lasciato gli altri per darvi la possibilità di sperimentare in modo semplice con la vostra scheda ESP32-CAM. Nel seguito dell’articolo vi spiegheremo anche come modificare l’interfaccia web per esempio per lasciare il solo controllo del LED.

In Fig. 13 abbiamo affiancato a destra dell’interfaccia Web la finestra di debug di Arduino per vedere l’avvicendarsi dei comandi che vengono inviati mentre controlliamo la posizione del PAN e TILT sulla immagine della camera oppure quando accendiamo e spegniamo il LED di bordo.

Potrete provare ad usare anche gli altri controlli, vedrete che raggiungeranno il modulo ESP32-CAM, verranno “parsate” in modo corretto dal parser JSON, ma non sortiranno alcun effetto. Per gestire questi ulteriori comandi dovrete intervenire nella procedura handle_message dello sketch Arduino.

Nel bordo superiore sinistro della camera è presente un pulsante a sandwich in funzionamento toggle che permette di nascondere o visualizzare il pannello di controllo inferiore che all’apertura della pagina web che risulta di default nascosto. Va fatta una precisazione per quanto riguarda la fruibilità della interfaccia web.

Non è possibile usufruire della stessa da più di un browser web contemporaneamente. L’ESP32 non è così potente da poter gestire client concorrenti, ma il lavoro che fa questo piccolo SoC è veramente strabiliante.

Modificare il file dell’interfaccia web

La pagina index.html che implementa l’interfaccia web della nostra camera è troppo grande (circa 500 righe di codice) per essere riportato integralmente in queste pagine; riporteremo nel Listato 7 solo la parte riguardante il pannello di controllo.

Se vorrete cimentarvi nella modifica è consigliabile aprire lo stesso non con semplice editor di testo ma è preferibile un editor HTML che vi assista nella fase di editing del codice e vi evidenzi eventuali errori.

Il Listato 7 riporta la parte della interfaccia web della camera che si trova in basso e che rappresenta il pannello di controllo.

Listato 7

<nav id=”menu”>
<div class=”input-group” id=”flash-group”>
<label for=”flash”>On Board LED</label>
<div class=”switch”>
<input id=”flash” type=”checkbox” class=”default-action” onclick=”sentCheckbox(this.id,this.value);”>
<label class=”slider” for=”flash”></label>
</div>
</div>
<div class=”input-group” id=”vflip-group”>
<label for=”checkbox1”>checkbox</label>
<div class=”switch”>
<input id=”checkbox1” type=”checkbox” class=”default-action” oninput=”sentCheckbox(this.id,this.value);”>
<label class=”slider” for=”checkbox1”></label>
</div>
</div>
<div class=”input-group” id=”saturation-group”>
<label for=”saturation”>Range</label>
<div class=”range-min”>0</div>
<input type=”range” id=”range1” min=”0” max=”100” value=”0” class=”default-action” oninput=”sentRange(this.id,this.value);”> 
<div class=”range-max”>100</div>
</div>
<div class=”input-group” id=”wb_mode-group”>
<label for=”wb_mode”>Select</label>
<select id=”wb_mode” class=”default-action” oninput=”sentSelect(this.id,this.value);”>
<option value=”0” selected=”selected”>Auto</option>
<option value=”1”>Option1</option>
<option value=”2”>Option2</option>
</select>
</div>
<section id=”buttons”>
<button id=”btn1” onclick=”setBotton(this.id);”>Botton1</button>
<button id=”btn2” onclick=”setBotton(this.id);”>Botton2</button> 
</section> 
</nav>

 

Nel listato abbiamo riportato diversi controlli. Ma se volete lasciare solo quello relativo al LED (blocco in grassetto) niente di più semplice.

Rimuovete la parte di codice HTML relativa ai controlli che non desiderate e poi seguite la procedura che riportiamo nel prossimo paragrafo per rigenerare dal file index.html il file index.html.h da includere nello sketch Arduino.

Il SoC ESP32 per poter renderizzare una pagina Web ha necessità che la stessa sia inserita nel codice di Arduino come un array di Byte.

Quindi quello che bisognerebbe fare partendo dal file HTML della pagina che vogliamo visualizzare è prima di tutto sottoporre il file ad un processo di compressione tramite Gzip, poi convertire il risultato della compressione in un array di Byte.

Per agevolarvi nella procedura, abbiamo realizzato una piccola utility in C# che permette con pochi clic di ottenere il risultato desiderato. Troverete l’eseguibile (FileConverter.exe) nella stessa cartella del codice Arduino insieme con il file index.html.

Aprite l’eseguibile e, nella finestra di dialogo che appare, cliccate sul pulsante Gzip, selezionate il file da convertire. Questo primo passo genererà un file index.html.gz. Cliccate sul pulsante “Convert to ByteArray”, selezionate il file Gzip appena creato ed otterrete nella stessa cartella il file index.html.h che lo sketch del nostro progetto si aspetta di trovare nella propria cartella.

Come potete verificare dalla Fig. 14, il file index.html.h in effetti è stato convertito in un array di Byte della lunghezza (in questo caso) di 3.638 elementi. Per agevolare chi voglia modificare l’interfaccia Web della camera, abbiamo predisposto due server web realizzati in NodeJS. Il primo server web è quello che si occupa di “inviare” la pagina index.html verso il browser.

 

Fig. 14 File convertito in un array

 

Il secondo server è un server Winsock che si occupa di ricevere i comandi dalla pagina Web.

Non abbiamo previsto l’invio di immagini verso la pagina web per simulare la camera, ma riteniamo che sia sufficiente l’ambiente che abbiamo predisposto per potersi cimentare sulla modifica della pagina web della camera e verificare che non ci siano errori Javascript prima di trasformare il file html per caricarlo sul modulo ESP32-CAM.

Nella cartella del progetto troverete una cartella NodeJS entro la quale sono presenti due sottocartelle: “server-html” e “server-winsock” all’interno della cartella “server-html” troverete una ulteriore cartella “www” all’interno della quale è presente il file index.html che potrete modificare a vostro piacimento e che poi una volta testato potrà essere convertito come indicato nei paragrafi precedenti. Il codice dei rispettivi server si trova nei file “server.js” delle rispettive cartelle.

Se andate a curiosare troverete che i due server sono realizzati con una decina di righe di codice… Magia di NodeJS.

Per mandare in esecuzione i due server sarà sufficiente aprire le rispettive cartelle e cliccare sui due file “run.bat”, l’esecuzione dei quali aprirà due finestre shell-DOS. Se le due finestre DOS non riportano errori ma si presentano come in Fig. 15.

 

Fig. 15 Finestre DOS

 

Potrete aprire il browser all’indirizzo 127.0.0.1 (localhost) per visualizzare l’interfaccia web della Webcam. Le cartelle dei due server contengono già le librerie NodeJS che servono alla loro implementazione. Se non avete mai installato NodeJS sul vostro PC dovrete installarlo. La procedura è molto semplice. Potrete trovare un interessante tutorial alla pagina seguente: https://www.mrwebmaster.it/javascript/introduzione-node-js_12432.html.

Come funziona

Sul codice che abbiamo installato sul modulo ESP32-CAM coesistono sia un server Web che è in grado di fornire ad un browser una pagina HTML, sia un server Winsock che si occupa di ricevere dei comandi dalla pagina Web della camera che è stata aperta sul browser, sia inviare dal modulo ESP32 verso il browser web il flusso binario relativo alle immagini che vanno a comporre il video in tempo reale della ripresa. Tutto questo senza dover ricaricare il contenuto della pagina web.

Ricordiamo infatti che la comunicazione Websocket è bidirezionale. Nel codice Javascript abbiamo inserito una funzione che verifica lo stato della connessione Winsock e nel caso questa sia per qualche motivo interrotta la ripristina mantenendo nel tempo la funzionalità di visualizzazione e controllo della pagina Web.

Come potrete vedere analizzando il codice HTML della pagina index.html non sono presenti immagini e non sono stati utilizzate librerie particolari ma puro Javascript e del CSS per assegnare l’aspetto grafico agli elementi della pagina.

La maggior parte del codice HTML presente nella pagina index.htm è relativo alle funzioni Javascript per instaurare la connessione Winsock, gestire la posizione del controllo PAN e TILT e inviare i dati tramite Winsock verso il modulo ESP32-CAM. Si noti anche il fatto che i comandi inviati tramite Websocket verso il modulo ESP32-CAM sono nel formato Json.

Per esempio il comando relativo alla posizione Pan e Tilt viene inviato tramite la stringa Json: ‘{xy:[‘ + panDegrees + ‘,’ + tiltDegrees +’]}’; che viene poi parsato tramite la ormai famosa libreria Json.Arduino lato ESP32.

Colleghiamo i servo alla scheda

Se vogliamo utilizzare la camera con il controllo PAN e TILT è necessario acquistare un dispositivo meccanico (Fig. 16) che contenga due piccoli servo e che permetta lo spostamento orizzontale (PAN) e verticale (TILT) della camera. Tale dispositivo è comunemente detto “brandeggio”.

Fig. 16

Normalmente il pinout dei servomotori è quello indicato in Fig. 16 dove il pin rosso deve essere collegato ai +5V il marrone alla GND, mentre il pin arancio è il segnale di controllo PWM.

Per il collegamento dei cavetti dei servomotori è preferibile rimuovere i connettori e saldare direttamente gli stessi sul PCB della motherboard, assicurandovi di aver lasciato una lunghezza dei cavi che permettano il movimento completo della camera senza ostacolare lo stesso.

Realizzazione pratica

Elenco Componenti:

C1: 220 µF multistrato
C2, C3: 100 nF ceramico
C4: 220 µF multistrato
P1: Pulsante da CS
- Strip maschio 2 vie (2 pz.)
- Strip maschio 3 vie (2 pz.)
- Strip maschio 6 vie
- Strip femmina 8 vie (2 pz.)
- Jumper
- Circuito stampato S1502

 

Passiamo ora alla costruzione pratica: è necessario ottenere il PCB scaricando il file da www.elettronicain.it e ricavando da esso la pellicola necessaria alla fotoincisione.

Il PCB è a doppia ramatura ed essendo i componenti utilizzati di tipo SMD, la realizzazione pratica richiede un minimo di esperienza e una certa attrezzatura, vale a dire:
• Una stazione saldante che abbia una potenza almeno di 40÷50W. Una punta che, contrariamente a quello che si potrebbe essere portati a pensare non è necessario sia sottilissima. La cosa importante e che sia in buono stato (non ossidata) e che abbia la parte terminale corta, questo consente di trasferire velocemente calore dalla punta alla piazzola ed evita la realizzazione di saldature fredde.
• Della lega di stagno (preferibile Sn-Ag) con flussante, da 0.5 mm e 1 mm.
• Una pinzetta per prelevare e posizionare i componenti.
• Una trecciola dissaldante. Molto importante nel caso in cui vengano a crearsi dei ponticelli tra i pin più ravvicinati dei componenti.
• Una lente di ingrandimento.
• Per ultimo ma non meno importante… tanta pazienza ed una mano salda.

La camera OV2640 presente sul modulo ESP32-CAM normalmente è già collegata al connettore e assicurata con del nastro biadesivo alla parte metallica dello slot micrSD. Per evitare di danneggiarla, non flettete in modo ripetuto il sottile connettore flessibile di cui è dotata e sinceratevi che sia fissata con il biadesivo.

Al solito, iniziate il montaggio dai componenti a basso profilo e proseguite in ordine di altezza.

Download Gerber

Conclusioni

Bene, per il momento abbiamo terminato. Risulterà chiaro che il modulo ESP32-CAM è molto versatile. Per il momento abbiamo appena iniziato a sfruttarne le enormi potenzialità.

Sperimentate con il progetto che vi abbiamo introdotto in questo articolo cercando di prendere confidenza con il modulo ESP32-CAM e con la relativa Motherboard. In un articolo successivo vedremo come utilizzare la Microcamera in un altro progetto molto interessante.

Il codice e le librerie utilizzate nell’articolo sono disponibili al seguente url di Github, https://github.com/open-electronics/ESP32-CAM.

6 Commenti

  1. Buonasera, Ottimo progetto, Vorrei realizzarlo, Gentilmente chiedo all'autore dove poter scaricare il pcb gerber citato nell'articolo, e dove poter comprare il brandeggio con i servo. Grazie
  2. Buonasera potete suggerirmi dove posso comprare il brandeggio per i servo da Voi citati. Grazie ottimo porgetto. spero di farlo subito.
  3. Renderete disponibile anche il circuito già montato per il controllo dei servi? O almeno uno schema che non richieda componenti SMD? Tanto c'è spazio in abbondanza: perchè usare SMD, che richiedono attrezzature speciali e/o abilità particolari? Per quanto riguarda i servi, poso orientarli in modo assoluto? Cioè posso impostarli su 37° o posso solo incrementare/decrementare la rotazione? Hanno un feedback di posizione? E la risoluzione angolare quant'è? Praricamente la parte del pan/tilt è l'unica che mi interessa ma anche l'unica che non avete spiegato in dettaglio. :-)
    • Ciao, il circuito completo non è disponibile, ma puoi scaricare il gerber e realizzarlo con il servizio PCBPRODUCTION. E' stato utilizzato l'SMD per poter mantenere le dimensioni della camera. I servo non hanno feedback, ma puoi comunque modificare il circuito e codice per poterlo implementare.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.

Menu