CO2-Ampel mit ESPHome und SCD41: Lüften erinnern

CO2-Ampel selber bauen: ESP32 und SCD41 mit ESPHome in Home Assistant einbinden, Offset und Höhe einstellen und per Automation ans Lüften erinnern.

Stand
Lesezeit
9 Min.
Blatt
53 von 54
Thema
ESPHome
CO2-Ampel mit ESPHome und SCD41: Lüften erinnern

Werbung / Affiliate-Links: Mit * markierte Links sind Affiliate-Links. Beim Kauf über diese Links erhalten wir eine kleine Provision — für dich ändert sich am Preis nichts. Als Amazon-Partner verdienen wir an qualifizierten Verkäufen.

Im Home-Office oder im Kinderzimmer steigt der CO2-Gehalt bei geschlossenem Fenster schnell an. Du merkst es erst, wenn die Luft schon stickig ist. Mit einem ESP32, einem SCD41 und ESPHome baust du dir eine CO2-Ampel, die ihre Werte an Home Assistant meldet und dich per Push ans Lüften erinnert. Die Anleitung zeigt Verkabelung, Konfiguration, die wichtigen Kalibrier-Einstellungen und eine Erinnerung mit Hysterese.

Was du für die CO2-Ampel brauchst

Der SCD41 von Sensirion misst CO2 photoakustisch und liefert zusätzlich Temperatur und relative Feuchte. Laut Sensirion-Produktseite und Datenblatt arbeitet er mit 2,4 bis 5,5 V Versorgung und spricht I²C unter der Adresse 0x62.

  • Mikrocontroller: Ein ESP32-Board wie das AZDelivery ESP32 Dev Kit C*, das auch in unserer Anleitung zu ESP32 und ESPHome die Grundlage ist.
  • Sensor: Ein fertiges Breakout, zum Beispiel das Adafruit SCD-41 mit STEMMA QT/Qwiic*. Das ESP32 Dev Kit C hat keinen Qwiic-Anschluss. Du verbindest das Modul deshalb mit vier Leitungen an den Pins oder nimmst ein Qwiic-auf-Pin-Adapterkabel. Es gibt viele No-Name-Module mit dem gleichen Chip, achte darauf, dass wirklich SCD41 (nicht SCD40) auf der Platine steht.
  • Strom: Ein USB-Netzteil mit Kabel. Der Aufbau läuft mit Kleinspannung, am 230-V-Netz arbeitest du nicht.

Den Unterschied der beiden Chips legt das Datenblatt fest. Der SCD40 ist laut Sensirion für 400 bis 2000 ppm spezifiziert (±(50 ppm + 5 % vom Messwert)). Der SCD41 deckt 400 bis 5000 ppm ab, bei 400 bis 1000 ppm mit ±(50 ppm + 2,5 % vom Messwert). Für ein Wohnzimmer oder Büro reicht der SCD40 oft aus. Der SCD41 hat mehr Reserve und den zusätzlichen single_shot-Modus. Die Genauigkeitsangaben gelten laut Datenblatt unter definierten Bedingungen (25 °C, 50 % rF, 1013 mbar); dein Raum weicht davon ab.

So haben wir verglichen: Kriterien waren Messbereich, Genauigkeit und die verfügbaren Betriebsmodi. Datenbasis sind das Sensirion-Datenblatt und die ESPHome-Dokumentation. Die Sensoren haben wir nicht selbst getestet.

Verkabelung am ESP32

Beim ESP32 sind GPIO21 (SDA) und GPIO22 (SCL) die üblichen I²C-Pins. Verbinde so:

SCD41-ModulESP32
VIN (oder 3V3)3V3
GNDGND
SDAGPIO21
SCLGPIO22

Prüfe die Beschriftung deines Moduls und die Pinbelegung deines Boards, sie unterscheidet sich je nach Hersteller. Auf dem Sensor sitzt eine weiße Membran: Sie darf nicht entfernt oder beschädigt werden, so steht es in der ESPHome-Dokumentation. Fass sie nicht an und halte sie sauber.

ESPHome-Konfiguration für den SCD41

