Approfondimenti sulle centraline fai da te del progetto ScienziAria

Nella nostra guida per costruire una centralina di monitoraggio della qualità dell'aria ci siamo concentrati su come reperire e assemblare i materiali, limitandoci però alle sole configurazioni essenziali e qualche informazione di base.

In questo articolo invece daremo un'occhiata più ravvicinata alla logica interna della centralina, analizzando codice di programmazione e componenti hardware (anche in ottica di consumo energetico, in base alle specifiche tecniche).

Il nostro obiettivo è dare un'infarinatura generale su principi di funzionamento e scelte di progettazione a chiunque abbia curiosità o interesse, senza necessariamente avere conoscenze o esperienze pregresse in questi domini più tecnici.

Sensori a confronto

Andiamo con ordine e partiamo proprio dai sensori di particelle.

Ecco come viene misurata la concentrazione di polveri sottili:

  1. L'aria entra da apposite aperture con un flusso mantenuto costante da una ventola, che funge anche da sbocco di fuoriuscita dell'aria.
  2. Le particelle vengono colpite da un raggio laser LED, la cui luce viene diffusa in base al fenomeno dello scattering e poi catturata da un fotodiodo.
  3. La concentrazione in termini di massa per volume viene infine calcolata con un algoritmo basato sullo scattering di MIE a partire dal conteggio delle particelle e dalla quantità e angolazione dello scattering.

Questo comportamento è comune a tutta la classe dei cosiddetti contatori ottici di particelle (OPC, dall'inglese Optical Particle Counters). Tra i più diffusi sensori di questo tipo figurano il Plantower PMS5003, il Nova Fitness SDS011 e il Sensirion SPS30. Segnaliamo anche l'Alphasense OPC-N3, modello sensibilmente più costoso ma che rientra comunque nella categoria dei sensori low cost.

Di seguito ci soffermeremo brevemente sui sensori da noi scelti, dopodiché vedremo come leggere le rilevazioni e integrarle nella centralina fai da te.

KeyeStudio KS0578

Come già accennato nella guida, la ragione principale per cui abbiamo optato per questo sensore è la sua compatibilità con la piattaforma didattica ArduinoBlocks (che abbiamo usato durante i laboratori del progetto ScienziAria).

Un altro vantaggio è la sua semplicità d'uso: basta collegare i cavetti DuPont, senza doversi preoccupare di trovare opportuni adattatori. Inoltre, grazie al protocollo I2C è più veloce nella trasmissione dei dati rispetto a molti altri sensori (anche se va sottolineato che una differenza di pochi millisecondi è del tutto ininfluente nell'ottica del funzionamento generale della centralina).

Gli svantaggi sono il prezzo più alto e l'assenza di documentazione: nel momento in cui scriviamo, non c'è una scheda tecnica nemmeno sul sito del produttore.

Dopo qualche test e numerose ricerche, siamo comunque riusciti a farci qualche idea sul suo funzionamento interno: pare che il sensore vero e proprio sia un Plantower PMS9003M (o un clone che ne rispetta le specifiche), montato sulla placchetta nera targata KeyeStudio che ha lo scopo di adattare l'output ai connettori DuPont e gestire la comunicazione I2C.

Ne abbiamo smontato uno e non abbiamo trovato etichette sul sensore, per cui non possiamo essere sicuri sull'effettivo produttore. Ad esempio, il Winsen ZH07 è esteticamente identico al PMS9003M, ma riporta caratteristiche tecniche inferiori. Ad ogni modo, dai nostri test è emerso un comportamento del tutto coerente con la scheda tecnica del già citato sensore prodotto dalla più nota azienda Plantower (cfr. PMS9003M datasheet (v1.0)).

Plantower PMS5003

Alla luce di quanto appena esposto, abbiamo scelto questo modello perché ha un funzionamento molto simile al precedente (cfr. PMS5003 datasheet (v1.0)).

Facciamo notare che tutti i sensori della serie Plantower PMSxx03 condividono gli stessi principi di base e hanno caratteristiche tecniche quasi identiche, mentre differiscono soprattutto per la forma esteriore e/o il design interno.

