Costruiamo una stazione meteo con ESP32, che rilevi temperatura, umidità, pressione, CO2, velocità del vento e luminosità, alimentandosi da pannello solare e accumulo con batteria da 3,7V, su cui monitorare il livello di carica
Abbiamo già realizzato una prima stazione meteo integrabile in Home Assistant e programmata con ESPHome [LINK], tuttavia ci sembra doveroso fare un importante upgrade cambiando non solo la dev-board, ma aumentando anche il numero di sensori e la qualità, quindi, del progetto. Partiremo usando una ESP32-S3, nello specifico la BPI-Leaf-S3, che abbiamo già visto [LINK], realizzando anche un anemometro con sensore Hall per rilevare la velocità del vento.
Componenti
Come abbiamo anticipato, il nucleo centrale del progetto della stazione meteo sarà la Banana Pi BPI-Leaf-S3, possiede un microcontrollore ESP32-S3, Xtensa® LX7 a 32 bit , corredato da 2MB PSRAM, 8MB di memoria flash e connessione Wi-Fi 2.4GHz a 150 Mbps con standard IEEE 802.11 b/g/n, Bluetooth 5 e tensione di lavoro a 3,3V, sebbene sia possibile fornire una scheda una tensione in ingresso non superiore ai 6V. La scelta ricade su questa scheda, non solo perchè già in nostro possesso, ma perché è una scheda compatibile con progetti a basso consumo energetico, visto che in deep sleep richiede solo 10μA.

Per il monitoraggi di temperatura, umidità e pressione atmosferica ci affidiamo nuovamente al sensore BME280, apprezzato da noi per le piccole dimensioni, prezzo accessibile e consumi ridotti (consuma fino a 3,6 μA). Sebbene non sia tra i sensori più precisi, è perfetto per progetti DIY, il sensore BME280 è discretamente affidabile; abbiamo un’accuratezza dello 0,25% per la pressione con un range compreso tra i 300hPa e i 1100hPa, mentre la temperatura registrabile va da un minimo di -40°C a un massimo di 85°C. L’umidità relativa possiede invece una tolleranza del 3%.

Per monitorare la qualità dell’aria, ci siamo affidati al l CCS811; esso possiede 8 pin e lavora con una tensione di 3,3V, ma per questo progetti andiamo ad erogargli comunque i 5V, altrimenti darebbe problemi nei risvegli da deep sleep. Una volta collegato tramite interfaccia I2C alla dev-board, il sensore misurerà la concentrazione di CO2 (anidride carbonica) in un intervallo compreso tra 400 e 8192 parti per milione (ppm) e la concentrazione di TVOC (composto organico volatile totale) in un intervallo compreso tra 0 e 1187 parti per miliardo (ppb).

Il BH1750, sensore scelto per rilevare la luminosità, offre una precisione di circa ±20%, generando misurazioni sufficientemente precise. Possiamo, inoltre, alimentare il sensore con i 3,3V o i 5V, richiedendo corrente fino a circa 0.12 mA e questo lo rende perfetto per sensori IOT sempre accesi o per applicazioni su ESP32 alimentati a batteria o pannello solare. Questa combinazione di precisione, facilità d’uso e basso costo lo rende ideale per progetti DIY basati su microcontrollori e ambienti automatizzati.

Nel progetto adoperiamo anche un modulo di tensione in DC, che utilizza un partitore resistivo progettato per ridurre la tensione di ingresso di un fattore cinque. Ciò significa che se al terminale si applica una tensione di 25 V, in uscita verso il microcontrollore ne arriveranno soltanto 5 V, rientrando così nei limiti accettabili da Arduino. Nel caso di un sistema basato su ESP32 o altri dispositivi a 3,3 V, il limite massimo si riduce proporzionalmente a 16,5 V. Il modulo in esame, sarà collegato alla batteria Li-Po da 3,7V che alimenterà la dev-board nelle ore serali, quando il pannello solare non potrà essere adoperato.

