L’orto che Twitta: come inviare immagini con ESP32-CAM a Twitter

Il piccolo orticello sul balcone di casa sta diventando la valvola di sfogo di molti italiani che si armano di zappa e rastrello e chini sulla terra si cimentano nel coltivare ortaggi vari. Al momento di strappare quel cespo di insalata si fa sempre un po’ fatica … perché ormai lo considera come uno di casa.
Visto il diffondersi di questa pratica ci è sembrato giusto, in linea coi tempi e le tendenze che vedono la condivisione quotidiana delle attività sui Social, dare al nostro sudato lembo di terra la possibilità di promuoversi su Twitter con dei cinguettii che comunichino il progresso della crescita dei nostri ortaggi e le condizioni meteo dell’orto.
Faremo questo con l’applicazione descritta in queste pagine, basata sul popolare modulo ESP32-CAM che utilizzerà la connettività WiFi e provvederà al monitoraggio di alcuni parametri interfacciandosi ad appositi sensori.

Cos’è ESP32-CAM

L’ESP32-CAM Development Board della A.I. Thinker o equivalente è una piccola scheda con a bordo un SoC (System On Chip) ESP32 equipaggiata da una videocamera da 2M Pixel (OV2640) ad ottica fissa, uno slot per una memoria miniSD fino a 4Gbyte e una serie di linee GPIO per poter interfacciarsi al mondo esterno.
Abbiamo scelto questa piattaforma sia per l’ampia diffusione e il basso costo, sia per la possibilità di gestirla all’interno dell’IDE Arduino come hardware di terze parti, grazie al rilascio da parte della Espressif di specifiche librerie.

Per farvi comprendere come l’ESP32-CAM verrà impiegata proponiamo, nella Fig. 1, la pin-out. Come avrete notato, non è presente la porta USB (per ragioni di economia e semplicità) quindi per poter caricare il nostro sketch sul modulo dovremo dotarci di un convertitore USB TTL che permetta di ottenere una tensione di alimentazione di 5V ed abbia la possibilità di selezionare il livello delle tensioni dei segnali RX e TX a 3,3 V.

Fig. 1

Ricordiamo che il modulo SOC ESP32 non è 5V tolerant quindi i segnali dei sensori che andremo a collegare al pin GPIO devono essere tassativamente tutti nei limite dei 3,3V.
Nella scheda sono presenti tre regolatori lineari di cui un AMS1117-3.3 si occupa di convertire i 5V provenienti dalla alimentazione esterna ai 3,3V necessari per il modulo ESP32. A valle del regolatore è presente un MOS 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.

Per il funzionamento della miniSD sono necessari diversi segnali, alcuni dei quali sono esposti sul connettore del modulo ESP32-CAM, ma dobbiamo essere consapevoli che se vogliamo utilizzare la miniSD dobbiamo rinunciare ad utilizzare questi PIN come GPIO standard.

Nella scheda sono presenti due LED: il primo (indicato come LED) è collegato al pin GPIO33, quindi impegna un I/O che non è neppure esposto esternamente. L’altro LED presente sulla scheda e posizionato frontalmente è un LED ad alta luminosità indicato come LED_FLASH ed è collegato al GPIO4 e controllato tramite un transistore NPN (Q1). Il GPIO33 tuttavia è condiviso (HS2_DATA1) con la scheda miniSD e quindi se viene impiegata la scheda miniSD il LED lo vedrete lampeggiare mentre la SD è in attività.

A bordo del modulo ESP32-CAM è presente un piccolo pulsante di reset del ESP32S collegato a pin E32_RST. Purtroppo i progettisti sono stati poco lungimiranti e non hanno previsto di portare esternamente questo PIN e lo hanno posizionato nel lato inferiore della schedina rendendolo difficilmente accessibile quando il modulo è in sede.
I due pin U0TXD (TX) e U0RXD (RX) che ci permettono di caricare il nostro codice sul modulo ESP32-CAM sono esposti sul connettore esterno. Sul connettore del modulo ESP32-CAM è presente anche una seconda seriale U2RXD (RX) utilizzabile nel caso in cui serva ricevere dati tramite seriale.

Il modulo comprende un’antenna WiFi su PCB.
Nel caso in cui il modulo si trovi molto distante dal router o access-point, c’è la possibilità di collegare una antenna esterna tramite un micro connettore IPEX (U.FL) che si trova sul lato inferiore del PCB, in prossimità dell’antenna integrata. Però per attivare l’antenna esterna è necessario lo spostamento di un ponticello realizzato con un resistore SMD a valore 0 ohm che deve essere spostato dal collegamento con l’antenna integrata al collegamento con il connettore IPEX.