A differenza del KS0578, il PMS5003 prevede una trasmissione seriale asincrona e non è nativamente compatibile con i connettori DuPont. Questi però non sono svantaggi in senso stretto: la modalità di comunicazione dei dati è un dettaglio implementativo, mentre per poter collegare i cavi DuPont è sufficiente frapporre una scheda di adattamento (che ha costi irrisori e inoltre rende più agevole l'uso della modalità risparmio energetico del sensore, come vedremo più avanti).

Inoltre, il PMS5003 è estensivamente testato sul campo: non solo nell'ambito di svariati studi accademici, ma anche in molteplici applicazioni commerciali (tra cui citiamo a titolo di esempio AirGradient e Purple Air). Poiché questo sensore è così popolare, sono disponibili numerose librerie che ne facilitano la lettura (ad esempio PMS Library di Mariusz Kacki (alias fu-hsi), installabile dal Gestore Librerie di Arduino IDE).

In linea di massima, i vantaggi del PMS5003 sono ben più desiderabili di quelli del KS0578. A conti fatti, l'unica discriminante è proprio la compatibilità con ArduinoBlocks (che però è assolutamente facoltativa e, per quanto possa essere utile sul piano didattico, condivide le inerenti limitazioni dei metodi di programmazione visuali come piattaforme a blocchi ed editor WYSIWYG).

PM1 e margini di errore

Nella guida abbiamo accennato che le misurazioni di PM1 non sono affidabili come quelle del PM10 e del PM2,5. Ma per quale motivo? È presto detto.

I nostri sensori sono in grado di rilevare particelle di diametro compreso tra 0,3 e 10 μm (micrometri), ma l'efficienza di conteggio è solo del 50% per le particelle di 0,3 μm (mentre schizza al 98% a partire da 0,5 μm).

Tutto questo al netto dei consueti margini di errore sempre presenti, che per lo più raggiungono il 10–15% circa a seconda delle condizioni di misurazione (rimandiamo alle già menzionate schede tecniche per ulteriori dettagli).

Aggiungiamo che il limite inferiore di 0,3 μm riguarda indistintamente tutti i sensori low cost di cui siamo a conoscenza, per cui supponiamo sia il risultato di limitazioni condivise da tutta questa classe di sensori basati sul laser.

Misurare le particelle di dimensioni ridotte (tra cui il particolato ultrafine, di diametro inferiore a 0,1 μm) è oggettivamente complicato e a detta dell'OMS (Organizzazione Mondiale della Sanità) "non sono ancora disponibili dati sufficienti per fornire raccomandazioni per i livelli AQG [linee guida sulla qualità dell'aria] e gli obiettivi intermedi per tipi specifici di PM" ((fonte: Linee guida globali OMS sulla qualità dell'aria, p. 6).

Facciamo notare infine che queste minuscole particelle hanno una massa relativamente trascurabile, per cui la loro esclusione non influenza in modo significativo le misurazioni delle particelle più grandi (ed è per lo stesso motivo che la concentrazione di particolato ultrafine si esprime piuttosto con il numero di particelle per centrimetro cubo anziché in termini di massa).

Utilità dei sensori a basso costo

Viene naturale chiedersi se questi sensori così economici siano realmente utili. La risposta breve è sì, perché aumentano la risoluzione spaziale e temporale dei dati disponibili. In altre parole, possono coprire più luoghi e intervalli di tempo rispetto alle misurazioni ufficiali.

Dato che ScienziAria è un progetto di Citizen Science, ci sembra davvero il minimo includere qualche fonte accademica a supporto delle nostre asserzioni:

"I sensori low cost per la massa del particolato (PM) consentono misurazioni della qualità dell'aria spazialmente dense e ad alta risoluzione temporale altrimenti impossibili con il monitoraggio di riferimento tradizionale."

(Giordano MR, Malings C, Pandis SN, et al. From low-cost sensors to high-quality data: A summary of challenges and best practices for effectively calibrating low-cost particulate matter mass sensors. Journal of Aerosol Science. 2021;158:105833. doi:10.1016/j.jaerosci.2021.105833)

Poco dopo aver aperto l'abstract proprio con le parole appena citate, lo stesso studio afferma:

"Purtroppo, i sensori PM a basso costo presentano anche una serie di difficoltà che devono essere affrontate affinché sia possibile utilizzare i loro dati per qualcosa di più di una caratterizzazione qualitativa della qualità dell'aria."

Questa "caratterizzazione qualitativa" va più che bene per chiunque non abbia standard accademici o governativi da rispettare, pur di non focalizzarsi tanto sui valori esatti dei sensori quanto sull'andamento delle misurazioni (particolarmente idoneo per rilevare variazioni sospette e picchi di concentrazione).

Ciò nonostante, lo studio prosegue nel dimostrare che "[s]ebbene ottenere dati di alta qualità da questi sensori presenti una serie di difficoltà uniche, tali difficoltà non sono insormontabili" (e lo ribadisce ulteriormente in chiusura).

Menzioniamo anche due pubblicazioni più recenti, con i risultati di analisi svolte proprio in Italia: la prima a Palermo e la seconda a Mesagne (BR).

  1. Brugnone F, Randazzo L, Calabrese S. Use of Low-Cost Sensors to Study Atmospheric Particulate Matter Concentrations: Limitations and Benefits Discussed through the Analysis of Three Case Studies in Palermo, Sicily. Sensors. 2024;24(20):6621. doi:10.3390/s24206621
  2. Suriano D, Prato M. An investigation on the possible application areas of Low-Cost PM sensors for air quality monitoring. Sensors. 2023;23(8):3976. doi:10.3390/s23083976

