Quick and Dirty Co² Sensor mit ESP32 und SCD41

User stellen ihre Haussteuerung vor

Moderator: Co-Administratoren

cloudman88
Beiträge: 115
Registriert: 26.10.2020, 11:32
System: Alternative CCU (auf Basis OCCU)
Hat sich bedankt: 12 Mal
Danksagung erhalten: 18 Mal

Quick and Dirty Co² Sensor mit ESP32 und SCD41

Beitrag von cloudman88 » 13.10.2021, 12:57

Quick and Dirty Co² Sensor mit ESP32 und SCD41

Noch mal ein CO² Beispiel – diesmal mit ESP32 und ESPHome

TLDR

ESP32 zusammen mit SCD41, BME280 und LEDs zu Signalisierung.
Der Sensorwert wird über HTTP in eine Homematic Systemvariable geschrieben.
Kosten ca. 70€

Vorteil: extrem einfach aufzubauen und MQTT / Webserver mit dabei.
Nachteil:
- Batteriebetrieb ist so nicht realistisch - USB Stromversorgung notwendig.
- keine Direktverknüpfung wie mit AskSin++ möglich.



Details

Nachdem mir der HmIP-SCTH230 nicht wirklich zusagt und ich auch nicht wüsste, wo ich ihn installieren sollte, habe ich für mich nach einer Alternative gesucht.

