SensorsMQTT

ESP32 + BME280 weather station over MQTT

Difficulty: easy · Time: ~1 hour · Cost: ~$6–8

This project measures temperature, humidity and air pressure and periodically publishes them to an MQTT broker (for example Mosquitto in Home Assistant). Between readings the ESP32 goes into deep sleep to save battery.

Parts

Wiring

BME280ESP32
VIN / VCC3V3
GNDGND
SDAGPIO21
SCLGPIO22

The I2C address is usually 0x76 (or 0x77 depending on the module). If the sensor isn't detected, run an I2C scanner sketch.

Libraries (Arduino IDE)

Source code

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

const char* WIFI_SSID = "your_wifi";
const char* WIFI_PASS = "your_password";
const char* MQTT_HOST = "192.168.1.10";
const uint16_t MQTT_PORT = 1883;

const uint64_t SLEEP_US = 5ULL * 60ULL * 1000000ULL;  // 5 minutes

Adafruit_BME280 bme;
WiFiClient net;
PubSubClient mqtt(net);

void goSleep() {
  WiFi.disconnect(true);
  esp_sleep_enable_timer_wakeup(SLEEP_US);
  esp_deep_sleep_start();
}

void setup() {
  Serial.begin(115200);
  Wire.begin(21, 22);
  if (!bme.begin(0x76)) {
    Serial.println("BME280 not found!");
    goSleep();
  }

  // "Forced" mode: measure once, then return to sleep, using less power
  bme.setSampling(Adafruit_BME280::MODE_FORCED);
  bme.takeForcedMeasurement();
  float t = bme.readTemperature();
  float h = bme.readHumidity();
  float p = bme.readPressure() / 100.0F;

  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  uint32_t t0 = millis();
  while (WiFi.status() != WL_CONNECTED && millis() - t0 < 15000) delay(100);
  if (WiFi.status() != WL_CONNECTED) goSleep();

  mqtt.setServer(MQTT_HOST, MQTT_PORT);
  if (mqtt.connect("esp32diy-tram1")) {   // add user/pass if your broker requires it
    char buf[32];
    snprintf(buf, sizeof buf, "%.2f", t); mqtt.publish("esp32diy/tram1/nhiet_do", buf, true);
    snprintf(buf, sizeof buf, "%.2f", h); mqtt.publish("esp32diy/tram1/do_am", buf, true);
    snprintf(buf, sizeof buf, "%.1f", p); mqtt.publish("esp32diy/tram1/ap_suat", buf, true);
    mqtt.loop();
    delay(100);  // give the packets time to leave
  }
  goSleep();
}

void loop() {}   // never reached

Home Assistant configuration

Add this to configuration.yaml (the MQTT integration must already be set up):

mqtt:
  sensor:
    - name: "Outdoor temperature"
      state_topic: "esp32diy/tram1/nhiet_do"
      unit_of_measurement: "°C"
      device_class: temperature
    - name: "Outdoor humidity"
      state_topic: "esp32diy/tram1/do_am"
      unit_of_measurement: "%"
      device_class: humidity
    - name: "Pressure"
      state_topic: "esp32diy/tram1/ap_suat"
      unit_of_measurement: "hPa"
      device_class: atmospheric_pressure
Tip: publish with retain = true so Home Assistant always has the latest value after a restart instead of waiting 5 minutes.

Next steps