L’anemometro funziona grazie a un sensore Hall che rileva il passaggio del magnete al neodimio fissato alle pale rotanti. Quando il vento fa girare l’asse, il cuscinetto a sfera (preso da un fidget spinner ) riduce l’attrito, permettendo una rotazione fluida; ogni passaggio del magnete davanti al sensore genera un impulso, che può essere convertito in velocità del vento in base alla frequenza di rotazione. Abbiamo adoperato la stampante 3D per realizzare le pale ed il corpo dell’anemometro [LINK].
Per gestire l’alimentazione alla scheda, usando il pannello solare e la batteria, abbiamo scelto un solar power manager che offre compatibilità universale, rendendolo perfetto per progetti IoT e di prototipazione. Grazie alla versatilità di alimentazione, supporta pannelli solari da 6V a 24V e ricarica tramite Type-C da 5V/3A. L’efficienza MPPT ottimizza l’energia prodotta dal pannello solare, mentre i LED di stato consentono di monitorare facilmente il funzionamento e la carica della batteria. Inoltre, i circuiti di protezione integrati assicurano un utilizzo sicuro e affidabile in ogni condizione.
La nostra stazione meteo possiede una pannello solare da 12V, con una potenza di picco di 12W. Questo è un pannello solare adatto a gestire progetti piccoli come questo, in quanto raggiungendo 1 Ampere di corrente, riesce a alimentare il progetto e caricare la batteria. Difatti, la nostra stazione, fuori dal deep sleep, arriva a richiedere 0,052A.
La batteria che accumulerà l’energia nelle ore diurne è una Li-Po da 3,7V da 20000mAh (sono in realtà due batterie da 10000mAh collegate in parallelo), riutilizzate da un powerbank.

Dal punto di vista strutturale, la parte elettrica della stazione meteo verrà ospitata dentro una scatola di derivazione per esterni 100×150 mm, fissata ad un bastone di legno con nastro forato da 12 mm.

All’interno della scatola, troviamo la batteria ed il PCB realizzato da PCBWay, dove alloggiare la BPI-Leaf-S3, i morsetti per i cavi dei sensori e il solar power manager. Il file Gerber del progetto è disponibile gratuitamente su GitHub a questo LINK.
I sensori di rilevamento ambientale, invece, verranno ospitati all’interno di un radiatore, stampato anche esso in PLA con la stampante 3D [LINK], e collocati dentro un PCB 2 x 8 cm, saldando a mano un pin header femmina e i cavi per la connessione elettrica e dati. Per tenere ferme le parti del radiatore, abbiamo usato 3 viti M4 da 75mm e 3 bulloni da 4mm. L’intero radiatore è stato poi bloccato al bastone con un morsetto per antenna.
Tutti i collegamenti sono stati poi effettuati con un cavo telefonico quadripolare, recuperato da un vecchio scatolone di cavi. Non manca l’utilizzo di qualche vite e un po’ di silicone per essere certi che non entri acqua dove abbiamo praticato dei fori nella scatola di derivazione.
Di seguito riportiamo la lista componenti su Amazon:
- Banana Pi BPI-Leaf-S3: https://amzn.to/4hukn4R
- BME280: https://amzn.to/3Lv2Hdd
- CCS811: https://amzn.to/42XWkoX
- BH1750: https://amzn.to/47FMaMe
- Sensore Hall: https://amzn.to/4quTSQN
- Modulo Tensione: https://amzn.to/4qz3XfK
- Magneti Neodimio: https://amzn.to/49ncfAZ
- Solar Power Manager: https://amzn.to/49j2sfd
- Batteria 3,7V Li-Po: https://amzn.to/49lvB9y
- Pannello Solare: https://amzn.to/3JgVH3d
- Scheda forata 2×8: https://amzn.to/47wZGRc
- Scatola derivazione: https://amzn.to/47s1hri
- Nastro Forato: https://amzn.to/4obvnqk
- Viti M4 75mm: https://amzn.to/479A5yL
- Dadi M4: https://amzn.to/479A5yL
- Terminali a vite (2/3/4 pin): https://amzn.to/4nwlMsN
- Pin header femmina: https://amzn.to/4ofK7EE
Lista componenti su Aliexpress:
- Banana Pi BPI-Leaf-S3: https://s.click.aliexpress.com/e/_c2y8mup1
- BME280: https://s.click.aliexpress.com/e/_c3tuvpeP
- CCS811: https://s.click.aliexpress.com/e/_c4MzRPlH
- BH1750: https://s.click.aliexpress.com/e/_c4tPoIX5
- Sensore Hall: https://s.click.aliexpress.com/e/_c3nWizPD
- Modulo Tensione: https://s.click.aliexpress.com/e/_c4Dkoq2L
- Magneti Neodimio: https://s.click.aliexpress.com/e/_c4Dkoq2L
- Solar Power Manager: https://s.click.aliexpress.com/e/_c3fSAVTh
- Batteria 3,7V Li-Po: https://s.click.aliexpress.com/e/_c4aYpQr9
- Pannello Solare: https://s.click.aliexpress.com/e/_c34YFM9H
- Scheda forata 2×8: https://s.click.aliexpress.com/e/_c4nvbuDZ
- Scatola derivazione: https://s.click.aliexpress.com/e/_c3AMcF8x
- Nastro Forato: https://s.click.aliexpress.com/e/_c3SELSlv
- Viti M4 75mm: https://s.click.aliexpress.com/e/_c4NOX3BD
- Dadi M4: https://s.click.aliexpress.com/e/_c4KaXIND
- Terminali a vite (2/3/4 pin): https://s.click.aliexpress.com/e/_c457BywL
- Pin header femmina: https://s.click.aliexpress.com/e/_c3mQGerV
Collegamenti
Partendo dai collegamenti elettrici, il Solar Power Manager è dotato di 3 terminali a due viti:
- Nel terminale riportante IN+ e IN- vanno collegati i cavi del pannello solare, rispettivamente il positivo in IN+ ed il negativo in IN-
- Il terminale con i morsetti Vcc e GND indicano i connettori a 5V che servono per alimentare la scheda e i sensori
- Il terminale coi morsetti Bat+ e Bat- indicano i corrispettivi positivo e negativo della batteria.
I cavi della batteria vanno anche collegati altrove, pertanto abbiamo bisogno di prolungarli fino alla morsettiera del partitore di tensione (modulo tensione), collegando il GND al negativo della batteria, mentre il positivo al terminale Vcc.
Per quanto riguarda la BPI-Leaf-S3 e i sensori, usiamo i pin 15 (SDA) e 16 (SCL), per collegare in parallelo il sensore BME280, BH1750 e CCS811. Di quest’ultimo, ricordiamoci di connettere il pin WAK al GND. Tutti i sensori con interfaccia I2C saranno alimentati a 5V.