Als Sensor verwende ich den relativ neuen SCD41 von Sensiron (https://www.sensirion.com/fileadmin/use ... asheet.pdf). Der Sensor ist ziemlich klein, recht genau (: ±(40 ppm + 5 %) und hat bereits Temperatur und Luftfeuchtigkeit Kompensation an Board.
Im Gegensatz zu vielen anderen CO² Sensoren wird beim SCD4x "Photoacoustic sensing" statt NDIR verwendet und damit kann der Sensor sehr klein ausfallen. Wer mehr wissen möchte kann hier starten : https://www.sensirion.com/en/about-us/c ... echnology/

Lieferbar war nur das „Evaluation Kit SEK-SCD41“ für ca €55. Kein Schnäppchen allerdings kostet der nackte Sensor auch nur ein paar Euro weniger.

Als Protocol wird I²C benutzt.

Zusätzlich kann noch der Luftdruck von einem externen Sensor zur Erhöhung der Genauigkeit verwendet werden. Ich habe dafür einen BME 280 genommen – einfach deswegen, weil ich davon einige in meiner Bastelkiste habe.
Zur Visualisierung werden 6 LEDs angesteuert.

Statt den Code selbst zu schreiben, kommt ESPHome zum Einsatz. Meiner Meinung nach ist ESPHome eines der besten Frameworks für ESPxxx. Die Konfiguration wird in YAML definiert und daraus wird dann C++ generiert der mit Platform IO kompiliert wird. Im Gegensatz zu z.b. Tasmota ist deswegen nur der Code im Image der benötigt wird.

Natürlich könnte man auch CuxD oder ccuJack verwenden, aber für meine Zwecke reicht eine Systemvariable aus.

Aufbau:

ESP32-Dev Kit
PIN 21 zu SCD41 und BME280 SCL PIN
PIN 22 zu SCD41 und BME280 SDA PIN
PINS 18, 19, 23,25,26,32 jeweils zu 220K Widerstand und LED

Die BME280 Platine enthält bereits Pullup Widerstände. Ansonsten sollte man noch ca 15k Pullup für SDA und SCl verwenden.

Und so sieht mein „professionelles“ Design aus 😊
co2.png

Software

In Homematic muss einen Systemvariable vom Typ Zahl angelegt werden – damit ist auf der Homematic Seite alles erledigt.

Der große Vorteil von ESPHHome für mich ist, dass der Sensor so auch direkt in Home Assistent oder MQTT verwendet werden kann.

Die Luftdruck Kompensierung wird über das Attribut ambient_pressure_compensation_source: definiert. Hier wird der Sensor angegeben, der die aktuelle Luftdruckwerte an den SCD4x liefert
(Die Möglichkeit einen externen Sensor zu verwenden ist aktuell noch nicht offiziell implementiert – allerdings sollte https://github.com/esphome/esphome/pull/2493 demnächst durchgehen)

Mein eigener Code beschränkt sich auf die on_value Aktion für den CO² Sensor.
Je nach CO² Level werden die LEDs angesteuert und dann ein HTTP Request an die CCU geschickt um die Systemvariable zu aktualisieren. Dafür müssen nur die beiden Attribute hm_host und und hm_sysvar angepasst werden.
Die generierte URL sieht dann in etwa so aus:

Code: Alles auswählen

http://192.168.1.58:8181/any.exe?x=dom.GetObject("scd41-co2").State(630)

Wer weder MQTT noch Home Assitant im Einsatz hat kann „mqtt:“ und „api:“ enfernen.
Mit „web:“ wird ein einfacher Webserver auf Port bereitgestellt

So sieht die ESPHome Konfiguration aus

Code: Alles auswählen

substitutions:
  updates: 30s
  devicename: co2-sensor
  hm_host: 192.168.1.58
  hm_sysvar_co2: scd41-co2

esphome:
  name: ${devicename}

esp32:
  board: esp32dev
  framework:
    type: arduino

wifi:
  ssid: !secret wifi_sid
  password: !secret wifi_password

time:
  - platform: sntp
    id: sntp_time
    timezone: "CET-1CEST,M3.5.0,M10.5.0/3"
    servers: "de.pool.ntp.org"

# Enable logging
logger:
  level: DEBUG
## Optional 
api:
  password: !secret api_password
  reboot_timeout: 0s

ota:
  password: !secret ota_password

## Optional
mqtt:
  broker: 192.168.1.114

i2c:
  - id: bus_a
    sda: 21
    scl: 22
    scan: True

http_request:
  useragent: esphome/device
  id: httpget
  timeout: 10s

sensor:
  - platform: scd4x
    id: scd41
    i2c_id: bus_a
    altitude_compensation: 418m
    co2:
      name: co2
      id: co2
      on_value:
        then:
          - lambda: |-
              if (x > 400 ) id(led_g1).turn_on() ; else id(led_g1).turn_off();
              if (x > 650 ) id(led_g2).turn_on() ; else id(led_g2).turn_off();
              if (x > 800 ) id(led_y1).turn_on() ; else id(led_y1).turn_off();
              if (x > 1050 ) id(led_y2).turn_on() ; else id(led_y2).turn_off();
              if (x > 1300 ) id(led_r1).turn_on() ; else id(led_r1).turn_off();
              if (x > 1550 ) id(led_r2).turn_on() ; else id(led_r2).turn_off();

          - http_request.get:
              url: !lambda |-
                return ((std::string) "http://${hm_host}:8181/any.exe?x=dom.GetObject('${hm_sysvar_co2}').State(" + esphome::to_string(static_cast<uint16_t>(x)) + ")" );

    humidity:
      name: "Luftfeuchtigkeit"
      id: humidity
    temperature:
      name: "Raumtemperatur"
      id: temperature
    ambient_pressure_compensation_source: bme280_pressure
    update_interval: ${updates}

  - platform: bme280
    setup_priority: -15
    temperature:
      name: "BME280-Temperature"
      id: bme280_temperature
      oversampling: 1x
    pressure:
      name: "BME280-Pressure"
      id: bme280_pressure
      oversampling: 1x

    humidity:
      name: "BME280-Humidity"
      id: bme280_humidity
      oversampling: 1x
    address: 0x76
    update_interval: ${updates}

  - platform: wifi_signal
    name: "WiFi Signal"
    id: wifisignal
    update_interval: ${updates}

output:
  - platform: gpio
    pin: 23
    id: led_g1
  - platform: gpio
    pin: 19
    id: led_g2
  - platform: gpio
    pin: 18
    id: led_y1
  - platform: gpio
    pin: 32
    id: led_y2
  - platform: gpio
    pin: 25
    id: led_r1
  - platform: gpio
    pin: 26
    id: led_r2

# Example configuration entry
switch:
  - platform: restart
    name: "CO² Sensor Restart"

web_server:
  port:80

Jetzt muss man das ganz nur noch kompilieren und hochladen.

Beim ersten mal über die USB-COM Schnittstelle und ab dann kann auch direkt über das Netz aktualisiert werden.

Code: Alles auswählen

esphome run   ..\test\co2-sensor.yaml
Mehr zu esphome unter https://esphome.io/index.html



In Homematic sieht es dann so aus
hm.png
hm.png (5.24 KiB) 316 mal betrachtet

Und in Home Assitant:
ha.png

Erweiterungen

Sobald der bestellte BME688 eintrifft werde ich ihn statt dem BME280 einbauen um auch noch VOC Werte zu erhalten.
Die etwas krude Signalsierung mit den LEDs ist auch nicht wirklich der Hit . Ich bin noch am überlegen, was ich stattdessen verwenden könnte. ESPHome bietet da einige Optionen https://esphome.io/index.html#display-components

Dann muss ich mir noch über ein Gehäuse Gedanken machen und zumindest von Breadboard zu Lochraster wechseln.


Batteriebetrieb ist mit diesem Setup nicht wirklich eine Option, weil der ESP32 und die LEDs dafür zuviel Strom ziehen.
Wenn man allerdings die LEDs weglässt und statt dem ESP32-DevKitC ein Board mit niedrigerem Verbrauch verwendet (z.b. TinyPico) wäre zusammen mit deep-sleep Batteriebetrieb denkbar.


Viel Spaß falls es jemand nachbauen möchte :)

tloeffel
Beiträge: 435
Registriert: 13.09.2017, 05:11
Hat sich bedankt: 1 Mal
Danksagung erhalten: 9 Mal

Re: Quick and Dirty Co² Sensor mit ESP32 und SCD41

Beitrag von tloeffel » 16.10.2021, 10:03

Hallo cloudman88,

danke für die super Anregung und habe viel gerlernt.

Code: Alles auswählen

sensor:
  - platform: dht
    pin: GPIO14
    temperature:
      name: "Dachgeschoss Temperatur01"
      id: wert1
      
      on_value:
        then:
          http_request.get: http://192.168.xxx.xxx:8181/egal.exe?x=dom.GetObject("_httptest").State(120)
Leider bekomme ich es nicht hin den tatsächlichen Wert des Temperatursensors zur CCU zu schreiben. Ich verstehe yaml leider noch nicht so gut. Kannst Du mir da kurz helfen :-).

