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