Startseite » Automatischer Taupunkt-Lüfter

Automatischer Taupunkt-Lüfter

Du hast einen Keller oder einen anderen Raum, der sehr feucht ist und der eigentlich laufend gelüftet werden müsste. Oder beheizt mit sehr viel Energie. Mit Taupunkt-Lüftung geht das optimal. Besser noch, wenn du eine Anlage baust, die Messungen automatisch übernimmt und den Raum zu den besten Zeitpunkten automatisch belüftet.

Nach dem Ukrainekrieg waren die Heizpreise im Winter 2022/2023 sehr hoch. Also habe ich versucht einen großen Raum, der nur selten genutzt wird, fast gar nicht zu heizen. Dabei können zwei Probleme entstehen: Die Leitungen können durch Frost Schaden nehmen, also muss eine gewisse Grundtemperatur im Raum herrschen. Außerdem kann sich Schimmel bilden. Mit einer Zieltemperatur von nur 8°C und der richtigen Technik zum Lüften konnte ich so meinen Heizbedarf und meine Kosten massiv senken. Und Schimmel entstand dabei nicht.

Inhaltsverzeichnis

Theorie

Luftfeuchte wird relativ in Prozent gemessen (relative Luftfeuchte). Relative Luftfeuchte beschreibt, wie viel Wasser in der Luft ist im Vergleich zu dem Maximum, das die Luft bei ihrer Temperatur speichern kann. Verändert sich die Temperatur, verändert sich auch die Menge an Wasser, die die Luft speichern kann. Verringert sich die Temperatur, wird die Wassermenge kleiner, wird die Luft wärmer, wird die Wassermenge größer.

Bleibt die Wassermenge in der Luft gleich und die Temperatur erhöht sich, dann wird die relative Luftfeuchte also kleiner. Verringert sich die Temperatur, wird die Luftfeuchte höher bis zu einem Maximum von 100%. Die Lufttemperatur, bei der die Luftfeuchte 100% erreichen würde und von hier an kondensiert, nennt man Taupunkt. Den Taupunkt kannst du also als Maß verwendet werden, um Luftmassen unterschiedlicher Temperatur und Luftfeuchte miteinander zu vergleichen. Luft mit einem geringeren Taupunkt enthält weniger Wasser als Luft mit einem höheren Taupunkt.

Wenn du also optimal Lüften willst, wartest du auf einen Zeitpunkt, an dem die Außenluft einen geringeren Taupunkt hat als die Luft innerhalb eines zu feuchten Raumes. Ist der Taupunkt der Außenluft höher, ist das Lüften sogar kontraproduktiv, weil du mehr Feuchtigkeit in deinen Raum hereinbringst, als bereits vorhanden ist. Vor allem im Sommer enthält die Luft oft mehr Feuchtigkeit, weil die warme Luft eben mehr Feuchtigkeit fassen kann als vielleicht deine kühlere Kellerluft.

Bei meinen Messungen habe ich die Beobachtung gemacht, dass besonders morgens zum Sonnenaufgang der beste Zeitpunkt zum Lüften ist, da die Außenluft hier meist am trockensten ist. Aber wir wollen es genau wissen.

Schimmel kann entstehen bei einer dauerhaften Luftfeuchte von 60% oder mehr. (Quelle: Verbraucherzentrale)

In einem anderen Beitrag schildere ich über eine Benachrichtigungsfunktion für gute Lüftungszeitpunkte, die 61% als Schwellwert verwenden und auch mit Taupunkten arbeitet.

Hardware

Die Hardwareteile sind unten in der Grafik schon zu sehen. Das ein oder andere Teil ist sicher austauschbar. Ich habe folgende Komponenten verwendet

  • 1x D1 Mini NodeMcu mit ESP8266
  • 1x TCA9548A I2C-Switch
  • 2x Sensor BME280
  • 1x Widerstand: 1kΩ
  • 1x TIP122 Transistor NPN
  • 2x 70cm 4pin Dupont Kabel männlich zu weiblich (zur einfachen Anbindung der Sensoren)
  • Jumper-Kabel
  • 120mm PC-Lüfter (so viele du glaubst zu brauchen)
  • 1x Breadboard
  • 1x Breadboard Power Supply MB120
  • 1x DC Steckernetzteil 12V 5A passend zum Breadboard Power Supply
  • ggf. Plexiglas passend für die Öffnung, mit der du die Luftzufuhr steuern willst.