Vi ricordiamo che anche se potrebbe apparire una buona idea bypassare il regolatore AMS1117 ed alimentare il tutto tramite una tensione esterna di 3,3V, è preferibile alimentare il modulo ESP32-CAM tramite l’ingresso 5V che fa, appunto, capo al Regolatore AMS1117.
Notate che il pin 4 (P_OUT) è marcato come 3,3V/5V perche è prevista la possibilità di farvi arivare l’una o l’altra tensione montando una sola per volta delle due “resistenze” da 0 ohm; normalmente è montato il resistore che porta sul P_OUT la tensione a valle del regolatore AMS1117 (3,3V).

Il segnale di reset della microcamera è derivato da una rete RC che permette alla telecamere di resettarsi nella fase di applicazione della tensione di alimentazione.
Potrebbe succedere che la porta del PC non sia in grado di alimentare in modo corretto il modulo stesso e in questo caso, 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 caricatore USB per cellulare è più che sufficiente) oppure tramite un PowerBank. Quello che può accadere se utilizziamo l’alimentazione dalla porta USB è che il modulo risenta della poca capacità di alimentazione e soffra di ripetuti riavvii, blocchi o con dei malfunzionamenti.

Il Sensore BME280 con ESP32-CAM

Bene, ciò detto andiamo a vedere il sensore con cui l’ESP32-CAM funzionerà: nello specifico si tratta del modulo multisensore Bosch BME280.
Sarà quindi possibile scattare ad intervalli predefiniti delle foto delle nostre piantine e contemporaneamente rilevare temperatura, pressione ed umidità. La foto scattata ed i dati meteo saranno quindi pubblicati su un account Twitter in tempo reale. Naturalmente si tratta di un esercizio puramente accademico che ha il solo scopo di investigare il funzionamento delle API di Twitter e permetterci di capire come farlo con un piccolo e modesto ESP32-CAM.

Il BME280 è disponibile in una comoda breakout board che permette di ricavare i valori della temperatura, pressione ed umidità. Il protocollo di comunicazione è SPI oppure I²C. Noi adotteremo il modulo con il protocollo I²C anche perché i pin disponibili sul modulo ESP32-CAM sono veramente ridotti all’osso. Inoltre dovremo utilizzare una libreria particolare e non quella che si usa normalmente sui moduli ESP32 standard perché la seconda va in conflitto con una variabile utilizzata nella libreria della ESP32-CAM.

Il BME280 può misurare l’umidità relativa da 0 a 100% con una precisione del ± 3%, la pressione barometrica da 300 Pa a 1100 HPa con una precisione assoluta di ± 1 HPa e la temperatura da -40° C a 85° C con una precisione di ± 1,0° C. Le misurazioni della pressione sono così precise che il modulo potrebbe essere usato come altimetro con una precisione di ± 1 metro.

Il setup della libreria permette di settare i due pin per la comunicazione I²C, specificando le variabili I2C_SDA e I2C_SCL. Nel nostro caso abbiamo utilizzato il pin 16 per SDA e 14 per SCL. La lettura dei dati del sensore è veramente molto semplice.
È importante utilizzare proprio questi due pin per la comunicazione I²C perché utilizzando altri pin liberi abbiamo notato dei malfunzionamenti che interferiscono con il processo di Boot e quindi con la fase di caricamento del codice.
L’indirizzo I²C predefinito del modulo BME280 è 0x76HEX e può essere modificato facilmente in 0x77HEX rimuovendo un sottile ponticello di pista e facendo una piccola saldatura (Fig. 2).

Fig. 2

Da notare anche che la Breakboard BME280 ospita un regolatore di tensione lineare LDO da 3,3 V quindi deve essere alimentato sul Pin VIN applicando 5V. Sono presenti anche dei traslatori di livello che permettono di interfacciare il modulo con dei microcontrollori che lavorino a 5V. Significa quindi che il cuore del modulo, il sensore Bosch, potrebbe lavorare direttamente con modulo ESP32 alimentandolo a 3,3V ed interfacciandosi con i pin del ESP32. Purtroppo la breakout board non espone i pin di alimentazione a 3,3V né i pin diretti del sensore, quindi dobbiamo sacrificare un po’ di energia ed alimentare la Breakboard a 5V tramite il modulo ESP32. In Fig. 3 vediamo il collegamento del modulo BME280 con il modulo ESP32Cam.

Fig. 3

Creare una App Twitter per ESP32-CAM

