Raumklima-Sensor mit BME680 und ESPHome

Ein BME680 am ESP32 misst Temperatur, Luftfeuchte und Luftdruck – und merkt außerdem, wie verbraucht die Raumluft ist. Boschs Bibliothek BSEC2 macht daraus einen Luftqualitätsindex, mit dem Home Assistant ans Lüften erinnern kann. Der Aufbau dauert eine Stunde, danach braucht der Sensor ein bis zwei Tage, um seinen Raum kennenzulernen.
Überblick
Material: ESP32-Board, BME680-Breakout, vier Kabel, Home Assistant mit ESPHome.
Ergebnis: sieben Entitäten in Home Assistant – Temperatur, Luftfeuchte, Luftdruck, Luftqualität (IAQ) samt Bewertung in Worten, geschätztes CO₂ und VOC sowie die Angabe, wie verlässlich der IAQ-Wert gerade ist.
1 VerkabelnAufbau
Ziel: Sensor am I²C-Bus des ESP32.
| BME680 | ESP32 |
|---|---|
| VCC | 3V3 |
| GND | GND |
| SDA | GPIO 21 |
| SCL | GPIO 22 |
Die übrigen Pins (CS, SDO) sind auf gängigen Breakout-Boards bereits für I²C beschaltet.

2 Konfiguration aufspielenAufbau
Ziel: ESPHome-Firmware mit BSEC2 auf dem ESP32.
WarumBSEC2 statt eigener Formel?
Der Sensor selbst liefert nur einen Gaswiderstand: hoch bei sauberer, niedrig bei belasteter Luft. Was „sauber“ ist, hängt vom Raum ab. BSEC2 lernt diese Basislinie und skaliert den Index daran – eine feste Formel bleibt dagegen dauerhaft bei einem Wert um 20 und reagiert kaum.
Zuerst eine secrets.yaml mit wifi_ssid, wifi_password, ap_password und api_key anlegen. Dann die Gerätekonfiguration:
esphome:
name: raumklima
friendly_name: Raumklima
esp32:
variant: esp32
framework:
type: esp-idf
logger:
api:
encryption:
key: !secret api_key
ota:
- platform: esphome
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
ap:
ssid: "Raumklima Fallback Hotspot"
password: !secret ap_password
captive_portal:
i2c:
- id: i2c_1
sda: 21
scl: 22
scan: true # zeigt die gefundene Adresse im Log
bme68x_bsec2_i2c:
i2c_id: i2c_1
address: 0x77 # SDO offen: 0x77, SDO an GND: 0x76
model: bme680
operating_age: 28d # für die erste Kalibrierung: 4d
sample_rate: LP # alle 3 s; ULP (5 min) kalibriert kaum
supply_voltage: 3.3V
temperature_offset: 0 # in Schritt 5 bestimmen
state_save_interval: 6h # Kalibrierung im Flash sichern
sensor:
- platform: bme68x_bsec2
temperature:
name: "Temperatur"
pressure:
name: "Luftdruck"
humidity:
name: "Luftfeuchte"
iaq:
name: "Luftqualität"
on_value:
- text_sensor.template.publish:
id: iaq_bewertung
state: !lambda |-
if (isnan(x)) return "unbekannt";
if (x <= 50) return "sehr gut";
if (x <= 100) return "gut";
if (x <= 150) return "leicht belastet";
if (x <= 200) return "mäßig belastet";
if (x <= 250) return "stark belastet";
if (x <= 350) return "sehr stark belastet";
return "extrem belastet";
co2_equivalent:
name: "CO2 (geschätzt)"
breath_voc_equivalent:
name: "VOC (geschätzt)"
text_sensor:
- platform: bme68x_bsec2
iaq_accuracy:
name: "Kalibrierung"
- platform: template
id: iaq_bewertung
name: "Luftqualität (Bewertung)"
update_interval: neverDen ersten Flash-Vorgang per USB erledigen, alle weiteren laufen per OTA.
3 In Home Assistant einbindenAufbau
Ziel: Messwerte als Entitäten in Home Assistant.
Das Gerät wird meist automatisch gefunden; sonst über Einstellungen → Geräte & Dienste → ESPHome hinzufügen.
4 Kalibrieren lassenEinregeln
Ziel: Kalibrierung steht auf 3 – Calibrated.
WarumWarum dauert das?
BSEC2 braucht einen Eindruck von sauberer und belasteter Luft, um die Basislinie festzulegen. Erst ab Stufe 3 wird der Zustand im Flash gespeichert – ein Neustart davor beginnt von vorn.
Den Sensor offen im Raum laufen lassen, ohne neu zu flashen oder neu zu starten. Hilfreich ist ein kurzer Geruchsreiz: ein Filzstift oder etwas Desinfektionsmittel für einige Sekunden in die Nähe, danach gründlich lüften. Ein fabrikneuer Sensor braucht zusätzlich bis zu 48 Stunden Einbrennzeit.
| Kalibrierung | Bedeutung |
|---|---|
| 0 – Stabilizing | Anlaufphase |
| 1 – Uncertain | Basislinie noch offen |
| 2 – Calibrating | Kalibrierung läuft |
| 3 – Calibrated | Werte belastbar |
5 Gehäuse und TemperaturkorrekturEinregeln
Ziel: Messwerte, die nicht von der Wärme des ESP32 verfälscht sind.
WarumWarum ein eigenes Fach?
Der ESP32 erwärmt sich im Betrieb um mehrere Grad. Sitzt der Sensor in seiner Nähe oder in seiner Abluft, misst er zu warm und zu trocken. Zudem erreicht ihn die Raumluft nur durch Diffusion – in stehender Luft reagiert er träge und kalibriert schlecht.
- Sensor in ein eigenes Fach, durch eine Wand vom ESP32 getrennt, unterhalb oder seitlich davon, nie darüber.
- Sensorfach mit großzügigen Öffnungen auf mindestens zwei Seiten, die Öffnung im Metalldeckel zur Raumluft.
- Gedruckte Gehäuse einige Tage auslüften lassen, bevor der Sensor einzieht – Ausgasungen verfälschen die Basislinie.
- Sonne, Heizung und Herd meiden.
Nach 1–2 Stunden im Gehäuse die Temperatur mit einem Referenzthermometer vergleichen und die Differenz als temperature_offset eintragen (z. B. -2.5). Der gespeicherte Kalibrierzustand bleibt beim erneuten Flashen erhalten.
Werte lesen
| IAQ | Bewertung |
|---|---|
| 0–50 | sehr gut |
| 51–100 | gut |
| 101–150 | leicht belastet |
| 151–200 | mäßig belastet |
| 201–250 | stark belastet |
| 251–350 | sehr stark belastet |
| über 350 | extrem belastet |
Aussagekräftiger als der einzelne Wert ist der Verlauf: Ein Anstieg zeigt zuverlässig, dass gelüftet werden sollte.
Fehlerbilder
| Beobachtung | Ursache | Abhilfe |
|---|---|---|
| IAQ bleibt bei etwa 50 | Kalibrierung läuft noch | weiterlaufen lassen (Schritt 4) |
| Kalibrierung bleibt auf Uncertain | gleichförmige Luft, Neustarts oder ULP | Geruchsreiz, keine Neustarts, LP |
| Temperatur mehrere Grad zu hoch | Wärme des ESP32 | trennen, temperature_offset (Schritt 5) |
| Sensor nicht gefunden | Adresse oder Verkabelung | I²C-Scan im Log, 0x76/0x77, SDA/SCL |
| IAQ nach Gehäuseeinbau unplausibel | Ausgasungen des Druckmaterials | auslüften, neu kalibrieren lassen |