Das ganze kannst du wie unten zu sehen dann verkabeln. Ich verwende D4 als Signal-Pin um die Lüfter zu aktivieren. D1 und D2 um den I2C-Switch anzubinden und dort die Kanäle 2 und 3 für die Sensoren, die du aber auch ändern kannst. Denk nur daran, die auch später in de Konfiguration zu ändern. Der Sensor an Kanal 3 ist für drinnen, der Sensor an Kanal 2 ist für draußen bestimmt.

Die Lüfter werden so angebracht, dass sie die feuchte Luft aus dem Raum heraussaugen. Frische trockenere Luft strömt dann von woanders nach.

Software

1) Vor oder nach dem Zusammenbau will der ESP8266 mit Software betankt werden. Mit ESPHome geht das sehr einfach, wenn du das erstmalig in Betrieb genommen hast. Python gibt es nicht nur für Linux, sondern auch für Windows. Hast du kein Linux auf deinem Rechner, willst es aber verwenden, kannst du das auch innerhalb einer VirtualBox laufen lassen. Ich habe es auch geschafft, mit Portable Python von Windows aus ESPHome zu verwenden.

1.1)Hinweis: Unter Ubuntu 22.04 wird der ESP nicht automatisch korrekt erkannt. Hier sind vorher noch zwei Handgriffe nötig:

  • btltty entfernen
sudo apt remove brltty #removes brltty, do not remove if you need this because of blindness!

oder benutze ein früheres Ubuntu.

Für Windows und normalerweise auch unter anderen Ubuntu-Versionen lässt sich der ESP recht einfach provisionieren ohne 1.1)

2) Schließe deinen ESP8266 an deinen Rechner an und provisioniere ihn mit web.esphome.io.

3) Und verwende folgende ESPHome-Konfiguration:
(nachdem du name, wifi und mqtt auf dein Netz angepasst hast)

esphome:
  name: esp-fan-controller

esp8266:
  board: d1_mini
  #board: nodemcuv2

# Enable logging
logger:
  tx_buffer_size: 256
  #level: NONE
  #level: VERBOSE

web_server:
  port: 80

ota:
#  password: ""

wifi:
  networks:
  - ssid: "R'lyeh2"
    password: "00Cthulhu00"
  - ssid: "FritzBox7590"
    password: "Annette&Ralf&Alexander&Christian"
#  domain: ".rlyeh"
  reboot_timeout: 2min


#https://esphome.io/components/i2c.html
i2c:
  id: i2c_main
  scl: D1
  sda: D2
  scan: true
  frequency: 20kHz

tca9548a:
  - address: 0x70
    id: multiplex0
    i2c_id: i2c_main
    channels:
      - bus_id: i2c_0
        channel: 2
      - bus_id: i2c_1
        channel: 3
      
sensor:
  - platform: uptime
    id: uptime_id
    name: "Uptime"
    update_interval: 15s
      
  #BME/P280
  #https://esphome.io/components/sensor/bme280.html
  - platform: bme280
    i2c_id: i2c_0
    temperature:
      name: "BME-T 2 (out)"
      id: bme280_0_temperature
      oversampling: 8x
      filters:
        - filter_out: NaN
    pressure:
      name: "BME-P 2 (out)"
      id: bme280_0_pressure
      filters:
        - filter_out: NaN
    humidity:
      name: "BME-H 2 (out)"
      id: bme280_0_humidity
      filters:
        - filter_out: NaN
    address: 0x76
    update_interval: 30s
  - platform: template
    name: "Dew Point 2 (out)"
    id: bme280_0_dewpoint
    lambda: |-
      return (243.5*(log(id(bme280_0_humidity).state/100)+((17.67*id(bme280_0_temperature).state)/
      (243.5+id(bme280_0_temperature).state)))/(17.67-log(id(bme280_0_humidity).state/100)-
      ((17.67*id(bme280_0_temperature).state)/(243.5+id(bme280_0_temperature).state))));
    unit_of_measurement: °C
    icon: 'mdi:thermometer-alert'
    filters:
      - filter_out: NaN
  - platform: bme280
    i2c_id: i2c_1
    temperature:
      name: "BME-T 3 (in)"
      id: bme280_1_temperature
      oversampling: 8x
      filters:
        - filter_out: NaN
    pressure:
      name: "BME-P 3 (in)"
      id: bme280_1_pressure
      filters:
        - filter_out: NaN
    humidity:
      name: "BME-H 3 (in)"
      id: bme280_1_humidity
      filters:
        - filter_out: NaN
    address: 0x76
    update_interval: 30s
  - platform: template
    name: "Dew Point 3 (in)"
    id: bme280_1_dewpoint
    lambda: |-
      return (243.5*(log(id(bme280_1_humidity).state/100)+((17.67*id(bme280_1_temperature).state)/
      (243.5+id(bme280_1_temperature).state)))/(17.67-log(id(bme280_1_humidity).state/100)-
      ((17.67*id(bme280_1_temperature).state)/(243.5+id(bme280_1_temperature).state))));
    unit_of_measurement: °C
    icon: 'mdi:thermometer-alert'
    filters:
      - filter_out: NaN


