Impara come costruire una stazione meteo con un ESP32 che mostra informazioni meteorologiche locali o da internet su un display e-Paper.
In questo tutorial imparerai come costruire una stazione meteo alimentata a batteria che utilizza la modalità deep-sleep dell’ESP32 e un display e-Paper per una lunga durata. In realtà costruiremo due versioni. Una versione mostra temperatura ambiente, umidità e pressione atmosferica raccolte tramite un sensore BME280. L’altra versione legge i dati meteo da internet usando OpenWeather e utilizza il software ESP32-e-Paper-Weather-Display per visualizzarli.
Iniziamo!
Componenti necessari
Per questo progetto sto usando una vecchia scheda ESP32 (ESP32 lite), che è stata deprecata ma è ancora reperibile. È quella elencata qui sotto. Esiste un modello successore (Amazon) con specifiche migliorate. E la scheda predefinita che la libreria ESP32-e-Paper-Weather-Display utilizza è una LOLIN D32, che ha un monitor integrato della tensione della batteria.
Ma qualsiasi altro ESP32, ESP8266 o Arduino (con WiFi) funzionerà comunque. Preferibilmente, però, si consiglia una scheda di sviluppo con capacità di ricarica batteria e basso consumo in deep-sleep, come le schede ESP32 menzionate sopra.

Display e-Paper da 2,9″

ESP32 lite

Sensore BME280

Cavo dati USB

Set di fili Dupont

Breadboard
Makerguides is a participant in affiliate advertising programs designed to provide a means for sites to earn advertising fees by linking to Amazon, AliExpress, Elecrow, and other sites. As an Affiliate we may earn from qualifying purchases.
Display e-Paper
Una breve parola sul display e-Paper che useremo per la nostra stazione meteo. I display e-Paper, chiamati anche display e-Ink, hanno il vantaggio di consumare pochissima energia. In realtà, l’energia è necessaria solo per aggiornare il display. Una volta aggiornato, il contenuto rimane praticamente visibile per sempre, senza consumare energia.

Un altro vantaggio del display e-Paper è che ha angoli di visuale fantastici (>170 gradi) ed è facile da leggere anche sotto la luce del sole.
Gli svantaggi sono il tempo di aggiornamento lento, la gamma di colori limitata e l’assenza di retroilluminazione; quindi non si possono leggere al buio.
Di solito un display e-Paper impiega 2 secondi per aggiornarsi, anche se è possibile fare aggiornamenti parziali di sezioni del display molto più veloci (0,3 secondi). Questo vale per i display in bianco e nero. I display a colori sono molto, molto più lenti nel refresh (> 20 secondi), hanno pochi colori e sono molto più costosi.
Ma per una stazione meteo alimentata a batteria che aggiorna i dati solo ogni pochi minuti, i display e-Paper sono una scelta eccellente e hanno un aspetto davvero bello.
Modulo display e-Paper da 2,9″
Per questo progetto sto usando specificamente un modulo display e-Paper da 2,9″, con risoluzione 296×128 pixel e un controller integrato con interfaccia SPI.

Nota che la maggior parte dei moduli display e-Paper con SPI ha un piccolo interruttore o jumper che permette di passare da SPI a 4 fili a SPI a 3 fili. Qui useremo il default SPI a 4 fili.
Il modulo display funziona a 3,3V o 5V, ha un consumo in sleep ultra basso di 0,01µA e consuma solo circa 26,4mW durante l’aggiornamento del contenuto. Questo significa che puoi far funzionare un display e-Paper a lungo anche con una piccola batteria.
Per maggiori informazioni sui display e-Paper dai un’occhiata al nostro tutorial Interfacing Arduino To An E-ink Display.
Sensore BME280
Per la nostra stazione meteo vogliamo anche misurare alcuni dati ambientali, come temperatura, umidità e pressione atmosferica. Userò un BME280 sensor qui. Il motivo principale è che ha anche una modalità sleep a basso consumo, dove consuma solo 0,1µA (3,6 μA in modalità normale).
In combinazione con un e-Paper e l’ESP32-lite con un consumo in deep-sleep di 5,65mA (a 5V), questo crea un setup a bassissimo consumo che può funzionare a lungo con batteria.
Il sensore BME280 è molto piccolo e di solito viene montato su una breakout board con interfaccia I2C; vedi l’immagine sotto.