Per poter pubblicare un post su Twitter in modo programmatico, ovvero da un dispositivo hardware quale il modulo ESP32-CAM non è sufficiente possedere le credenziali di un account Twitter, ma è necessario essere in possesso anche di un account sviluppatore Twitter. La sottoscrizione quale sviluppatore non comporta costi, ma deve essere richiesta compilando alcuni form sul relativo portale https://developer.twitter.com attendere poi l’esito della richiesta via e-mail che normalmente richiede un paio di giorni di valutazione. Se non siamo stati molto convincenti nel rispondere ai pochi ma perentori quesiti proposti (Fig. 4) qualche volta veniamo ricontattati via e-mail e sollecitati a rispondere ad altre domande che volgono a sincerarsi del fatto che lo sviluppatore non voglia fare un uso fraudolento o comunque non lecito delle API (Application Programming Interface) messe a disposizione dell’ambiente di sviluppo di Twitter.

Fig. 4

Una volta entrati in possesso delle credenziali, sarà necessario terminare la compilazione (Fig. 5) del profilo di sviluppatore inserendo un numero di cellulare valido e convalidarne la correttezza tramite la ricezione di un codice.

Fig. 5

A questo punto si rende necessario accedere alla Dashboard, creare un progetto assegnandogli un nome, nel nostro caso abbiamo usato come nome del progetto “Social Gardening” (Fig. 6) ed all’interno del progetto creare una App.

Fig. 6

Alla App abbiamo assegnato il nome “ESP32 Chirping” (Fig. 7). È poi necessario assegnare dei permessi alla App, per la nostra abbiamo selezionato “Read + Write + Read and post direct messages”.

Fig. 7

Nella schermata che elenca la nostra App è possibile selezionare il pulsante che specifica le Keys ed i Token da utilizzare per l’autenticazione (Fig. 8).

Fig. 8

Aperta questa schermata è possibile individuare due porzioni di nostro interesse: “API Key & Secret” che è in diretta relazione con il nostro account Developer di Twitter e la voce “Access Token & Secret” che è connesso alla specifica App. In pratica per poter postare sul nostro account Twitter tramite codice presente su ESP32 abbiamo necessità di due coppie di stringhe: API Key e API Key secret – Access token e Access token secret.

È assolutamente raccomandato che queste coppie di chiavi non siano divulgate, alla pari delle vostre credenziali Twitter standard, perché permettono di impersonarvi in modo completo. Nel caso in cui per qualche motivo la sicurezza fosse compromessa, è possibile rigenerare le chiavi.
Gli endpoint, ovvero gli indirizzi che vengono utilizzati per effettuare le chiamate verso le API di Twitter, sono ovviamente in https:

https://api.twitter.com/1.1/statuses/update.json

https://upload.twitter.com/1.1/media/upload.json

Dall’URL possiamo evincere anche che vengono usate le API nella Versione 1.1, quella attualmente consolidata. Dalla Dashboard di Twitter è possibile notare che sono in fase di definizione anche delle nuove API 2.0, ma il nostro progetto fa attualmente uso della versione 1.1.

Comunicazione HTTPS con ESP32

Normalmente nell’instaurare un canale di comunicazione in HTTPS sono richieste molte risorse computazionali criptografiche; nel caso del nostro semplice ESP32, per poter instaurare una comunicazione sicura in HTTPS ci si accontenta di verificare se l’url al quale intendiamo collegarci sia da ritenersi attendibile, e per poter fare questo si ricorre alla verifica di validità del certificato dell’endpoint basandosi sulla catena di certificazione e quindi andando a ritroso verificando che il certificato dell’ente Emittente (CA) sia valido.

Un po’ come funziona il sistema notarile: un notaio emette un atto, chi viene in possesso dell’atto, per verificarne la validità controlla che il Notaio che l’ha redatto sia in effetti iscritto all’albo Notarile.
Per poter fare questo abbiamo bisogno di salvare sul nostro sketch, la FingerPrint del certificato della CA che ha emesso il certificato per i siti degli endpoint di Twitter.