Il sensore Hall, anch’esso alimentato a 5V, verrà connesso al pin 4 della ESP32. Il modulo di tensione, alimentato invece a 3,3V, sarà connesso alla scheda al pin 2.

Codice
Questo è il codice per configurare una Banana Pi BPI-Leaf_s3 per leggere lo stato dei sensori e inviare tutto a Home Assistant tramite ESPHome. La stazione meteo sarà accessibile in rete tramite Wi-Fi e potrà essere aggiornata via OTA (Over-The-Air) senza bisogno di connessione fisica. Potete scaricarlo a questo LINK.
All’inizio, il codice definisce il nome del progetto, sia quello tecnico (“stazione-meteo-esp32”) che quello più leggibile per Home Assistant (“Stazione Meteo ESP32”).
esphome:
name: stazione-meteo-esp32
friendly_name: Stazione Meteo ESP32
Poi si specifica che il microcontrollore utilizzato è un ESP32-S3 e che il firmware verrà compilato usando il framework Arduino, che è più semplice e supportato rispetto ad altre alternative come ESP-IDF.
esp32:
board: esp32-s3-devkitc-1
framework:
type: arduino
Il codice attiva il logger, che serve a registrare gli eventi e inviare messaggi di debug. Inoltre, viene attivata l’API di ESPHome, che permette a Home Assistant di comunicare con il dispositivo in modo sicuro grazie a una chiave di crittografia.
logger:
api:
encryption:
key: "EzeTZyss1nhIhBVgbHtDWP329yQSXVyKC29bg8yVUAE="
Per evitare di dover collegare il dispositivo fisicamente ogni volta che si vuole aggiornare il firmware, viene attivata la modalità OTA (Over-The-Air), con una password di sicurezza.
ota:
- platform: esphome
password: "394cd9fd203e7fc97d769ede1da8ea58"
Per collegarsi alla rete, il codice usa le credenziali Wi-Fi salvate nei secrets di ESPHome (file separato non visibile nel codice). Se la connessione fallisce, il dispositivo crea un hotspot Wi-Fi di emergenza (“Stazione-Meteo-Esp32”) con una password predefinita, in modo che sia possibile riconfigurarlo. Inoltre, è presente la funzione captive portal, che permette di riconfigurare il Wi-Fi direttamente da un browser in caso di problemi di connessione.
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
ap:
ssid: "Stazione-Meteo-Esp32"
password: "NVlVvfzgZwlp"
captive_portal:
Alla ESP32 abbiamo connesso in parallelo 3 sensori con interfaccia I2C (BME280, BH17050 e CCS811), pertanto abbiamo bisogno di dichiarare i pin SDA e SCL.
i2c:
sda: GPIO15
scl: GPIO16
scan: true
Andiamo a dichiarare i nostri sensori con interfaccia I2C, settando per ognuno un nome, il corretto indirizzo e update (2 secondi). Non spediamo troppe parole su questi sensori, giacché li abbiamo visti singolarmente. Ricordiamo che ci serviranno per rilevare temperatura, umidità, pressione, luminosità, anidride carbonica e composti organici volatili.
sensor:
- platform: bme280_i2c
temperature:
name: "Temperatura"
oversampling: 16x
pressure:
name: "Pressione"
humidity:
name: "Umidità"
address: 0x76 # 0x77 se il sensore ha un altro indirizzo
update_interval: 2s
- platform: bh1750
name: "Luminosità"
address: 0x23
update_interval: 2s
- platform: ccs811
eco2:
name: "eCO2"
tvoc:
name: "TVOC"
address: 0x5A
update_interval: 2s
Passiamo ora a dichiarare il partitore di tensione, per misurare la tensione della batteria e creare un valore in percentuale per averne una lettura più semplice. A tale scopo, è doveroso chiarire che le batterie Li-Po hanno una tensione di carica massima a 4,2V e minima a 3,0,V valori che useremo per determinarne lo stato di carica. Consci dei valori di minimo e massimo, rilevando lo stato della tensione attuale, possiamo ottenere un valore in percentuale, leggibile dall’utente.
- platform: adc
pin: GPIO2
name: "Tensione Batteria"
id: battery_voltage
unit_of_measurement: "V"
icon: "mdi:flash"
attenuation: 12db
update_interval: 20s
accuracy_decimals: 2
filters:
- multiply: 5.0 # partitore resistivo
- platform: template
name: "Batteria (%)"
unit_of_measurement: "%"
icon: "mdi:battery"
update_interval: 10s
lambda: |-
if (id(battery_voltage).state >= 4.2) {
return 100;
} else if (id(battery_voltage).state <= 3.0) {
return 0;
} else {
// mappa linearmente tra 3.0V e 4.2V
return (id(battery_voltage).state - 3.0) * 100.0 / (4.2 - 3.0);
}
Una parte particolarmente ostica riguarda la configurazione dell’anemometro, per misurare la velocità del vento in Km/h. L’anemometro in questione non misura direttamente i km/h, ma invia un impulso elettrico ogni volta che compie una rotazione, d’altro canto l’ESP32 deve quindi contare questi impulsi e convertirli in una misura di velocità del vento. Con pulse_meter comunichiamo ad ESPHome che il sensore funziona tramite conteggio di impulsi ed ogni impulso elettrico rappresenta un evento fisico (una rotazione completa). Il sensore Hall, connesso al pin 4, riceve il segnale (input: true), attiva la resistenza in pullup interna (pullup: true). Il controllo sulle rotazioni viene compiuto entro 60 secondi, oltre i quali, se non ci sono segnali, l’anemometro risulterà fermo. Ad ogni giro, per evitare false lettura, viene impostata un filtro di 100 ms (internal_filter: 100ms). Infine, adoperando il fattore di calibrazione (0.18), convertiamo il numero di rotazioni in Km/h, ottenendo così la velocità del vento.
- platform: pulse_meter
pin:
number: GPIO4
mode:
input: true
pullup: true # attiva la resistenza di pull-up interna
name: "Velocità Vento"
unit_of_measurement: "Km/h"
icon: "mdi:weather-windy"
timeout: 60s
accuracy_decimals: 2
internal_filter: 100ms # ignora impulsi troppo ravvicinati (antirimbalzo)
filters:
- multiply: 0.18
Abbiamo anche generato un sensore di conteggio degli impulsi per verificare che non ci siano false letture.
total:
name: "Impulsi Vento Totali"
unit_of_measurement: "impulsi"
accuracy_decimals: 0
Concludiamo il codice con il deep sleep, mandando a dormire la scheda per 30 minuti e riattivandola solo per 2 minuti.
deep_sleep:
run_duration: 2min
sleep_duration: 30min
Salvate e verificate con Validate se il codice è stato scritto correttamente.