Poiché le pubblicazioni di stampo accademico sono tecniche e prolisse, citiamo infine due video (più accessibili, ma non meno scientificamente validi).

  1. Low-Cost Aerosol Sensors (5:19). Una lezione narrata dal dott. Thomas Peters (professore presso l'università di Iowa) e creata nell'ambito del Midwest Emerging Technologies Public Health and Safety Training (METPHAST).
  2. TCEQ Border Affairs: Low-Cost Air Sensor Study (4:33). Uno studio binazionale che ha coinvolto la University of Texas at El Paso (UTEP) negli Stati Uniti e la Universidad Autónoma de Ciudad Juárez (UACJ) in Messico, con la partecipazione della dott.ssa Mayra Chavez della UTEP e del dott. Adrián Vázquez dela UACJ.

Lettura delle rilevazioni

Al di là degli aspetti tecnici osservati sinora, ciò che ci interessa è ottenere i valori rilevati dal sensore per integrarli nel codice della nostra centralina.

Il procedimento generale è:

  1. Inizializzare la comunicazione con il sensore.
  2. Ricevere i byte che contengono le ultime misurazioni.
  3. Verificare che non ci siano stati errori di trasmissione.
  4. Elaborare i dati per ottenere la concentrazione di polveri sottili.

L'implementazione a livello di codice dipende dalla modalità di comunicazione e dal protocollo di trasporto del sensore, indicato dal produttore nella relativa scheda tecnica (ecco perché la documentazione ufficiale può tornare utile).

Nel nostro caso, entrambi i sensori usano lo stesso protocollo di trasporto (documentato da Plantower). Per quanto riguarda la modalità di comunicazione, come già accennato il KS0578 usa il protocollo I2C e il PMS5003 la trasmissione seriale: l'ESP32 implementa le apposite librerie di Arduino, in particolare Wire nel primo caso e Serial nel secondo.

Inoltre, il PMS5003 offre due modalità di lettura: attiva e passiva. La prima prevede un invio automatico delle rilevazioni ed è quella predefinita, mentre la seconda permette di ricevere dati su richiesta e viene impostata a seguito di un apposito comando. Il KS0578 invece agisce come un'interfaccia (o un driver, se vogliamo) del PMS9003M (o quale che sia il sensore che monta), emulandone di fatto la modalità passiva (e sopprimendo ogni possibilità di interazione diretta con il sensore, che non può più ricevere comandi).

Anche per chi ha già qualche esperienza di programmazione, avere a che fare con sensori e microcontrollori per la prima volta può risultare poco intuitivo. Noi però abbiamo voluto gestire la lettura del sensore direttamente nel programma, per evitare dipendenze da librerie esterne e semplificare al massimo la fase di configurazione.

Di seguito passeremo rapidamente in rassegna le parti di codice della centralina che permettono di leggere ciascuno dei sensori che abbiamo usato.

Lettura KS0578

Prima di richiedere dati al KS0578 è necessario inizializzare la comunicazione I2C, assicurandosi che i pin SDA e SCL indicati nel codice corrispondano a quelli del circuito (ovvero al collegamento tra scheda ESP32 e sensore).

Per quanto riguarda la lettura in senso stretto, abbiamo inglobato il relativo codice in una funzione personalizzata (readPM()) da richiamare all'occorrenza.

L'indirizzo I2C (0x2a) da cui leggere i dati è deciso a priori dal produttore (KeyeStudio). In mancanza di altra documentazione tecnica, l'abbiamo recuperato a partire dall'implementazione di ArduinoBlocks. (Segnaliamo en passant che in base ai nostri test il sensore non può rilevare anche la concentrazione di formaldeide, al contrario di quanto suggerito dalla piattaforma.)

Una volta ricevuti i dati, procediamo con la validazione in base al meccanismo di checksum documentato da Plantower nella scheda tecnica del sensore.

Se i dati ricevuti sono corretti, possiamo infine estrapolare la concentrazione di PM come indicato dal protocollo di trasporto (sempre nella scheda tecnica).

Lettura PMS5003

Nell'integrare il PMS5003 abbiamo cercato mantenere un certo parallelismo con il codice che avevamo già sviluppato. Usare il sensore in modalità passiva non solo concorre al raggiungimento di questo scopo, ma è anche più facile per chi vi si approccia a partire dal tradizionale paradigma della programmazione imperativa.

La nostra scelta però implica un passaggio aggiuntivo: dopo aver inizializzato la comunicazione seriale, bisogna configurare il sensore. Anche se basterebbe farlo solo una volta, abbiamo optato per un'implementazione meno efficiente ma più semplice e robusta (in linea con le priorità che ci eravamo prefissati).

Abbiamo delegato questi compiti a una funzione apposita (initPM()), in parte anche per preservare ancora il parallelismo di codice tra le due versioni.

L'invio ridondante del comando a ogni ciclo ci permette di saltare a piè pari i controlli di integrità della trasmissione, a patto di svuotare il buffer seriale prima della lettura successiva (che è comunque una buona prassi). Ciò equivale a dare per scontato che il sensore abbia ricevuto e interpretato correttamente il comando pur senza verificare la sua risposta, anziché prevedere un meccanismo di conferma (che dovrebbe peraltro considerare anche malfunzionamenti su cui non sarebbe comunque possibile intervenire e che verrebbero ugualmente rilevati nel corso di un normale utilizzo della centralina).

Inoltre, abbiamo incluso un'attesa di circa 900 ms per prevenire potenziali rilevazioni fallite nel caso limite in cui il sensore non abbia aggiornato la sua struttura dati interna dopo esser entrato in modalità passiva. In condizioni ottimali basterebbero 57 ms, ma l'attesa aggiuntiva è trascurabile ai nostri fini (tanto più che viene comunque recuperata durante la fase di ibernazione).

La funzione readPM() invece implementa lo stesso algoritmo già visto prima, con opportune modifiche dovute alle differenze specifiche tra i due sensori.

Codice e parametri

Abbiamo appena visto alcune implicazioni dei sensori sul codice. Proseguiamo ora analizzando anche il resto del programma.

Partiamo dalla funzione setup(), che viene eseguita ad ogni avvio dell'ESP32 e nel nostro caso contiene la logica relativa alla lettura e all'invio dei dati.

Impostazioni preliminari

Per prima cosa, dobbiamo attendere almeno 30 secondi per ottenere misurazioni stabili a causa delle prestazioni della ventola del sensore (cfr. datasheet, § 8. Circuit Attentions, p. 7: "Stable data should be got at least 30 seconds after the sensor wakeup from the sleep mode because of the fan's performance").

Questo parametro è definito nella costante STABILIZZAZIONE_SENSORE_S in base a esplicite indicazioni del produttore, per cui consigliamo di non modificarlo.

Come sottolineato nei commenti del codice, in questa versione della centralina è sufficiente stabilizzare il sensore solo al primo ciclo di rilevazione.

Per contro, all'inizio di ogni ciclo di rilevazione vogliamo assicurarci che la frequenza della CPU sia ridotta al minimo indispensabile. Questo è un piccolo accorgimento per risparmiare energia, dato che la nostra semplice applicazione non richiede certo tutta la potenza di calcolo dell'ESP32 (che sarà spesso in attesa e quindi girerà a vuoto, consumando inutilmente più corrente del dovuto).

Anche in questo caso ci sono dei commenti con qualche indicazione più specifica direttamente nel codice, per chiunque voglia approfondirne la comprensione.

Lettura del sensore

A questo punto siamo pronti per entrare nella fase di lettura del sensore.

Effettuare svariate rilevazioni e calcolarne la media ci permette non solo di smussare eventuali errori, ma anche di monitorare meglio lo stato del sensore.

I parametri rilevanti qui sono il numero di misurazioni (MAX_LETTURE_SENSORE) e l'intervallo tra due letture successive (POLLING_SENSORE_MS), considerando che il tempo di risposta del sensore (cioè la rapidità con cui può rilevare dei cambiamenti nella qualità dell'aria) può estendersi fino a 1 secondo (sempre in base alla scheda tecnica del sensore in uso, cfr. § 4. Technical Index, p. 5).