Per estrarre il certificato utilizzeremo il browser Chrome. Apriamo quindi Chrome e digitiamo nella barra degli indirizzi l’url di uno degli endpoint di Twitter (“https://api.twitter.com”), il lucchetto chiuso alla sinistra dell’url ci indica che il certificato e valido e si è quindi in comunicazione protetta con l’endpoint. Se clicchiamo sul lucchetto si apre una finestra, clicchiamo su “certificato (Valido)” poi sul tab “Percorso di certificazione” e poi sul primo elemento della catena di certificazione “DigiCert”, poi clicchiamo sul pulsante “Visualizza Certificato”, clicchiamo sul tab “Dettagli” e poi su “Copia su file…”, pulsante Avanti, selezioniamo “Codificato Base 64 X.509” ed infine pulsante Avanti, selezionando il nome del file (il nome non è importante) in cui vogliamo salvare il certificato.

Dobbiamo copiare il contenuto del file in una variabile root_ca nel nostro sketch avendo cura di terminare in modo corretto le varie righe di cui si compone il certificato con il carattere \n” \ come si potrà vedere dal codice.
Abbiamo riportato la procedura per ottenere il certificato di Root a scopo di completezza, ma non preoccupatevi: potete saltare la procedura perché l’abbiamo fatto per voi e lo abbiamo incluso nel file twitter_settings.h.

Come avrete notato analizzando il certificato in Chrome, la scadenza è 10/11/2031, quindi fino a quella data potremo stare sicuri che la comunicazione con gli endpoint avverrà in modo corretto.

Server NTP (Network Time Protocol)

Le API di Twitter richiedono che il dispositivo ESP32 fornisca durante la comunicazione dei Timestamp corretti. Per ottemperare a questo requisito è necessario che il Modulo ESp32 utilizzi il servizio fornito da un server NTP. Inoltre abbiamo necessità di attivare l’invio del Twitt ad una particolare ora e quindi dobbiamo sincronizzare l’RTC (Real Time Clock) interno al modulo ESP32 con il servizio NTP.
NTP sta per Network Time Protocol. È un protocollo Internet (IP) standard per sincronizzare gli orologi del computer tramite rete internet. Il protocollo può essere utilizzato per sincronizzare un dispositivo con l’ora UTC (Coordinated Universal Time). L’ora UTC è uno standard mondiale, strettamente correlato al GMT (Greenwich Mean Time). L’UTC non varia, è lo stesso in tutto il mondo.
NTP imposta l’ora sulla base di UTC, qualsiasi offset del fuso orario locale o dell’ora legale deve essere applicato dal client.
In questo modo i client possono sincronizzarsi ai server indipendentemente dalla posizione e dalle differenze di fuso orario.
Il dispositivo client come ESP32 si connette al server utilizzando il protocollo UDP (User Datagram Protocol) sulla porta 123.
Il client trasmette quindi un pacchetto di richiesta a un server NTP.
In risposta a questa richiesta, il server NTP invia un pacchetto timestamp.
Un pacchetto timestamp contiene più informazioni come timestamp, accuratezza, ritardo o fuso orario UNIX.
Un client analizza i valori di data e ora correnti e setta l’orologio interno (RTC)
Per fare questo la funzione che dovremo usare per ottenere la sincronizzazione del RTC con il servizio NTP è:

configTime(gmtOffset_sec, daylightOffset_sec, ntpServerName)

dove:

gmtOffset_sec

lo possiamo ricavare dalla seguente url: https://en.wikipedia.org/wiki/List_of_UTC_time_offsets
Nel nostro caso viene impostato a 3600 secondi = 1h

daylightOffset_sec

è in pratica il parametro che definisce lo scostamento dell’ora solare. Lo possiamo settare a 0 e probabilmente lo sarà anche per gli anni a venire visto che il 2020 sembra che sia stato l’ultimo in cui La UE utilizzerà l’ora solare.

NtpServerName

Si tratta dell’URL del server che andremo ad interrogare. Lo settiamo a “pool.ntp.org”, come suggerisce il prefisso, si tratta di un pool (batteria di server) che assicurano la risposta in tempi brevi e garantisce una notevole ridondanza.
Il modulo RTC integrato sul modulo ESp32 non eccelle come precisione e quindi è buona norma risincronizzarlo abbastanza regolarmente. Abbiamo fatto in modo che la sincronizzazione avvenga al primo boot del dispositivo ed ogni 5 riavvi successivi.

Una volta eseguita la sincronizzazione, per interrogare l’RTC e ricavare l’ora e la data corrente, possiamo usare una funzione getLocalTime(&timeinfo) dove &timeinfo è il puntatore alla struttura dati che “riceverà” la data e l’ora corrente.
Bene, se chiamassimo questa funzione contestualmente alla sincronizzazione con il server NTP, l’ora ritornata sarebbe corretta, ma se come abbiamo intenzione di fare non facessimo una sincronizzazione con il server NTP ad ogni boot del dispositivo, andando a recuperare l’ora e la data come visto sopra, avremmo l’amara sorpresa di trovare uno scostamento rispetto a quella effettiva.
Per scongiurare questo dobbiamo “informare” il codice della nostra TZ (Time Zone) per cui prima di chiamare la funzione getLocalTime() dobbiamo settare il TZ con la funzione seguente setenv(“TZ”, “CET-1”, 1) anche qui è possibile gestire l’ora legale, ma la sintassi della stringa è un poco più articolata. Per esempio setenv(“TZ”, “CET-1CEST-2,M3.5.0/02:00:00,M10.5.0/03:00:00”, 1);

Vi rimandiamo al seguente sito per una lista https://remotemonitoringsystems.ca/time-zone-abbreviations.php

Per la stessa motivazione addotta in riferimento al parametro daylightOffset_sec, anche qui non setteremo l’ora legale e quindi adotteremo solo setenv(“TZ”, “CET-1”, 1).

Gestire la fotocamera dell’ESP32-CAM

Il modulo ESP32-CAM espone esternamente diversi pin sui due Header, ma non tutti sono utilizzabili. Alcuni sono dedicati alla comunicazione con il chip PRAM, altri sono impegnati per la scheda SD, ed alcuni per gestire la CAMERA. Inoltre la gestione della Camera impone l’utilizzo di risorse anche software che potrebbero compromettere il funzionamento di altri sensori aggiuntivi.
Per questo motivo abbiamo adottato la tecnica di inizializzare la camera solo nel momento in cui si renda necessario scattare la foto ed al termine effettuare un deinit() per liberare le risorse software.
Tra le cose che devono essere fatte nella fase di inizializzazione della camera c’è l’esigenza di portare a livello basso il pin CAM_POWER nella fase di inizializzazione e a livello alto in quella di de inizializzazione tramite i comandi digitalWrite (CAM_POWER, LOW); digitalWrite (CAM_POWER, HIGH); Lo scopo del pin è quello di controllare l’applicazione dei 3.3V derivanti dal regolatore AMS1117 ai due regolatori a 2,8V e 1,2V necessari per l’alimentazione della Camera.

La foto catturata dalla camera non sarà salvata né sulla SD card (che non adotteremo) né sul Filesystem SPIFF il quale in seguito a ripetute scritture potrebbe deteriorare il funzionamento del modulo. Ricordiamo che il filesytem SPIFF è derivato dalla Flash memory e quindi ha un limite di circa 10.000 cicli di scrittura. La foto viene invece mantenuta in memoria e viene quindi inviata al server attingendo alla variabile (Buffer) in cui il modulo ESP32CAM salva i dati. Non possiamo neppure utilizzare la MicroSD perché poi non avremmo disponibili i pin GPIO che ci servono per comunicare con il sensore Bosch.

Modalità Low Power dell’ESP32

Il nostro scopo è quello di mantenere il più possibile il modulo ESP32CAM in modalità basso consumo (LP), risvegliarlo dopo un certo intervallo di tempo, scattare una foto, leggere i parametri dal sensore BME280, comporre un messaggio di testo, postare il tutto su Twitter e poi tornare in modalità LowPower.
Naturalmente non ha senso inviare più di un messaggio al giorno e quindi abbiamo deciso di specificare che il risveglio debba avvenire definendo un orario in una variabile e quindi l’ideale sarebbe un risveglio ogni 24 ore in un orario specificato per esempio alle 10 del mattino.

Purtroppo non è possibile mantenere in modalità LP il modulo per un tempo così lungo e quindi quello che abbiamo fatto e definire il max intervallo di sleep, poi ad ogni risveglio andremo a controllare se l’orario corrente corrisponde a quello impostato per lo scatto della foto.
Se non coincide torneremo velocemente in modalità LP senza nemmeno inizializzare la connessione WiFi, la camera o altro. Se invece l’orario corrisponde con quello impostato, attiveremo il WiFi, leggeremo i dati del sensore, scatteremo la foto e la posteremo su Twitter per poi tornare velocemente in modalità LP, in attesa di un altro ciclo.
Inoltre, ogni 5 riavvii andremo ad interrogare il server NTP per sincronizzare l’orario del modulo interno RTC.

Il modulo ESP32-CAM nell’IDE Arduino

Come anticipato nella parte introduttiva, grazie alle librerie rilasciate da Espressif è possibile utilizzare il modulo tramite l’ambiente di sviluppo di Arduino. Come di consueto, se non avete già utilizzato dei moduli ESP32 nei vostri progetti precedenti seguite passo-passo le indicazioni seguenti per installare il Core dei moduli SoC ESP32. Consigliamo vivamente di assicurarsi di aver la versione della IDE di Arduino più recente possibile.

Fig. 9

Al momento della stesura del seguente articolo la versione più aggiornata è la 1.8.13. Apriamo quindi dal menu file la voce File/Impostazioni. Poi individuiamo la casella di testo “URL aggiuntive per il gestore di schede” (Fig. 9) e clicchiamo sul pulsante a destra per aprire una finestra (Figura 10) nella quale poter inserire l’URL di definizione dei core SoC fornito da Espressif:

https://dl.espressif.com/dl/package_esp32_index.json

ed inseriamolo (oppure aggiungendolo ad altri eventualmente presenti) nella casella di testo e salviamo cliccando su OK.

Fig. 10

Riavviamo quindi L’IDE di Arduino. Poi andiamo a selezionare Strumenti/Gestione schede, digitiamo “ESP32” nella casella di testo. Dopo una breve attesa dovrebbe apparire la voce visibile in Fig. 11, selezioniamo la versione più recente del pacchetto.

Fig. 11

Nel nostro caso 1.0.3 e clicchiamo su installa. Una barra di progressione apparirà in calce alla scheda informandoci sul progresso della installazione. Al termine della quale potremo riavviare L’IDE di Arduino e alla prossima apertura avremo un sottomenu con una nuova serie di schede basate sul chip SoC ESP32 installate sul nostro ambiente di sviluppo. Il modulo che dobbiamo selezionare per il progetto corrente dovrà essere “ESP32 Dev Module”.

Il Codice per inviare foto su Twitter con ESP32-CAM

Il codice è organizzato in quattro file: il file principale ESP32CamMEM.ino, il file di ap_settings.h che definisce i dati di accesso al nostro Router WiFi e i parametri del server NTP, il file che specifica i pin del modulo camera_pins.h ed il file twitter_settings.h che specifica i parametri di connessione con gli endpoint di Twitter ed il certificato CA degli stessi. Per il progetto di questo articolo avremo necessità di aggiungere le seguenti librerie ad Arduino:
ArduinoJson https://github.com/bblanchon/ArduinoJson
BME280 https://github.com/BoschSensortec/BME280_driver
TimeLib https://github.com/PaulStoffregen/Time

Fig. 12

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 ArduinoJson (Fig. 13) mentre per BME280 e TimeLib (non essendo tuttora disponibili nel repository di Arduino) dovremo inserirle a mano nella cartella Libraries di Arduino.

Fig. 13

Dovremo quindi scaricare il file zippato BME280_driver-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 ed analogamente per TimeLib. Inserite le librerie e riavviato L’IDE, saremo pronti per il nostro codice.
Non riporteremo lo sketch completo nell’articolo, ma solo le parti salienti.
Potrete comunque trovare tutto il codice sul nostro sito; qui di seguito vediamo la parte di importazione delle librerie:
#include <TimeLib.h>
#include <time.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <ArduinoJson.h>
#include <base64.h>
#include <esp_camera.h>
#include <Arduino.h>
#include <BME280.h>
#include <soc/rtc_cntl_reg.h>
#include <esp_task_wdt.h>
#include “ap_settings.h”
#include “twitter_settings.h”
#include “camera_pins.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 WiFiClientSecure che viene impiegata per effettuare le chiamate alle API di Twitter in https, poi a seguire la Libreria WiFi.h per la gestione del WiFi, ArduinoJson.h per parsare i response delle chiamate API. La libreria BME280.h per la lettura dei dati dal sensore.

Abbiamo anche un paio di librerie del Core del modulo ESP32 Core, come soc/rtc_cntl_reg.h usata per disattivare brownout detector (il rilevamento delle sotto tensioni di alimentazione) e esp_task_wdt.h usata per realizzare una funzione per riavviare il modulo che impiega il Watch Dog, poi una libreria crittografica base64.h impiegata per codificare in base64 alcuni parametri durante le chiamate alle API di Twitter.

Vediamo poi nella parte terminale della stessa sezione l’inclusione dei file locali. Notare la mancanza delle parentesi angolari (< >) cosa che sta ad indicare che i file si devono trovare nella stessa cartella del file principale dello sketch.
Abbiamo poi due righe di codice molto interessanti che definiscono due variabili particolari:

RTC_DATA_ATTR int bootCount = 0;
RTC_DATA_ATTR int NTP_set = 0;

L’attributo RTC_DATA_ATTR anteposto al tipo (int) specifica che queste due variabili sono destinate a “sopravvivere” durante la fase di passaggio in modalità LowPower e successivo risveglio.
In pratica RTC_DATA_ATTR specifica che la collocazione del valore delle due variabili deve essere posizionata nella memoria (registri) RTC che mette a disposizione fino ad 8K di spazio. Il mantenimento del valore delle variabili avviene in virtù del fatto che durante la fase di basso consumo uno dei pochi moduli che rimane alimentato è proprio l’RTC ed i suoi registri di memoria.

Naturalmente non bisogna abusarne (vista la ridotta dimensione), ma in questo caso è essenziale mantenere il numero di cicli di LowPower eseguiti ed il fatto che la chiamata al server NTP sia andata a buon fine. All’interno del codice potremo utilizzare queste variabili nel modo tradizionale. Naturalmente se resetteremo il modulo tramite il relativo pulsante oppure togliendo l’alimentazione al modulo queste variabili verranno resettate. Dopotutto vivono in una memoria RAM.
Nel blocco successivo abbiamo la definizione del fattore di conversione da secondi a microsecondi, utilizzato nella definizione dell’intervallo di durata della modalità LP, poi abbiamo la durata massima in secondi che possiamo assegnare al modulo e l’orario al quale deve essere scattata la foto e postata su Twitter.

#define uS_TO_S_FACTOR 1000000ULL long SleepDuration = 7200;
int ShootAt = 10;

Di seguito abbiamo la definizione dei pin dedicati alla comunicazione I²C con il sensore BME280 e la definizione del pin utilizzato per esempio per fare triggerare l’uscita del modulo dalla modalità LP:

#define P_BUTTON GPIO_NUM_13
#define I2C_SDA GPIO_NUM_16
#define I2C_SCL GPIO_NUM_14

Abbiamo inoltre il blocco che definisce SHA1 di porzioni di testo nella fase di invio agli endpoint delle API di Twitter utilizzando delle librerie esterne scritte in C (Listato 1).

Listato 1

extern “C” {
  typedef struct{
   uint32_t Intermediate_Hash[SHA1_SIZE / 4];
   uint32_t Length_Low;
   uint32_t Length_High;
   uint16_t Message_Block_Index;
   uint8_t Message_Block[64];
} SHA1_CTX;
  void SHA1Init(SHA1_CTX *);
  void SHA1Update(SHA1_CTX *, const uint8_t * msg, int len);
  void SHA1Final(uint8_t *digest, SHA1_CTX *);
}

A seguire troviamo l’assegnazione dello SSID e della password (che dovrete personalizzare) della nostra rete WiFi, che sono definiti nel file esterno ap_settings.h :

const char* ssid = WIFI_SSID;
const char* password = WIFI_PASSWORD;

Proseguendo nel codice abbiamo l’attribuzione delle variabili utilizzate per le chiamate alle API di Twitter.

char consumer_key[] = API_KEY;
char consumer_secret[] = API_KEY_SECRET;
char access_token[] = ACCESS_TOKEN;
char access_secret[] = ACCESS_TOKEN_SECRET;
char base_host[] = API_BASE_HOST;
char base_url[] = API_BASE_URL;
char base_uri[] = API_BASE_URI;
char message_array[141];

Da notare la variabile che dovrà contenere il messaggio testuale del Twitt char message_array[141]; che quindi come ci si poteva aspettare può contenere al massimo un messaggio di 140 caratteri. La dimensione è 141 per il carattere terminatore.
Nel blocco successivo abbiamo poi la definizione della variabile destinata a contenere il FrameBuffer fb della immagine ripresa della camera, la classe del sensore BME280 e la classe del client Http che useremo per postare i dati verso gli endpoint delle API di Twitter in Https.

camera_fb_t * fb = NULL;
Bme280 bme280;
WiFiClientSecure client;

Nel blocco seguente (Listato 2) abbiamo la sezione di Setup del codice.

 

Listato 2

Void setup () {
  bool result = false;
  Serial.begin(115200);
  pinMode(P_BUTTON, INPUT_PULLUP);
  pinMode(LED_BUILTIN, OUTPUT);
  esp_sleep_enable_ext0_wakeup(P_BUTTON, 0);
  ++bootCount;
  Serial.println(“Boot number: “ + String(bootCount));
  Serial.println(“NTP_set: “ + String(NTP_set));
  print_wakeup_reason();
  if (NTP_set == 0 || bootCount%5==0) {
   wifi_connect();
   Sync_With_NTP();
  }
}

 

Le parti degne di nota della sezione di setup sono: La definizione dei due I/O il pulsante P_BUTTON come INPUT_PULLUP e LED_BUILTIN come OUTPUT, subito sotto abbiamo la definizione della assegnazione del pulsante P_BUTTON alla routine di Wakeup dalla modalità LP sul fronte di discesa dello stato del PIN. Abbiamo poi l’incremento del contatore di risvegli bootCount che viene incrementato ad ogni risveglio del modulo. Viene poi inserita a scopo di debug, (e quindi in produzione la riga può essere commentata) la visualizzazione del motivo che ha comportato il risveglio del modulo, raggiungimento del tempo massimo di SleepMode, oppure la pressione del pulsante P_BUTTON.

Abbiamo poi la verifica di una condizione: se non è stata eseguita la sincronizzazione oppure se il numero dei cicli LP è multiplo di 5 vengono eseguite la connessione WiFi e la sincronizzazione con il server NTP.

 

Listato 3

void loop() {
// Acquisisce l’ora corrente
  CurTime ct = getTime();
  Serial.print(“CurrentHour:”);
  Serial.println(ct.CurrentHour);
  Serial.print(“CurrentMinutes:”);
  Serial.println(ct.CurrentMin);
  Serial.print(“CurrentSeconds:”);
  Serial.println(ct.CurrentSec);
// Comparo l’ora corrente con l’ora di invio Twitt
  if (ct.CurrentHour == ShootAt) {
    if (WiFi.status() == WL_CONNECTED) {
      if (! twitt_done ) {
       inizialize_CAM();
       twitt_done = send_Twitt();
       BeginSleep();
      }
    } else {
     wifi_connect();
    }
  } else {
  Serial.println(“NOT IN TIME WINDOW”);
  BeginSleep();
  }
}

Nella sezione di Loop() (Listato 3), viene letta l’ora attuale dal RTC tramite la funzione getTime() che ritorna una Struct CurTime, viene quindi confrontata l’ora corrente con l’ora per la quale desideriamo che venga effettuato il Post. Se l’ora non coincide il dispositivo viene messo nuovamente in modalità LowPower. Quando l’ora corrisponde, viene verificato se la connessione WiFi è attiva, se attiva viene inizializzato il sensore BME280, viene inizializzata la camera, viene scattata la foto ed inviato il Tweet e poi il dispositivo viene messo in modalità LowPower. Se non attiva viene eseguita la connessione WiFi.

Caricare lo sketch sul modulo ESP32

Come primo passo compiliamo il codice. Apriamo la voce “Strumenti” dal menu della IDE di Arduino e settiamo le varie voci evidenziate come in Fig. 13. La porta seriale potrebbe essere diversa da quella che abbiamo indicato, in tal caso selezionate dal menu a discesa quella corretta nel vostro PC. Chiaramente dovremo poi mantenere le stesse impostazioni quando avvieremo il processo di caricamento. Terminata la configurazione cliccate sul pulsante con il segno di spunta nell’IDE di Arduino. Se il processo di compilazione si è concluso con successo, possiamo passare al caricamento dello sketch; se invece si verifica un errore di compilazione, dobbiamo prima risolverlo.

Fig. 14

Per poter caricare lo sketch sul modulo, dobbiamo per prima cosa collegare (prestando attenzione alla pin-out ed al settaggio dei livelli di tensione) il convertitore USB/seriale alla porta USB del nostro PC e al connettore che abbiamo predisposto sulla motherboard, settare in modalità programmazione il modulo chiudendo con un ponticello il connettore SV5 che fa capo al GPIO0. Il modulo del convertitore USB proposto in Fig. 15 ha una piedinatura che si adatta al connettore della schedina, ma non è scontato. Se avete un convertitore diverso prestate attenzione alla corrispondenza dei pin.

Fig. 15

Poi dobbiamo cliccare sul pulsante di upload dell’IDE di Arduino e dopo qualche secondo pigiare brevemente e rilasciare 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à di programmazione (Fig. 16). Rimosso il ponticello, apriamo il monitor seriale e pigiamo il pulsante di reset. Dopo qualche secondo dovrebbero apparire dei messaggi di log che ci informano del funzionamento del nostro sketch.

Fig. 16

Realizzazione pratica

Per la programmazione monteremo l’ESP32-CAM sulla scheda madre, che consente il caricamento da PC tramite un convertitore USB-TTL.

Il Gerber di questa scheda è scaricabile dalla sezione download di questo articolo.
Il progetto si realizza facilmente connettendo tra loro la brekout board BME280 e la ESP32-CAM come proposto nela Fig. 3; il tutto andrà innestato nella scheda adattatrice giusto il tempo per programmare il modulo. Notate che la camera OV2640 presente sul modulo ESP32-CAM, normalmente è già collegata al connettore e assicurata con un pezzetto di nastro biadesivo alla parte metallica dello slot miniSD. Per evitare di danneggiarla, non flettete in modo ripetuto il sottile connettore flessibile di cui è dotata e sinceratevi che sia fissata con il biadesivo.

Conclusioni

Bene, per questo articolo abbiamo terminato; con questa nuova applicazione vi risulterà chiaro che il modulo ESP32-CAM è molto versatile. Sperimentate con il progetto che vi abbiamo introdotto in questo articolo cercando di prendere confidenza con il modulo ESP32-CAM. Il codice e le librerie utilizzate nell’articolo sono disponibili su Github.

Download

 

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.

Menu