Lege in der ESPHome-App von Home Assistant ein neues Gerät an (Schritt für Schritt im Artikel zur ESPHome-Einbindung). Dann ergänzt du:

i2c:
  sda: GPIO21
  scl: GPIO22
  scan: true

sensor:
  - platform: scd4x
    id: scd41
    address: 0x62
    update_interval: 60s
    measurement_mode: periodic
    temperature_offset: 4
    altitude_compensation: 100
    automatic_self_calibration: true
    co2:
      name: "CO2"
      id: co2_ppm
      filters:
        - timeout: 3min
    temperature:
      name: "Temperatur"
    humidity:
      name: "Luftfeuchtigkeit"

text_sensor:
  - platform: template
    name: "CO2-Ampel"
    update_interval: 60s
    lambda: |-
      if (!id(co2_ppm).has_state() || isnan(id(co2_ppm).state)) return {"Kein Wert"};
      if (id(co2_ppm).state < 1000) return {"Grün"};
      if (id(co2_ppm).state <= 2000) return {"Gelb"};
      return {"Rot"};

binary_sensor:
  - platform: template
    name: "CO2 hoch"
    id: co2_hoch
    lambda: |-
      if (!id(co2_ppm).has_state() || isnan(id(co2_ppm).state)) return false;
      if (id(co2_ppm).state > 1000) return true;
      if (id(co2_ppm).state < 800) return false;
      return id(co2_hoch).state;
    filters:
      - delayed_on: 5min

Den üblichen WLAN-, API- und OTA-Block legt ESPHome beim Anlegen des Geräts selbst an. Der Filter timeout: 3min setzt den CO2-Wert auf NaN, wenn der SCD41 drei Minuten lang keinen neuen Messwert liefert. Bei einem Lesefehler veröffentlicht die scd4x-Komponente sonst keinen neuen Wert, und der letzte bleibt stehen. Ampel und Binärsensor zeigen dann „Kein Wert“ bzw. „aus“, statt mit einem veralteten Wert weiterzuarbeiten. Die Schwellen der Ampel stammen aus den Leitwerten des Umweltbundesamts: unter 1000 ppm hygienisch unbedenklich, 1000 bis 2000 ppm hygienisch auffällig, über 2000 ppm hygienisch inakzeptabel.

Flashen: Beim ersten Mal per USB am Rechner, dabei hängt der Aufbau an keiner weiteren Spannungsquelle. Spätere Änderungen gehen per OTA über WLAN.

Messmodus und Messintervall

Laut ESPHome-Doku liefert periodic (Standard) alle 5 Sekunden einen Wert, low_power_periodic alle 30 Sekunden. single_shot gibt es nur beim SCD41, die Messung startet dann zu jedem update_interval. Bei Netzbetrieb per USB nimmst du periodic. Für eine Lüftungserinnerung genügt update_interval: 60s.

temperature_offset: warum 4 °C nicht für jeden Aufbau passen

Der Sensor erwärmt sich im Betrieb selbst, und der ESP32 heizt die Umgebung zusätzlich auf. ESPHome setzt deshalb standardmäßig temperature_offset: 4 (in °C). Der Offset korrigiert die Temperatur und die davon abgeleitete Feuchte, nicht den CO2-Wert. Passt der Standard bei deinem Gehäuse nicht, vergleiche die Temperatur mit einem Referenzthermometer im selben Raum und passe den Wert an. Eine Orientierung gibt auch das Datenblatt: Die Temperaturgenauigkeit liegt dort bei typisch ±0,8 °C zwischen 15 und 35 °C.

Höhen- und Druckkompensation

CO2-Sensoren dieser Bauart hängen vom Luftdruck ab. Du hast zwei Wege:

  • altitude_compensation: 100 mit deiner Höhe über Meereshöhe in Metern. Das ist einfach und reicht für den Alltag.
  • ambient_pressure_compensation in mbar oder ambient_pressure_compensation_source mit der ID eines Drucksensors, etwa einem BME280. Ist der Druck gesetzt, ignoriert ESPHome die Höhe.