Connessione al Wi-Fi

Dopo aver calcolato le medie delle misurazioni, il prossimo passo è connettersi al Wi-Fi (compito apparentemente facile, ma che nasconde delle insidie).

In particolare, è fondamentale prevedere un tempo limite (che nel nostro caso è specificato in millisecondi nella costante TIMEOUT_WIFI_MS).

Dal punto di vista prettamente applicativo, questo ci aiuta a evitare che la centralina consumi risorse in caso di indisponibilità prolungata del Wi-Fi. Dal punto di vista tecnico, risolve un bug (comportamento anomalo e indesiderato) dell'ESP32 su cui non è il caso di dilungarsi in questa sede.

Invio dati a ThingSpeak

Una volta stabilita la connessione, possiamo infine inviare i dati rilevati.

Qui facciamo riferimento alla REST API di ThingSpeak per aggiornare il canale in base alla WRITE_API_KEY (uno dei parametri obbligatori in configurazione).

Abbiamo già visto nella guida che i primi 3 campi si riferiscono alle polveri sottili e proprio in questo articolo abbiamo spiegato perché i valori di PM1 sono meno attendibili rispetto a PM10 e PM2,5 (v. PM1 e margini di errore).

Abbiamo già accennato anche ai campi di controllo, che rivediamo brevemente qui.