Gruß und Danke Thomas
972 Kanäle in 165 Geräten: Davon 16 HM, 145 HMIP, 2 Gruppen und 2 CUXD Geräte

cloudman88
Beiträge: 115
Registriert: 26.10.2020, 11:32
System: Alternative CCU (auf Basis OCCU)
Hat sich bedankt: 12 Mal
Danksagung erhalten: 18 Mal

Re: Quick and Dirty Co² Sensor mit ESP32 und SCD41

Beitrag von cloudman88 » 16.10.2021, 11:16

Gibt die Url doch mal im Browser ein

Code: Alles auswählen

http://192.168.xxx.xxx:8181/egal.exe?x=dom.GetObject('_httptest').State(120)
Die Systemvariable _httptest hast du vorher schon als Zahl angelegt - richtig?
Übrigens verwende ich die einfachen Anführungszeichen in meinem Beispiel, weil ich später für den string noch doppelte benötige

tloeffel
Beiträge: 435
Registriert: 13.09.2017, 05:11
Hat sich bedankt: 1 Mal
Danksagung erhalten: 9 Mal

Re: Quick and Dirty Co² Sensor mit ESP32 und SCD41

Beitrag von tloeffel » 16.10.2021, 12:02

Hallo cloudman88,

so habe es hinbekommen.

Code: Alles auswählen

 - http_request.get:
              url: !lambda |-
                return ((std::string) "http://192.168.180.48:8181/any.exe?x=dom.GetObject('${hm_sysvar_co2}').State(" + esphome::to_string(static_cast<uint16_t>(x)) + ")" );
Bei mir werden nur ganze Zahlen übertragen. Ich verstehe diesen Inhalt leider noch nicht: [State(" + esphome::to_string(static_cast<uint16_t>(x)) + ")].
Kannst Du es mir erklären?

Danke Dir.
Gruß Thomas
972 Kanäle in 165 Geräten: Davon 16 HM, 145 HMIP, 2 Gruppen und 2 CUXD Geräte

cloudman88
Beiträge: 115
Registriert: 26.10.2020, 11:32
System: Alternative CCU (auf Basis OCCU)
Hat sich bedankt: 12 Mal
Danksagung erhalten: 18 Mal

Re: Quick and Dirty Co² Sensor mit ESP32 und SCD41

Beitrag von cloudman88 » 16.10.2021, 12:06

return ((std::string) "http://192.168.180.48:8181/any.exe?x=do ... 2}').State(" + esphome::to_string(x) + ")" );
Sollte klappen - ich wandle den float Wert in integer um weil Co2 parts per million ist und ich da keine nachkomma stelle brauche

tloeffel
Beiträge: 435
Registriert: 13.09.2017, 05:11
Hat sich bedankt: 1 Mal
Danksagung erhalten: 9 Mal

Re: Quick and Dirty Co² Sensor mit ESP32 und SCD41

Beitrag von tloeffel » 16.10.2021, 12:12

Hi,

