Stazione meteo IoT con ESP32 e BME280: dati in tempo reale su Home Assistant

Pubblicato il 17/07/2026 IoT

Una stazione meteo domestica con dati in tempo reale in Home Assistant è uno dei progetti IoT più soddisfacenti da costruire: componenti economici, poche righe di firmware, e un risultato che usi davvero ogni giorno per decidere se prendere l'ombrello. Il cuore del progetto è il sensore BME280 (Bosch), che in un solo package misura temperatura, umidità relativa e pressione atmosferica via I2C.

Collegamento hardware

Il BME280 comunica via I2C, quindi bastano quattro fili verso l'ESP32:

  • VCC → 3.3V (attenzione: molti moduli BME280 economici NON sono 5V-tolerant)
  • GND → GND
  • SCL → GPIO 22 (default I2C su molte board ESP32 DevKit)
  • SDA → GPIO 21

Per un'installazione esterna, il sensore va protetto dalla pioggia diretta ma non sigillato ermeticamente: serve comunque un minimo di ricircolo d'aria per una lettura di umidità/pressione realistica — uno schermo tipo Stevenson-screen in miniatura, anche stampato in 3D, risolve il problema.

Firmware: lettura del sensore

#include <Wire.h>
#include <Adafruit_BME280.h>

Adafruit_BME280 bme;

void setup() {
  Serial.begin(115200);
  Wire.begin(21, 22);
  if (!bme.begin(0x76)) {   // alcuni moduli usano 0x77: prova entrambi
    Serial.println("BME280 non trovato");
    while (1) delay(1000);
  }
}

void loop() {
  float temp = bme.readTemperature();          // °C
  float hum  = bme.readHumidity();              // %
  float pres = bme.readPressure() / 100.0F;      // hPa
  Serial.printf("T=%.1f°C  U=%.1f%%  P=%.1f hPa\\n", temp, hum, pres);
  delay(30000);
}

Pubblicazione via MQTT

Home Assistant "auto-scopre" i sensori se pubblichi anche un messaggio di discovery MQTT una tantum, oltre ai dati periodici:

#include <PubSubClient.h>

WiFiClient espClient;
PubSubClient mqtt(espClient);

void pubblicaDiscovery() {
  mqtt.publish("homeassistant/sensor/meteo_giardino_temp/config",
    "{\\"name\\":\\"Temperatura giardino\\",\\"state_topic\\":\\"meteo/giardino/temperatura\\","
    "\\"unit_of_measurement\\":\\"°C\\",\\"device_class\\":\\"temperature\\"}", true);
  // ripeti per umidita' e pressione con i rispettivi topic/device_class
}

void loop() {
  mqtt.loop();
  mqtt.publish("meteo/giardino/temperatura", String(bme.readTemperature(),1).c_str());
  mqtt.publish("meteo/giardino/umidita", String(bme.readHumidity(),1).c_str());
  mqtt.publish("meteo/giardino/pressione", String(bme.readPressure()/100.0F,1).c_str());
  delay(30000);
}

Il flag true nel publish del discovery imposta il messaggio come retained: resta memorizzato sul broker, così Home Assistant lo riceve anche se si riavvia dopo che l'ESP32 lo ha già pubblicato.

Calibrazione: il dettaglio che tutti saltano

Il BME280 misura la temperatura vicino ai propri componenti elettronici, che scaldano leggermente: in un case chiuso o vicino a un ESP32 attivo, la lettura può risultare 1-3°C sopra il reale. Confrontala con un termometro di riferimento e applica un offset software fisso in firmware, invece di fidarti ciecamente del valore grezzo — lo stesso principio vale per qualunque sensore di temperatura installato vicino a componenti che dissipano calore.

Alimentazione per installazione permanente

Per una stazione esterna alimentata a batteria, alterna letture ogni 30-60 secondi con un deep sleep tra un ciclo e l'altro: un ESP32 in deep sleep consuma pochi microampere contro le decine di milliampere della modalità attiva, trasformando una batteria che dura ore in una che dura mesi.