Trage in jedem Fall etwas ein, wenn du deutlich über oder unter Meereshöhe wohnst.

Automatische Selbstkalibrierung (ASC)

automatic_self_calibration ist standardmäßig aktiv. Der Algorithmus geht laut Sensirion-Datenblatt davon aus, dass der Sensor mindestens einmal pro Woche Luft mit 400 ppm sieht. In einem Raum, der nie gründlich gelüftet wird, kann die ASC den Sensor falsch einpegeln. Dann setzt du automatic_self_calibration: false und kalibrierst bei Bedarf manuell mit der Aktion scd4x.perform_forced_calibration. Damit du sie aus Home Assistant aufrufen kannst, ergänzt du im vorhandenen api:-Block eine eigene Aktion (Beispiel nach der ESPHome-Doku):

api:
  actions:
    - action: co2_kalibrieren
      variables:
        referenz_ppm: int
      then:
        - scd4x.perform_forced_calibration:
            value: !lambda 'return referenz_ppm;'
            id: scd41

Der Sensor soll davor laut Doku mehr als drei Minuten im später genutzten Messmodus laufen, in einer Umgebung mit gleichmäßiger, konstanter CO2-Konzentration. Danach rufst du in den Entwicklerwerkzeugen unter „Aktionen“ die neue ESPHome-Aktion des Geräts mit dem Referenzwert in ppm auf.

Einbindung in Home Assistant

Nach dem Flashen taucht das Gerät unter Einstellungen → Geräte & Dienste als entdecktes ESPHome-Gerät auf. Bestätige es mit dem Verschlüsselungsschlüssel aus der ESPHome-App. Danach hast du die Entitäten für CO2, Temperatur, Feuchte und die Ampel. Für das Dashboard eignet sich eine Verlaufsgrafik für den CO2-Wert; die Ampel-Entität zeigst du als Kachel. Wie du Dashboards aufbaust, steht im Artikel zum Home-Assistant-Dashboard.

Lüftungserinnerung mit Hysterese

Ein einfacher Trigger bei 1000 ppm nervt: Pendelt der Wert um die Schwelle, kommen Dutzende Meldungen. Deshalb steckt die Logik schon im Binärsensor „CO2 hoch“ aus der ESPHome-Konfiguration oben. Er schaltet erst ein, wenn der Wert fünf Minuten lang durchgehend über 1000 ppm liegt. Fällt er in dieser Zeit auf 1000 ppm oder darunter, verwirft der Filter delayed_on den Einschaltvorgang, und die fünf Minuten beginnen beim nächsten Überschreiten neu. So beschreibt die ESPHome-Doku zu Binärsensor-Filtern den Filter. Aus geht der Sensor erst unter 800 ppm. Dazwischen behält er seinen Zustand, das ist die Hysterese.

Der Vorteil: Der Zähler läuft auf dem ESP32. Ein Neustart von Home Assistant setzt ihn nicht zurück. Bei einem for: in einer Automation wäre das anders, laut Home-Assistant-Doku übersteht for weder einen Neustart noch das Neuladen der Automationen. Einen Helfer brauchst du so nicht.

Die Entitäts-ID unten ist ein Beispiel und setzt den Gerätenamen co2-ampel voraus. Setze die tatsächlichen Namen aus deiner Installation ein, den Notify-Dienst findest du in den Entwicklerwerkzeugen unter „Aktionen“.

alias: CO2 – Lüften erinnern
triggers:
  - trigger: state
    entity_id: binary_sensor.co2_ampel_co2_hoch
    to: "on"
  - trigger: time
    at: "07:00:00"
  - trigger: homeassistant
    event: start
conditions:
  - condition: state
    entity_id: binary_sensor.co2_ampel_co2_hoch
    state: "on"
  - condition: time
    after: "07:00:00"
    before: "22:00:00"
actions:
  - action: notify.mobile_app_dein_handy
    data:
      title: "Zeit zum Lüften"
      message: "CO2 liegt bei {{ states('sensor.co2_ampel_co2') }} ppm."
mode: single