so habe jetzt verstanden das der Datentyp "int" war und habe den durch "double" ausgetauscht. Jetzt zeigt der auch Kommastellen an.

Code: Alles auswählen

" + esphome::to_string(static_cast<double>(x)) + "
Kannst Du mir kurz erklären was "+ esphome::to_string ...... +" genau macht?

Gruß Thomas
972 Kanäle in 165 Geräten: Davon 16 HM, 145 HMIP, 2 Gruppen und 2 CUXD Geräte

tloeffel
Beiträge: 435
Registriert: 13.09.2017, 05:11
Hat sich bedankt: 1 Mal
Danksagung erhalten: 9 Mal

Re: Quick and Dirty Co² Sensor mit ESP32 und SCD41

Beitrag von tloeffel » 16.10.2021, 12:14

naja dann hast DU in "int" und ich dann wieder "double". Ok werde Deines einsetzen :-). Wieder was gelernt.
972 Kanäle in 165 Geräten: Davon 16 HM, 145 HMIP, 2 Gruppen und 2 CUXD Geräte

tloeffel
Beiträge: 435
Registriert: 13.09.2017, 05:11
Hat sich bedankt: 1 Mal
Danksagung erhalten: 9 Mal

Re: Quick and Dirty Co² Sensor mit ESP32 und SCD41

Beitrag von tloeffel » 16.10.2021, 12:40

Weißt Du wie man im ESPhome rundet (also die Syntax)?

Gruß Thomas
972 Kanäle in 165 Geräten: Davon 16 HM, 145 HMIP, 2 Gruppen und 2 CUXD Geräte

Xel66
Beiträge: 10073
Registriert: 08.05.2013, 23:33
System: Alternative CCU (auf Basis OCCU)
Wohnort: Nordwürttemberg
Hat sich bedankt: 160 Mal
Danksagung erhalten: 708 Mal

Re: Quick and Dirty Co² Sensor mit ESP32 und SCD41

Beitrag von Xel66 » 16.10.2021, 12:47

Wenn der Sensor in Parts per Million ausgibt, dann ist eine Wandlung auf real eine Änderung von 0,000000% auf 0,000000x%. Ist das wirklich relevant? Machen die Stellen hinter dem Komma wirklich was aus oder gaukeln sie nur eine Genauigkeit vor, die der Sensor bei einer angegebenen Toleranz von ±(40 ppm + 5 %) gar nicht leisten kann? Nur weil eine Zahl mit vielen Kommastellen dargestellt werden kann, heißt das noch lange nicht, dass die Genauigkeit auch in diesem Bereich angesiedelt ist. Ähnlich wie bei den Thermostaten. Ich glaube nicht, dass man Temperaturunterschiede von mehr als einer Kommastelle spüren kann.

Gruß Xel66
-------------------------------------------------------------------------------------------
343 Kanäle in 118 Geräten und 264 CUxD-Kanäle in 33 CUxD-Geräten:
282 Programme, 246 Systemvariablen und 144 Direktverknüpfungen,
RaspberryMatic Version: 3.59.6.20211009 + Testsystem: CCU2 2.53.27
-------------------------------------------------------------------------------------------
Einsteigerthread, Programmlogik-Thread, WebUI-Handbuch

cloudman88
Beiträge: 115
Registriert: 26.10.2020, 11:32
System: Alternative CCU (auf Basis OCCU)
Hat sich bedankt: 12 Mal
Danksagung erhalten: 18 Mal

Re: Quick and Dirty Co² Sensor mit ESP32 und SCD41

Beitrag von cloudman88 » 16.10.2021, 13:24

Ich denke es geht um die Temperatur (ich hab irgendwo DHT22 gesehen)

So ginge es

Code: Alles auswählen

   - http_request.get:
              url: !lambda |-
                char buf[128];
                snprintf(buf,sizeof(buf),"http://${hm_host}:8181/any.exe?w=dom.GetObject('${hm_sysvar_co2}').State(%0.1f)", x);
                return buf;
Anzahl der Nachkomma Stellen kannst du mit %0.nf festlelegen (n = Anzahl der Nachkomma Stellen)

Für CO2 ist es in der Tat nicht sinnvoll. Der Wert liegt immer im Berreich von ca 450 - 1200 ppm bei mir

Der DHT22 hat übrigens auch nur humidity +-2%RH(Max +-5%RH); temperature <+-0.5Celsius
Deutlich genauer ist z.b. der SHT35 oder SHT85 (+- 0.1°C) bzw. der neue SHT40 mit (+- 0.2°C)

Antworten

Zurück zu „Projektvorstellungen“