Il quarto campo indica la percentuale di letture riuscite, per tenere sotto osservazione il sensore e rilevare eventuali anomalie a colpo d'occhio.

Il quinto campo rappresenta un'indicazione della potenza del segnale Wi-Fi detta RSSI, dall'inglese Received Signal Strength Indicator. Può essere utile per trovare una posizione migliore per la centralina, ma anche come rudimentale strumento di troubleshooting a distanza per diagnosticare problemi nell'invio dei dati.

Il sesto campo infine riporta il tempo necessario per stabilire una connessione al Wi-Fi. Valori ottimali si attestano sui 300 millisecondi o meno, ma pare che per connettersi ad alcuni router ci vogliano 2-3 secondi (il che è tutto sommato ininfluente). Valori più alti possono essere sintomatici di qualche problema di discontinuità della rete, soprattutto se la connessione fallisce frequentemente.

Dopo aver preparato l'URL con la richiesta GET, non ci resta che inviarla.

Predisponiamo quindi una connessione sicura con protocollo criptato HTTPS, per non inviare in chiaro dati sensibili (in particolare la Write API Key). Consigliamo di non modificare i parametri usati in questo frangente, a meno di non avere familiarità con i protocolli di rete e con la libreria HTTPClient.

L'invio della richiesta può fallire per i più svariati motivi, anche se è già stata stabilita una connessione ad internet. Per questo motivo abbiamo previsto la possibilità di riprovare a intervalli incrementali per un certo numero di volte. Tale numero è indicato dal parametro MAX_TENTATIVI_RICHIESTA, mentre gli intervalli sono regolati da un algoritmo di backoff esponenziale in base ai valori definiti nelle costanti FATTORE_BACKOFF_MS e MAX_BACKOFF_MS.

Ibernazione

Giunti ormai alla fine del ciclo, l'ultima cosa da fare è mettere la centralina in ibernazione sfruttando le modalità di risparmio energetico dell'ESP32.

Il tempo di riattivazione è calcolato sulla base di un parametro che denota la frequenza di invio dati, espressa in minuti: INTERVALLO_AGGIORNAMENTI_M.

Dal momento che di solito la concentrazione di polveri sottili nell'aria tende a cambiare lentamente, possono andar bene intervalli compresi tra 2 e 10 minuti.

L'importante è assicurarsi che l'intervallo tra due campionamenti successivi sia sempre superiore al tempo di esecuzione di un intero ciclo di rilevazione, anche nelle peggiori condizioni di connettività immaginabili. A tal proposito, il massimo teorico dipende dai parametri e non è affatto semplice da calcolare con precisione. In compenso, le probabilità che si verifichi nella pratica sono prossime allo zero e basta fare qualche test per trovare un massimo empirico.

Per riferimento, una centralina con le impostazioni predefinite potrebbe restare in attività anche più di mezzo minuto (a prescindere dall'esito dell'invio). Se invece la connessione è buona, un ciclo richiede solitamente tra 7 e 10 secondi.

Curiosità: per parametri particolarmente "sfortunati", la centralina potrebbe "inavvertitamente" finire in ibernazione per ben 49 giorni e 17 ore! Lasciamo la scoperta delle cause di questa precisa durata come esercizio per chi legge.

Nulla vieta di spaziare ulteriormente i campionamenti, ma questo aumenterebbe il rischio di punti ciechi nelle rilevazioni senza causare vantaggi significativi.

Infatti, la limitazione principale di questa versione base è che la ventola del sensore continua a girare anche quando l'attività della centralina è sospesa. Oltre a causare inefficienza energetica, ciò implica uno stress aggiuntivo sul sensore (che a lungo andare potrebbe influire sul suo funzionamento). La buona notizia è che anche i sensori hanno una modalità risparmio energetico, che abbiamo implementato in una delle varianti di centralina proposte più avanti.

E se invece volessimo ridurre gli intervalli di misurazione a meno di un minuto? Anche per questo caso d'uso abbiamo previsto una variante apposita, pensata per effettuare un monitoraggio continuo nel tempo (senza mai andare in ibernazione).

Consumo energetico

Ora che abbiamo finito con il codice, passiamo ad analizzare i consumi.

Per prima cosa dobbiamo considerare che una misurazione precisa della corrente assorbita dalla centralina richiederebbe attrezzatura specialistica di cui non disponiamo. Abbiamo anche provato a misurarla con strumenti a basso costo, che però hanno mostrato gravi difficoltà a tenere traccia di correnti molto basse.