Achte auf die Logik der drei Trigger. Der erste meldet, sobald der Binärsensor einschaltet. Er reagiert laut Doku zum State-Trigger auch auf den Wechsel von unavailable zu „an“, etwa wenn sich der ESP32 nach einem Verbindungsabbruch zurückmeldet. Der Zeit-Trigger um 7 Uhr deckt den Fall ab, dass der Sensor schon nachts eingeschaltet hat und die Meldung am Zeitfenster gescheitert ist. Der Start-Trigger prüft nach einem Neustart von Home Assistant, ob der Sensor bereits an ist. Die Bedingungen gelten für alle drei Wege gleich. Nach einem Neustart oder Verbindungsabbruch kann die Erinnerung deshalb ein weiteres Mal kommen, wenn die Luft noch schlecht ist. Verliert der ESP32 die Verbindung, wird der Binärsensor unavailable. Liefert der SCD41 keine Messwerte mehr, schaltet er über den timeout-Filter auf „aus“. In beiden Fällen verhindert die Bedingung „an“ eine Meldung. Wie du Nachrichten auf mehrere Geräte oder per Telegram schickst, zeigt der Artikel zu Benachrichtigungen mit Telegram und Pushover. Grundlagen zu Triggern und Bedingungen findest du in den Automationen für Einsteiger.

Der gleiche Sensor ergänzt übrigens das Thema Feuchte: Wie du mit Temperatur und Luftfeuchte Schimmel vorbeugst, steht in Schimmel vermeiden mit Home Assistant. Die Feuchtewerte des SCD41 taugen dafür als Anhaltspunkt, laut Datenblatt mit ±6 % rF bei 15 bis 35 °C und 20 bis 65 % rF, außerhalb davon typisch ±9 % rF. Eine genaue Messung ist das nicht.

Grenzen: Orientierungshilfe, kein Messgerät

Der Aufbau ist kein zertifiziertes Messgerät und kein Ersatz für eine Raumluftprüfung. Die Genauigkeit stammt aus den Herstellerangaben und gilt für ideale Bedingungen. Platziere den Sensor auf Kopfhöhe, mit Abstand zu Fenster, Tür, Heizkörper und deinem Atem. Direkt davor gehaltene Luft verfälscht die Werte.

FAQ

Welchen CO2-Wert sollte ich als Schwelle nehmen? Das Umweltbundesamt stuft Werte unter 1000 ppm als unbedenklich ein, zwischen 1000 und 2000 ppm als auffällig. 1000 ppm ist deshalb ein üblicher Auslöser für eine Erinnerung.

SCD40 oder SCD41? Beide arbeiten mit der gleichen ESPHome-Komponente scd4x. Der SCD41 deckt laut Datenblatt mehr Bereich ab (bis 5000 ppm) und kann single_shot. Für Wohnräume genügt oft der SCD40.

Muss die weiße Membran frei bleiben? Ja. Laut ESPHome-Doku darf sie nicht entfernt oder manipuliert werden.

Stimmt die Temperatur? Nicht ohne Anpassung. Der Sensor erwärmt sich selbst, deshalb gibt es temperature_offset. Vergleiche mit einem Referenzthermometer.

Fazit

Die CO2-Ampel eignet sich für alle, die in Home Assistant ohnehin ESPHome nutzen oder einsteigen wollen und für Home-Office oder Kinderzimmer eine Erinnerung zum Lüften brauchen. Das Projekt braucht keine Programmierkenntnisse, nur etwas YAML und vier Kabel. Wer einen fertigen, zertifizierten Sensor mit Gehäuse sucht, ist mit einem Fertiggerät besser bedient. Wichtig bleibt: Das Ergebnis ist eine Orientierung, die dich ans Fenster schickt, mehr nicht.

Autor
Philipp
Themen
Home Assistant, ESP32, Zigbee

Schreibt über Home Assistant, ESP32 und alles, was das Smart Home smarter macht.

Dieser Artikel wurde mit KI-Unterstützung erstellt; Angaben werden gegen offizielle Dokumentation und Herstellerangaben geprüft. Wie die Artikel entstehen