L’interfaccia I2C lo rende molto facile da collegare e usare. Il sensore può misurare pressione da 300 hPa a 1100 hPa, temperatura da -40°C a +85°C e umidità da 0% a 100%. Per maggiori informazioni sul BME280 leggi il nostro tutorial su How To Use BME280 Pressure Sensor With Arduino.
Collegamento e test del display e-Paper
Prima di provare cose complicate, colleghiamo e testiamo il funzionamento del display e-Paper. L’immagine seguente mostra il cablaggio completo per alimentazione e SPI.

Ecco la tabella con tutte le connessioni. Nota che puoi alimentare il display con 3,3V o 5V ma l’ESP32-lite ha solo un’uscita a 3,3V e le linee dati SPI devono essere a 3,3V.
| Display e-Paper | ESP32 lite |
|---|---|
| CS/SS | 5 |
| SCL/SCK | 18 |
| SDA/DIN/MOSI | 23 |
| BUSY | 15 |
| RES/RST | 2 |
| DC | 0 |
| VCC | 3.3V |
| GND | G |
Installazione della libreria GxEPD2
Prima di poter usare il display e-Paper dobbiamo installare due librerie. La libreria Adafruit_GFX è una libreria grafica core che fornisce un set comune di primitive grafiche (testo, punti, linee, cerchi, ecc.). E la libreria GxEPD2 fornisce il driver grafico per controllare un display e-Paper via SPI.
Installa le librerie nel modo consueto. Dopo l’installazione dovresti vederle nel Library Manager come segue.

Codice di test
Ecco un semplice codice di test che mostra il testo “Hello Makers!” sul display. Dai un’occhiata al codice completo prima, poi ne discutiamo alcuni dettagli.
#define ENABLE_GxEPD2_GFX 0
#include "GxEPD2_BW.h"
#include "Fonts/FreeMonoBold9pt7b.h"
//CS(SS)=5, SCL(SCK)=18, SDA(MOSI)=23, BUSY=15, RES(RST)=2, DC=0
GxEPD2_BW<GxEPD2_290_BS, GxEPD2_290_BS::HEIGHT> epd(GxEPD2_290_BS(5, 0, 2, 15));
void initDisplay() {
epd.init(115200, true, 50, false);
epd.setRotation(1);
epd.setFont(&FreeMonoBold9pt7b);
epd.setTextColor(GxEPD_BLACK);
epd.setFullWindow();
epd.fillScreen(GxEPD_WHITE);
}
void displayText() {
epd.setCursor(20, 20);
epd.print("Hello");
epd.setCursor(20, 40);
epd.print("Makers!");
}
void setup() {
initDisplay();
displayText();
epd.display();
epd.hibernate();
}
void loop() {
}
Analizziamo il codice nelle sue componenti per capire come funziona.
Costanti e librerie
Il codice inizia definendo una costante ENABLE_GxEPD2_GFX a 0. Puoi impostarla a 1, che secondo la documentazione abilita la classe base GxEPD2_GFX a passare riferimenti o puntatori all’istanza del display come parametro. Ma usa circa 1,2k di codice in più e non ne abbiamo bisogno, quindi è impostata a 0.
#define ENABLE_GxEPD2_GFX 0
Poi includiamo il file header GxEPD2_BW.h per un display e-Paper in bianco e nero (BW) e il font che useremo. Se hai un display a 3 colori dovresti includere GxEPD2_3C.h, o GxEPD2_4C.h per un display a 4 colori, e GxEPD2_7C.h per un display a 7 colori.
#include "GxEPD2_BW.h" #include "Fonts/FreeMonoBold9pt7b.h"
La libreria Adafruit_GFX include molti font diversi e li puoi trovare nella cartella della libreria sotto {application_path}\Arduino\libraries\Adafruit_GFX_Library\Fonts.
Oggetto Display
La riga successiva è importante. Crea l’oggetto display e dipende dal tipo o marca del display. Ho provato un display WeAct e uno WaveShare e la riga seguente funziona per entrambi.
GxEPD2_BW<GxEPD2_290_BS, GxEPD2_290_BS::HEIGHT> epd(GxEPD2_290_BS(5, 0, 2, 15));
La Readme per la libreria GxEPD2 elenca un enorme numero di display supportati e puoi trovare i dettagli nei file header, ad esempio GxEPD2.h.
Inizializzazione Display
La funzione initDisplay() è responsabile dell’inizializzazione del display e-Paper. Imposta i parametri del display come velocità di comunicazione, rotazione, font, colore del testo e colore di sfondo. Se riscontri problemi con il refresh del display, potresti dover modificare il parametro della funzione init().
void initDisplay() {
epd.init(115200, true, 50, false);
epd.setRotation(1);
epd.setFont(&FreeMonoBold9pt7b);
epd.setTextColor(GxEPD_BLACK);
epd.setFullWindow();
epd.fillScreen(GxEPD_WHITE);
}
Visualizzazione del testo
La funzione displayText() posiziona il cursore sul display e stampa il testo “Hello” e “Makers!” in coordinate specifiche.
void displayText() {
epd.setCursor(20, 20);
epd.print("Hello");
epd.setCursor(20, 40);
epd.print("Makers!");
}
Funzione Setup
Nella funzione setup(), il display viene inizializzato usando initDisplay(), il testo viene mostrato con displayText(), e poi il contenuto viene visualizzato sullo schermo e-Paper. Infine, il display viene messo in modalità ibernazione. Questo spegne il display e mette il controller in deep-sleep.
void setup() {
initDisplay();
displayText();
epd.display();
epd.hibernate();
}
Funzione Loop
La funzione loop() è vuota in questo codice perché il contenuto del display viene impostato nella funzione setup() e non necessita di aggiornamenti continui. L’ESP32 non eseguirà azioni specifiche nel loop.
void loop() {
}
Carica ed esegui il codice
Ora siamo pronti per caricare ed eseguire il codice. Seleziona la scheda che hai nel board manager. Nel mio caso è la WEMOS LOLIN32 Lite elencata nei Componenti necessari:

Poi premi upload e dopo qualche sfarfallio, il display dovrebbe mostrare il seguente testo:

Se funziona, possiamo passare a qualcosa di un po’ più complicato. Altrimenti, controlla il cablaggio e la riga dove viene creato l’oggetto display. In particolare, quali pin sono assegnati all’interfaccia SPI.
Collegamento di e-Paper e BME280 a ESP32
Vogliamo mostrare temperatura ambiente, umidità e pressione atmosferica usando il sensore BME280. Aggiungere il sensore è facile, grazie all’interfaccia I2C. Basta collegare SDA al pin 33 e SCL al pin 25, come mostrato sotto.

Puoi usare pin diversi per I2C ma se lo fai, non dimenticare di modificare il codice nella sezione successiva di conseguenza.
Nota che esistono versioni a 5V e 3,3V della breakout board BME280. Io uso la versione a 3,3V e quindi collego VCC al pin 3,3V dell’ESP32.
Poiché la WEMOS LOLIN32 Lite ha una porta batteria e caricatore integrati, puoi alimentare l’intero sistema con una batteria LiPo. L’immagine sotto mostra il cablaggio completo con una batteria LiPo collegata:

Anche con la piccola batteria LiPo da 420mAh usata qui, sono riuscito a far funzionare il sistema per diversi giorni (con un ciclo di aggiornamento di 5 minuti).
Nella sezione successiva scriveremo il codice per mostrare i dati del sensore sul display e-Paper.
Codice per stazione meteo locale
Il codice seguente legge temperatura ambiente, umidità e pressione dal BME280 ogni 5 minuti e mostra queste informazioni più l’altitudine sul display e-Paper. L’output appare così:

Tra gli intervalli di 5 minuti, ESP32, e-Paper e BME280 vanno tutti in modalità deep-sleep, riducendo notevolmente il consumo energetico del sistema. Dai un’occhiata al codice completo prima, poi analizziamo i dettagli:
#define ENABLE_GxEPD2_GFX 0
#include "Wire.h"
#include "GxEPD2_BW.h"
#include "Fonts/FreeMonoBold9pt7b.h"
#include "Fonts/FreeMono9pt7b.h"
#include "Fonts/FreeMonoBold18pt7b.h"
#include "Adafruit_BME280.h"
#include "esp_sleep.h"
#define SECONDS (1000 * 1000)
#define SEALEVELPRESSURE_HPA 1013.25
#define BME280_ADDRESS 0x76
Adafruit_BME280 bme;
GxEPD2_BW<GxEPD2_290_BS, GxEPD2_290_BS::HEIGHT> epd(GxEPD2_290_BS(5, 0, 2, 15));
void initDisplay() {
epd.init(115200, true, 50, false);
epd.setRotation(0);
epd.setFullWindow();
epd.setTextColor(GxEPD_BLACK);
epd.fillScreen(GxEPD_WHITE);
}
void initSensor() {
Wire.begin(33, 25); // Software I2C for BME280
bme.begin(BME280_ADDRESS, &Wire);
bme.setSampling(Adafruit_BME280::MODE_FORCED,
Adafruit_BME280::SAMPLING_X1, // temperature
Adafruit_BME280::SAMPLING_X1, // pressure
Adafruit_BME280::SAMPLING_X1, // humidity
Adafruit_BME280::FILTER_OFF);
}
void displayText(int x, int y, const GFXfont* f, const char* text) {
epd.setFont(f);
epd.setCursor(x, y);
epd.print(text);
}
void displayHLine(int y) {
int o = 8;
epd.drawFastHLine(o, y, 128 - 2 * o, GxEPD_BLACK);
}
void displayLargeValue(int y, const char* name, float val, const char* unit) {
static char buffer[32];
sprintf(buffer, "%7.1f", val);
displayText(8, y, &FreeMono9pt7b, name);
displayText(4, y + 30, &FreeMonoBold9pt7b, buffer);
displayText(86, y + 30, &FreeMono9pt7b, unit);
displayHLine(y + 50);
}
void displaySmallValue(int y, char* name, float val, char* unit) {
static char buffer[32];
sprintf(buffer, "%5.1f", val);
displayText(8, y, &FreeMono9pt7b, name);
displayText(4, y + 35, &FreeMonoBold18pt7b, buffer);
displayText(110, y + 35, &FreeMono9pt7b, unit);
displayHLine(y + 50);
}
void setup() {
initSensor();
initDisplay();
int o = 20, d = 76;
bme.takeForcedMeasurement();
float temp = bme.readTemperature();
displaySmallValue(o, "temp", temp, "C");
float hum = bme.readHumidity();
displaySmallValue(o + d, "hum", hum, "%");
float alt = bme.readAltitude(SEALEVELPRESSURE_HPA);
displayLargeValue(o + 2 * d, "alt", alt, "m");
float pres = bme.readPressure() / 100.0;
displayLargeValue(o + 3 * d, "pres", pres, "hPa");
epd.display();
epd.hibernate();
esp_sleep_enable_timer_wakeup(5 * 60 * SECONDS);
esp_deep_sleep_start();
}
void loop() {
}
Nel codice sopra, mostriamo le letture di temperatura, umidità e pressione da un sensore BME280 su un display e-Paper. Il sensore è collegato via software I2C e il display è controllato usando la libreria GxEPD2.
Costanti e librerie
Iniziamo includendo le librerie necessarie più tre librerie di font differenti. Nota che dovrai installare la Adafruit_BME280 library, se non l’hai già fatto.
#define ENABLE_GxEPD2_GFX 0 #include "Wire.h" #include "GxEPD2_BW.h" #include "Fonts/FreeMonoBold9pt7b.h" #include "Fonts/FreeMono9pt7b.h" #include "Fonts/FreeMonoBold18pt7b.h" #include "Adafruit_BME280.h" #include "esp_sleep.h" #define SECONDS (1000 * 1000) #define SEALEVELPRESSURE_HPA 1013.25 #define BME280_ADDRESS 0x76
L’indirizzo I2C del sensore BME280 è tipicamente 0x76 ma il tuo potrebbe essere diverso e su alcune breakout board puoi scegliere tra due indirizzi. La costante SEALEVELPRESSURE_HPA è usata dalla libreria BME280 per calcolare l’altitudine basandosi sulla pressione atmosferica. Anche questo va adattato alla tua posizione. Vedi il nostro tutorial su How To Use BME280 Pressure Sensor With Arduino, per maggiori dettagli.
Oggetti sensore e display
Poi creiamo gli oggetti per il sensore BME280 e il display e-Paper. Come detto, se usi un display diverso o un cablaggio differente dovrai modificare la costruzione dell’oggetto display.
Adafruit_BME280 bme; GxEPD2_BW<GxEPD2_290_BS, GxEPD2_290_BS::HEIGHT> epd(GxEPD2_290_BS(5, 0, 2, 15));
Funzioni di inizializzazione
La funzione initDisplay() inizializza il display e-Paper impostando comunicazione, rotazione, colore e pulizia dello schermo. La funzione initSensor() inizializza il sensore BME280 avviando la comunicazione I2C e configurando le impostazioni del sensore.
void initDisplay() {
...
}
void initSensor() {
Wire.begin(33, 25); // Software I2C for BME280
bme.setSampling(Adafruit_BME280::MODE_FORCED,
..
)
}
Poiché usiamo software I2C per il sensore BME280, dobbiamo chiamare Wire.begin(33, 25) con i pin SDA e SCL che stiamo usando. Se colleghi il sensore BME280 a pin diversi, dovrai modificare il codice qui.
Nota che facciamo funzionare il sensore BME280 con l’impostazione MODE_FORCED. In forced mode il sensore esegue una misurazione, memorizza i risultati e poi va in deep-sleep. È quello che vogliamo, dato che tra una misurazione e l’altra metteremo anche ESP32 e e-Paper in deep-sleep.
Funzioni di visualizzazione
Ci sono diverse funzioni per mostrare testo, linee orizzontali, valori grandi (pressione, altitudine) e valori piccoli (temperatura, umidità) sul display e-Paper. Queste funzioni gestiscono il formato e la posizione dei dati da mostrare.
void displayText(int x, int y, const GFXfont* f, const char* text) {
// Display text code
}
void displayHLine(int y) {
// Display horizontal line code
}
void displayLargeValue(int y, const char* name, float val, const char* unit) {
// Display large value code
}
void displaySmallValue(int y, char* name, float val, char* unit) {
// Display small value code
}
Funzione Setup
Nella funzione setup(), sensore e display vengono inizializzati. Vengono prese le letture di temperatura, umidità, altitudine e pressione e mostrate sullo schermo e-Paper. Il display viene poi aggiornato e messo in modalità ibernazione.
Dopodiché mettiamo anche l’ESP32 in modalità deep-sleep e lo risvegliamo automaticamente dopo 5 minuti.
void setup() {
initSensor();
initDisplay();
bme.takeForcedMeasurement();
float temp = bme.readTemperature();
displaySmallValue(o, "temp", temp, "C");
...
epd.display();
epd.hibernate();
esp_sleep_enable_timer_wakeup(5 * 60 * SECONDS);
esp_deep_sleep_start();
}
Funzione Loop
La funzione loop() è vuota perché l’ESP32 entra in deep sleep dopo il setup e non entra mai nel loop. Ma si risveglia ogni 5 minuti ed esegue di nuovo la funzione setup.
Ogni aggiornamento del display dura 2-3 secondi e comporta molto sfarfallio, che è piuttosto fastidioso e poco estetico. Puoi evitarlo facendo un aggiornamento parziale. Per maggiori dettagli dai un’occhiata al tutorial Partial Refresh of e-Paper Display.
A parte questo, ora hai una bella piccola stazione meteo alimentata a batteria che mostra e aggiorna temperatura ambiente, umidità, pressione atmosferica e altitudine!
Codice per stazione meteo internet
Se vuoi una stazione meteo più avanzata che recupera i dati da internet, c’è la fantastica libreria ESP32-e-Paper-Weather-Display che lo fa per te.
A seconda della dimensione del display mostra temperatura, umidità, pressione, direzione del vento, fasi lunari, condizioni meteo, previsioni e altro. Sul display e-Paper da 2,9″ che uso qui, appare così:

Installazione della libreria ESP32-e-Paper-Weather-Display
Per installare la libreria ESP32-e-Paper-Weather-Display devi scaricare il file zip dal repository github e poi installarlo tramite Sketch -> Include Library -> Add .ZIP Library ....

Ti serviranno anche le librerie GxEPD2 library e Adafruit_GFX library, ma le hai già installate nelle sezioni precedenti.
Configurazione della libreria ESP32-e-Paper-Weather-Display
Prima di poter mostrare i dati meteo da internet usando la libreria ESP32-e-Paper-Weather-Display, c’è un po’ di lavoro da fare. Prima dobbiamo ottenere una chiave API da OpenWeather, poi scaricare il codice di esempio per il nostro display, e infine aggiornare il file di configurazione nel codice di esempio con la chiave API e le credenziali Wi-Fi.
Chiave API OpenWeather
La libreria ESP32-e-Paper-Weather-Display usa il servizio gratuito OpenWeather per ricevere dati meteo da internet. Prima di poter usare qualsiasi API di OpenWeather, ti serve una chiave API e per ottenerla devi creare un account. Per creare un account gratuito vai su sign-up page e inserisci i tuoi dati.

Dopodiché vai alla pagina di creazione api-key e crea una chiave API. La chiave API è quella lunga stringa “sdfd87fakeby6apikeysf4z” che vedi nello screenshot sotto. La tua chiave sarà diversa.