button:
  #https://esphome.io/components/button/restart.html
  - platform: restart
    name: "Restart"
    
switch:
  #Digital Pins
  - platform: gpio
    id: gpio_d4
    name: "Fans"
    pin: D4


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

interval:
  - interval: 30s
    then:
      - if:
          condition:
            lambda: |-
              return id(bme280_0_dewpoint).state + 2.0 < id(bme280_1_dewpoint).state;
          then:
            - switch.turn_on: gpio_d4
          else:
            - switch.turn_off: gpio_d4
  - interval: 30s
    then:
      - http_request.post:
          url: !lambda |-
            const size_t capacity = JSON_OBJECT_SIZE(10);
            DynamicJsonDocument root(capacity);

            root["name"] = "NeuensteinKeller";
            root["uptime"] = id(uptime_id).state;
            root["bme280_0_temperature"] = id(bme280_0_temperature).state;
            root["bme280_0_pressure"] = id(bme280_0_pressure).state;
            root["bme280_0_humidity"] = id(bme280_0_humidity).state;
            root["bme280_0_dewpoint"] = id(bme280_0_dewpoint).state;
            root["bme280_1_temperature"] = id(bme280_1_temperature).state;
            root["bme280_1_pressure"] = id(bme280_1_pressure).state;
            root["bme280_1_humidity"] = id(bme280_1_humidity).state;
            root["bme280_1_dewpoint"] = id(bme280_1_dewpoint).state;

            String jsonPayload;
            serializeJson(root, jsonPayload);

            return ((String) "https://mystryx.dd-dns.de/files/json_receiver/?name=NeuensteinKeller&json=" + jsonPayload).c_str();
            
          headers:
            Content-Type: application/json
          verify_ssl: false
          json: |-
            root["name"]                = "NeuensteinKeller";
            root["uptime"]              = id(uptime_id).state;
            root["bme280_0_temperature"]= id(bme280_0_temperature).state;
            root["bme280_0_pressure"]   = id(bme280_0_pressure).state;
            root["bme280_0_humidity"]   = id(bme280_0_humidity).state;
            root["bme280_0_dewpoint"]   = id(bme280_0_dewpoint).state;
            root["bme280_1_temperature"]= id(bme280_1_temperature).state;
            root["bme280_1_pressure"]   = id(bme280_1_pressure).state;
            root["bme280_1_humidity"]   = id(bme280_1_humidity).state;
            root["bme280_1_dewpoint"]   = id(bme280_1_dewpoint).state;

Ich verwende meine Konstruktion in einem anderen Netzwerk uns sende mir die Daten selbst. Die HTTP-Requests sind zur Funktion nicht notwendig. Das letzte Interval kannst du für deine Zwecke vielleicht entfernen oder muss von dir angepasst werden.

Der json_receiver ist ein per HTTPS im Netz erreichbarer Server, der empfangene Daten in meinem Netz als MQTT-Nachricht einspeist.

Kommentar verfassen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Diese Seite verwendet Akismet, um Spam zu reduzieren. Erfahre, wie deine Kommentardaten verarbeitet werden..

Translate »