Rimane invece possibile (e non è neanche troppo complicato) valutare in modo approssimativo l'energia richiesta dalla centralina in base alle sue componenti.

Dal risultato dei nostri test e dei nostri calcoli (mantenendoci sempre larghi per cautela), il consumo stimato è al di sotto di 6 kWh all'anno (meno di 1 euro come anticipato nella guida, tenendo presente che alla pubblicazione di questo articolo il prezzo medio dell'energia elettrica si aggira attorno a 0,14 €/kWh).

Sospettiamo che nella maggior parte dei casi i consumi effettivi siano anche più bassi di così... ma saremmo ben lieti di accettare verifiche e correzioni da parte di chiunque sia in grado di misurarli a regola d'arte!

Nel frattempo riveliamo le nostre fonti e rimandiamo alla scheda tecnica dell'ESP32-WROOM-32 (v3.4), che a sua volta rimanda alla sezione RTC and Low-Power Management della scheda tecnica della serie ESP32 (v4.7).

Il consumo nominale di corrente è nell'ordine di poche decine di milliampere, che salgono a un paio di centinaia con uso intensivo del Wi-Fi in trasmissione dati per poi capitolare ai soli 5 μA (microampere) della modalità ibernazione.

Questi dati si riferiscono esclusivamente al microcontrollore e sono coerenti con misurazioni indipendenti che si possono trovare online (segnaliamo a titolo esemplificativo il video YouTube di pcbreflux ESP32 #23: Current Consumption).

A questo va aggiunto il sovraccarico dovuto alla scheda di sviluppo. Ad esempio, il regolatore di tensione potrebbe essere altamente inefficiente nel convertire i 5 V dell'USB ai 3,3 V dell'ESP32 e alcune schede montano LED e componenti aggiuntivi che influiscono sul consumo totale. Questa differenza però è rilevante solo per progetti alimentati a batteria, poiché resta nell'ambito di pochi mA.

A tal proposito, suggeriamo il video YouTube di Andreas Spies: #193 Comparison of 10 ESP32 Battery powered Boards without display (incl. deep-sleep). Segnaliamo anche l'articolo ESP32 Board Power Consumption di The Random Walk per un'ulteriore analisi indipendente.

Non dimentichiamoci infine della componente principe della nostra centralina: il sensore di particelle. Secondo le specifiche tecniche che abbiamo già menzionato in precedenza, la corrente massima di lavoro risulta inferiore ai 100 mA.

A questo punto quindi è sufficiente calcolare la media pesata dei consumi per ogni fase della centralina (ibernazione, lettura sensore, connessione al Wi-Fi e trasmissione dati). Noi ci siamo basati sui valori nominali più alti e abbiamo presupposto che la scheda di sviluppo assorba ulteriori 15 mA (ancora una volta, stima piuttosto conservativa), considerando per ogni fase le tempistiche medie osservate empiricamente su una centralina con impostazioni predefinite.

Mettendo il sensore in risparmio energetico si consumerebbe circa il 70% in meno (in base a calcoli analoghi, basati sugli stessi presupposti e parametri).

Varianti e migliorie

Nella guida, nel codice e in questo stesso articolo abbiamo accennato ad alcune varianti della centralina proposta e analizzata sino a questo punto.

In questa sezione esploreremo rapidamente non solo i nostri esperimenti (con il relativo codice sorgente), ma anche qualche idea che non abbiamo ancora testato.

Sensore a risparmio energetico

Abbiamo menzionato più volte l'impatto della modalità sleep del sensore in termini di efficienza energetica e durabilità della centralina fai da te.

Di fatto, tutte le centraline che abbiamo dislocato in varie zone di Altamura per la nostra azione di monitoraggio sono basate su questa variante.

Purtroppo però i sensori KeyeStudio KS0578 non sono nativamente predisposti per sfruttare la modalità sleep (pur montando un sensore che la supporta), per cui si è rivelato necessario intervenire manualmente su uno dei cavetti.

Abbiamo quindi deciso di escludere questa operazione aggiuntiva (e facoltativa) dalla versione base, mantenendo più semplice possibile la fase di assemblaggio.

Adesso però è arrivato il momento di scoprire di cosa si tratta.

In base alla scheda tecnica, sappiamo che mettere a massa il pin SET (numero 3) sospende la consueta attività del sensore (cfr. § 6. Pin Definition, p. 6). Abbiamo quindi tagliato il cavo in questione per unirlo all'estremità maschile di un cavo DuPont. A questo punto abbiamo collegato il cavo al pin 25 della scheda ESP32, che abbiamo poi opportunamente programmato per poter gestire il livello di tensione appropriato a seconda dello stato della centralina.

Per una discreta giuntura possono bastare anche solo un paio di forbici e del nastro isolante da elettricista, anche se l'ideale sarebbe saldare a stagno i cavi e poi applicare una guaina termorestringente.

Naturalmente consigliamo la massima cautela: unire due cavi potrebbe sembrare un'operazione banale, ma implica dei rischi di sicurezza non indifferenti.

Detto questo, su YouTube ci sono molti tutorial in merito: segnaliamo questo video di Filippo Niccolai, che ci è sembrato ben spiegato e semplice da seguire.

Dopo aver unito e collegato i cavi come appena discusso, non resta che caricare sull'ESP32 il codice di questa variante (configurato con opportuni parametri):

scienziaria-centralina-ks0578-sleep.ino

E per chi invece ha scelto il Plantower PMS5003?

Beh, in questo caso è semplicissimo! E non serve tagliare nulla. Basta soltanto collegare un cavo DuPont tra il pin SET della scheda di adattamento del sensore e il pin 25 dell'ESP32, dopodiché configurare e caricare questo sketch:

scienziaria-centralina-pms5003-sleep.ino

Un'ultima precisazione: si può cambiare la modalità operativa del PMS5003 anche solo trasmettendo un apposito comando, senza dover collegare cavi aggiuntivi. Abbiamo comunque preferito ancora una volta mantenere il parallelismo tra le versioni dei due sensori, tanto più che il codice era ormai già bell'e pronto.

Per contro (e come già osservato), il KS0578 non inoltra al sensore eventuali messaggi ricevuti via I2C ma si limita a emularne la modalità passiva.

Monitoraggio continuo, LED e DHT22

All'estremo opposto della precedente versione a risparmio energetico, in questa variante sia l'ESP32 che il sensore di polveri sottili sono sempre in attività.

Se prima l'ordine di esecuzione era predefinito e lineare, adesso invece dipende anche da eventi esterni che possono verificarsi in qualsiasi momento (cambiando lo stato della centralina in modo asincrono e imprevedibile).

Abbiamo dunque stravolto la logica della centralina, concettualizzandola come una macchina a stati e avvicinandoci a un paradigma di programmazione a eventi.

In altre parole, ci siamo avvicinati a un modus operandi più emblematico dei microcontrollori: una funzione loop() ripetuta indefinitamente per far fronte a tutto in tempo reale (e per questo è buona prassi non bloccare l'esecuzione con delay(), per quanto questa pratica non sia intrinsecamente sbagliata).

La differenza visivamente più immediata è l'introduzione di un indicatore LED che segnala il livello di concentrazione del PM10 e lo stato della centralina: quando è connessa al Wi-Fi, la luce è fissa; altrimenti, la spia lampeggia.

Poiché la centralina usa un normale ingresso USB per l'alimentazione, può essere tranquillamente messa in funzione tramite una power bank per cellulari. E poiché può connettersi a una qualsiasi rete Wi-Fi, si può anche creare un hotspot che corrisponda ai parametri precedentemente inseriti in fase di configurazione.

Questa variante quindi può facilmente diventare una centralina mobile: basta usarla con un sistema esterno di monitoraggio GPS (ad esempio l'app OpenTracks) per associare ogni rilevazione alla sua posizione geografica (ma questo tipo di utilizzo richiede qualche attenzione extra, che vedremo più avanti).

In base alle impostazioni predefinite, le misurazioni avvengono ogni secondo e l'aggiornamento del canale ThingSpeak ogni 16 secondi circa (salvo problemi di connessione). Ogni punto dati è il risultato di una media mobile ponderata esponenziale, che dà un maggior peso alle rilevazioni più recenti.

Abbiamo anche incluso il sensore DHT22, in grado di misurare umidità relativa e temperatura. L'abbiamo gestito con la DHT sensor library di Adafruit, installata tramite il Gestore Librerie di Arduino IDE (assieme alle sue dipendenze).

Collegare il DHT22 è semplicissimo:

  • Pin VDD al pin 3V3 della scheda ESP32.
  • Pin DATA al pin 25 della scheda ESP32.
  • Pin GND al pin GND della scheda ESP32.

L'unica accortezza è assicurarsi di rivolgerlo verso uno sbocco d'aria (noi l'abbiamo posizionato all'estremità di un tubo a gomito della cassetta stagna).

Come sempre, la scheda tecnica del DHT22 contiene tutti i dettagli. Inoltre, è disponibile anche un tutorial di Adafruit sui sensori DHT (in inglese).

Per quanto riguarda invece il LED RGB, abbiamo usato il seguente schema:

  • Pin R al pin 12 della scheda ESP32.
  • Pin G al pin 13 della scheda ESP32.
  • Pin B al pin 14 della scheda ESP32.
  • Pin GND al pin GND della scheda ESP32.

Le schede di sviluppo a 38 pin hanno solitamente 3 pin GND, ma giuntando i cavi ne basta anche solo uno (e si può lasciare libero un intero lato della scheda).

Naturalmente nulla vieta di usare altri GPIO dell'ESP32, a patto di modificare opportunamente il codice per rispecchiare il cablaggio effettivo.

E a proposito di codice, eccone un po' da poter usare come base di partenza o così com'è (o perché no, anche come supporto per imparare a programmare):

scienziaria-monitoraggio-continuo-ks0578.ino

Per la variante basata sul PMS5003 sarebbe sufficiente sostituire le istruzioni relative al funzionamento del sensore, ma ne abbiamo approfittato per migliorare la fase di inizializzazione: oltre a eliminare l'attesa (divenuta innecessaria), abbiamo confermato la risposta del sensore al comando per impostare la modalità passiva (che comunque potrebbe fallire solo a causa di un improbabile errore di trasmissione o un irrecuperabile malfunzionamento del sensore). Ecco lo sketch:

scienziaria-monitoraggio-continuo-pms5003.ino

Si potrebbe anche gestire il sensore nella sua modalità attiva, magari con una delle molte librerie disponibili... o magari anche senza! Per chiunque volesse smanettarci su, abbiamo un altro po' di codice di esempio da condividere:

scienziaria-lettura-pms5003.ino

Centralina indossabile

Un'altra variante che abbiamo già menzionato fugacemente un paio di volte (ad esempio negli articoli sulla biciclettata e sul monitoraggio in Bulgaria) è quella che abbiamo affettuosamente soprannominato la marsupio limited edition.

In realtà questa non è altro che una versione leggermente modificata della centralina mobile vista poco sopra (in quanto non ha il sensore DHT22).

La vera differenza è che si può portare in giro con molta più praticità: invece della classica scatola di derivazione, abbiamo recuperato un vecchio marsupio e l'abbiamo usato come involucro.

Scheda ESP32, power bank e cavi sono dentro. Si potrebbero fissare all'interno anche il LED e il sensore, tagliando appositamente il tessuto per far circolare correttamente l'aria, ma noi abbiamo improvvisato una soluzione meno invasiva.

In ogni caso, usare una centralina in mobilità richiede particolari accortezze.

Come già accennato, è bene unire le rilevazioni itineranti a un meccanismo di geolocalizzazione (a meno di non voler solo osservare i grafici in tempo reale).

Inoltre, bisogna considerare che questi sensori sono pensati principalmente per un uso stazionario. Quando si è in movimento (soprattutto su mezzi relativamente rapidi come una bicicletta), velocità e direzione del vento potrebbero influire sulle misurazioni. L'ideale sarebbe schermare in qualche modo l'ingresso e lo sbocco d'aria del sensore, il che è decisamente più semplice quando si ha a che fare con un involucro vero e proprio (come la scatola stagna da elettricisti).

In ogni caso, meglio evitare movimenti eccessivi (anche per non rischiare che salti qualche cavetto che non sia stato fissato benissimo) ed è sempre controindicato usare apparecchiature elettroniche non resistenti all'acqua sotto la pioggia.

Altre varianti

È tutto qui? Ovviamente no!

C'è una gran quantità di sensori a basso costo e un oceano di nuove possibilità da esplorare per chi abbia voglia di addentrarsi in questo campo.

Restando sul tema del monitoraggio ambientale, la nostra centralina potrebbe sicuramente beneficiare di un sistema di alimentazione a batteria (magari anche montando un pannellino solare). Le opzioni sono molteplici e dipendono dalle proprie esigenze, ma sempre facendo attenzione alle specifiche tecniche (se non vogliamo "friggere" microcontrollori e componenti con voltaggi troppo elevati).

Altre integrazioni migliorative potrebbero essere:

  • Un chip che permetta di usare una SIM per non dipendere da reti Wi-Fi esterne.
  • Un modulo GPS per gestire meglio la geolocalizzazione di rilevazioni mobili.
  • Una scheda microSD per avere un backup locale delle misurazioni effettuate.

Si potrebbe anche trasformare la centralina da dispositivo IoT a strumento offline (che richiede ben meno potenza e versatilità di una scheda ESP32), usando un display LCD per indicare la concentrazione attuale di polveri sottili.

In senso opposto, si potrebbe sfruttare al massimo la connettività dell'ESP32 implementando un meccanismo di aggiornamento OTA (Over-the-air) e creando un'interfaccia web per poter configurare la centralina tramite Wi-Fi.

Come abbiamo detto, le possibilità sono infinite. Speriamo che la nostra guida e questo articolo di approfondimento possano esserti serviti da ispirazione.

Non ci resta che augurarti buon divertimento!