Se ti serve aiuto, dai un’occhiata al nostro tutorial: Simple ESP32 Internet Weather Station.
Poi scarica il codice di esempio per la dimensione e tipo del tuo display dal repository github della libreria ESP32-e-Paper-Weather-Display. Per esempio, ho scaricato il codice per il Waveshare_2_9 example.
In alternativa, puoi usare l’IDE Arduino che ha alcuni ma non tutti gli esempi:

File di configurazione owm_credential.h
Infine, apri il file .ino (es. Waveshare_2_9.ino) nell’IDE Arduino e clicca sulla scheda del file owm_credential.h.
Questo file contiene tutte le impostazioni specifiche per la tua stazione meteo come posizione, unità, lingua, fuso orario e così via. Soprattutto, contiene le costanti per le credenziali Wi-Fi (ssid, password) e la chiave API OpenWeather che devi impostare lì.

owm_credential.hFile di configurazione per ESP32-e-Paper-Weather-DisplayCome detto, a seconda della dimensione del display e-Paper, la libreria ESP32-e-Paper-Weather-Display mostra informazioni meteo più o meno dettagliate. Su un grande display da 7,5″ ottieni un set molto ricco di dati meteo ed è davvero fantastico:

Monitor batteria
Infine, la libreria ESP32-e-Paper-Weather-Display mostra nativamente le informazioni sulla batteria se usi una Lolin D32 board che ha il GPIO-35 come ingresso ADC:

Su altre schede dovrai modificare la chiamata analogRead(35) nel codice e specificare il pin dove è collegato il monitor di tensione.

Un monitor di tensione può essere un semplice partitore di tensione collegato ai terminali della batteria. Dai un’occhiata a How to Monitor Battery Voltage for Battery Powered Projects, per maggiori dettagli. Per stime più accurate della carica della batteria puoi usare IC specifici per il monitoraggio della batteria, come il MAX1704X.
Conclusioni
In questo tutorial hai imparato come costruire una stazione meteo alimentata a batteria con un ESP32, un sensore BME280 e un display e-Paper.
Abbiamo usato un sensore BME280 per misurare temperatura ambiente, umidità e pressione atmosferica. E abbiamo usato il software ESP32-e-Paper-Weather-Display per mostrare i dati meteo da internet.
Con questo hai tutti i pezzi per costruire la tua versione che, per esempio, potrebbe combinare dati meteo internet con informazioni meteo locali. Potresti anche raccogliere informazioni da sensori remoti e aggiungerle al display.
Divertiti a sperimentare e se hai domande non esitare a chiedere 😉