Collegate la ESP32 al computer tramite cavo USB, e cliccate su Install.

Dovrebbe essere arrivata una notifica sulla plancia. In ogni caso, per integrarlo andate su Impostazioni -> Dispositivi e servizi e apparirà il dispositivo Stazione Meteo ESP32 da integrare.

Conclusa l’installazione, integriamo il device su Home Assistant. Possiamo così monitorare le rilevazioni ambienti della nostra stazione meteo, creando automazioni ad essa collegate, come ad esempio l’accensione delle luci esterne quando la luminosità sarà bassa o l’invio di messaggi tramite Telegram.
alias: Stazione Meteo
description: ""
triggers:
- minutes: "0"
trigger: time_pattern
conditions: []
actions:
- data:
message: >
Ciao, la Temperatura è di {{
states('sensor.stazione_meteo_esp32_temperatura') | float | round(2)
}}°C,
la Pressione è di {{ states('sensor.stazione_meteo_esp32_pressione') |
float | round(2) }} hPa
e l'Umidità è del {{ states('sensor.stazione_meteo_esp32_umidita') |
float | round(2) }}%.
Il vento soffia a {{
states('sensor.stazione_meteo_esp32_velocita_vento') | float | round(2)
}} Km/h
e i livelli di CO₂ nell'aria sono di {{
states('sensor.stazione_meteo_esp32_eco2') | int }} ppm.
action: telegram_bot.send_message
mode: single
























