Das ist meine DIY-Hardware für die Steuerung von 24 Volt Bewässerungsventilen

DIY Bewässerungssteuerung mit Home Assistant und ESPHome

So funktioniert meine Steuerung für 24 Volt Bewässerungsventile auf Basis von ESPHome.

Mit unserer Zisterne, die wir im letzten Jahr als Puffer und mit den neuen Rohren für die Regenwasserableitung bekommen haben, gibt es und reichlich kostenloses Wasser vom Dach. Zumindest, wenn es eines Tages mal wieder regnet.

Wir haben daher auf dem Grundstück Rohre für eine automatische Bewässerung verlegt, wozu das Gardena Bewässerungssystem zum Einsatz kam, da diese Komponenten im letzten Jahr günstiger als die Alternativen von Hunter oder Rainbird waren.

Über 5 Ventile steuern wir 5 individuelle Kreise an:

  • Rasenbewässerung Ost
  • Rasenbewässerung West
  • Hochbeet / Beete
  • Vorgarten
  • Wasserauslass in der Einfahrt

Als Material haben wird verbaut:

Gardena Versenkregner

Die Elektronik des Waterking

Die typischen Bewässerungsventile werden mit 24 Volt Wechselstrom angesteuert. Der Einschaltstrom beträgt etwa laut Datenblatt 370 mA, der Haltestrom 210 mA. Die tatsächlichen Werte waren nach meinen Messungen etwas geringer.

Da nie alle Ventile gleichzeitig in Betrieb sind, weil sonst der Wasserdruck zu stark abfallen würde (selbst bei der 4 bar Tauchdruckpumpe), genügt ein 24 Volt Wechselspannungsnetzteil mit 1 Ampere. Das hatte ich noch von einer alten Außenlichterkette. Passende Netzteile bekommt man auch bei Ebay.

Würde man die Ventile mit Gleichspannung betreiben, könnten sich die Kerne der Elektromagnete permanent magnetisieren und die Ventile würden „kleben“. Im schlimmsten Fall wird der Kern gesättigt, was einen höheren Stromfluss und damit die Zerstörung der Spulen bedeuten kann.

Daher kann man keine MOSFETs zur einfachen Ansteuerung nutzen. Am einfachsten wären Relais, doch darauf wollte ich nicht vertrauen. Erstens können die Kontakte korrodieren und die einfachen China-Relais, die es als 4er oder 8er Platinen fix und fertig gibt, sind nicht unbedingt zum Schalten von Niederspannung geeignet. Das klingt paradox, aber die meisten Legierungen, die für Relais-Kontakte eingesetzt werden (bei diesen Relais AgCdO), benötigen einen kurzen Lichtbogen, der nur bei höheren Spannungen und Strömen entsteht (der sog. Frittstrom). Dadurch werden Oxide weggebrannt, was für einen dauerhaft guten Kontakt sorgt. Da im Gerätehaus auch hohe Luftfeuchtigkeit vorkommt, schieden Relais für mich aus.

Die Triacs der 5 Kanäle mit den weißen Optokopplern

Ich habe mich bei meinem DIY-Controller, den ich Waterking getauft habe, für Triacs vom Typ BTA08-600B entschieden, die über einen MOC3041 Optokoppler angesteuert werden, der auch gleich einen Nulldurchgang-Triac-Treiber enthält. Rechnet man noch 5 Widerstände, einen NPN-Transistor und eine LED dazu, kostet ein Kanal nicht einmal einen Euro und man wird nie Kontaktprobleme haben. Die LEDs zeigen Hardware-seitig an, ob ein Ventil offen ist und der Optokoppler angesteuert wird.

Da man ohnehin schon die 24 Volt hat, kann man die auch für die Versorgung des ESP8266 und des Displays nutzen. Gleichgerichtet kommt man auf 35 V Gleichspannung, die ich mit einem LM2596S Step-Down-Konverter sehr effizient auf 5 Volt wandle.

Wie oft bei meinen Projekten kommt ein Wemos D1 Mini Pro zum Einsatz, weil ich vor längerer Zeit einmal preiswert einen größeren Posten eingekauft hatte. Der Wemos wird auch bis auf den (fast) letzten GPIO ausgereizt. Zur Ansteuerung von 5 Ventilen und unserer Tauchdruckpumpe benötige ich 6 Ausgänge. Jetzt könnte man 6 GPIOs verbraten oder man nimmt ein Schieberegister vom Typ SN74HC595. Damit kann man mit 3 Steuer-Pins 8 Ausgänge schalten. Benötigt man mehr, kann man unter ESPHome bis zu 4 SN74HC595 kaskadieren, wozu man dann noch einen Pin mehr benötigt, damit aber 32 Ausgänge erhält.

Die Pumpe wird über ein Solid State Relais (SSR) geschaltet.

Ursprünglich sollte mein Controller „dumm“ bleiben, also nur die Triac-Ausgänge per Home Assistant schaltbar machen. Wenn man aber schon einen Mikrocontroller hat, kann man ja auch gleich noch ein paar Funktionen extra einbauen. So schalten die Ventile nach einer konfigurierbaren Zeit (10 Minuten) ab. Ist kein Ventil mehr aktiv, wird auch die Pumpe deaktiviert. Sollte die WLAN-Verbindung während der Bewässerung verloren gehen oder Home Assistant einen Bug haben, schalten Ventile und die Pumpe automatisch und autonom ab. Aufgebaut habe ich alles auf einer Streifenrasterplatine. Ich bin „Team Streifenraster“ – mir gefällt das Herumgekleckse mit Lötzinn auf den Perfboards einfach nicht.

Bitte habt Verständnis dafür, dass ich keinen Plan für den Aufbau der Platine habe. Ich mache so etwas frei und ohne große Vorplanung direkt vom Schaltplan weg. Kurz die Position der Teile testen und los geht es. Bei Gelegenheit gibt es vielleicht mal ein Platinenlayout mit KiCAD dazu – vielleicht hat ja auch von euch jemand Lust dazu? Den Schaltplan in KiCAD dazu gibt es.

Schaltplan ohne Display und Encoder

Über einen Dreh-Encoder und das LED-Display kann ich nicht nur den Zustand der Ventile (zusätzlich zu den LEDs am Optokoppler) anzeigen lassen, sondern diese auch direkt am Controller ein- und ausschalten. Weitere Menü-Ebenen zeigen den Wasserstand der Zisterne in Zentimetern und Litern, die Stärke des WLAN-Signals, den heutigen Wasserverbrauch und die Uhrzeit an. Wie man den Wasserstandsmesser mit einem TL-136 Sensor baut, habe ich hier beschrieben: https://nachbelichtet.com/wasserstand-in-zisternen-mit-homeassistant-esphome-und-tl-136-drucksensor-messen/

Wasserstand in der Zisterne

Durch einfaches Drehen am Encoder kann man die Ebenen wechseln. Drückt man die Taste, gelangt man ins Setup-Menü für die Ventile. Ein Strich zeigt ein inaktives Ventil an, ein Kästchen ein aktives. Der Dezimalpunkt signalisiert, welches Ventil man gerade ausgewählt hat und ein langer Druck auf die Taste schaltet es ein oder aus. Mit einer kurzen Betätigung kommt man wieder ins Hauptmenü.

Der Waterking im Einsatz

Mich hat es einmal gereizt, mit einer einfachen 8-stelligen LED-Anzeige ein komfortables Menü zu basteln. Es muss nicht immer ein OLED- oder LC-Display sein und die LED-Anzeige ist sehr robust, was bei -20 bis +50 °C im Gerätehaus nicht unwichtig ist.

Die verschiedenen Menüs und Einstellungen im Display

Über die Abfrage des Wasserstands der Zisterne, kann ich die Pumpe deaktivieren, wenn der Wasserstand unter 12 cm sinkt. Eine lange Betätigung der Encoder-Taste schaltet alle Ventile und die Pumpe sofort aus.

Ventilesteuerung in Home Assistant mit Wasserstand der Zisterne

Das Interlocking der Ausgänge verhindert, dass bestimmte Ventile gleichzeitig aktiv sein können. Damit verhindert man nicht nur einen Druckabfall, sondern auch die Überlastung des Netzteils. Es können maximal 3 Ventile (Gardena Micro Trip Tropfer Hochbeet, Vorgarten und Wasserentnahme) aktiv sein und nur einer der beiden Kreise für die Rasenfläche. Auch diese Sicherheitsfunktion stellt der Controller direkt bereit – egal, was ich in Home Assistant sonst konfigurieren würde.

3D-gedrucktes Gehäuse für den Waterking

Damit alles auch ordentlich verpackt ist und auch gut aussieht, habe ich noch ein Gehäuse aus PETG und PLA gedruckt. Das transparente PETG lässt die LEDs und das Display durchscheinen.

Gehäuse mit abstrahiertem Modell der Platine

Beim Displayausschnitt habe ich die Schichtdicke bei der Konstruktion so gewählt, dass kein Infill gedruckt wird. Damit sieht das wie eine transparente Folie aus.

Das ganze Gehäuse ist schraubenlos verschließbar und auch die Platine wird nur von Schnappverschlüssen gehalten. Bei einer handgefertigten Platine ist die Konstruktion eines Gehäuses mit Deckel nicht ganz trivial, klappte aber beim ersten Versuch und Druck.

Konstruktion in Fusion 360

Als Gag ist noch ein Halter für eine Ersatzsicherung dabei. Der Zugang zu den Anschlussklemmen erfolgt von unten. Zur Konstruktion habe ich – wie immer – Autodesk Fusion 360 eingesetzt. Den Druck erledigte mein Creality Ender 3 in etwa 10 Stunden.

Zugang zu den Anschlussklemmen

Wer den Aufwand mit der Ventilansteuerung nicht betreiben möchte, kann statt der Triacs auch eine solche SSR-Platine einsetzen, die man für unter 20 € bekommt. Hier muss man nur noch die Kanäle mit dem ESP ansteuern. Der Code unten kann auch hierfür genutzt werden.

SSR-Modul mit 8 Kanälen.

Die YAML-Konfiguration in ESPHome habe ich mit entsprechenden Anmerkungen versehen:

esphome: name: waterking platform: ESP8266 board: d1_mini # Zur Sicherheit alle Ausgänge beim Start ausschalten on_boot: then: - switch.turn_off: v1 - switch.turn_off: v2 - switch.turn_off: v3 - switch.turn_off: v4 - switch.turn_off: v5 - switch.turn_off: pump - sensor.rotary_encoder.set_value: id: enc value: 0 # Seriellen Logger an RX/TX ausschalten, um Pins für andere Aufgaben nutzen zu können logger: baud_rate: 0 # Home Assistant API aktivieren api: ota: password: !secret otapass" wifi: ssid: !secret wifi_ssid password: !secret wifi_password use_address: waterking.local # Fallback Hotspot ap: ssid: "Bewaesserung Fallback Hotspot" password: !secret hotspot captive_portal: # Uhrzeit von HA holen time: - platform: homeassistant id: homeassistant_time # Globale Variablen setzen globals: - id: setpage #Einstellmodus type: bool restore_value: no initial_value: 'false' - id: maxtime #maximale Laufzeit Ventile als Schutz type: int restore_value: yes initial_value: '600000' # in ms = 10 min # Schieberegister einrichten sn74hc595: - id: 'sn74hc595_hub' data_pin: D5 clock_pin: D6 latch_pin: D7 oe_pin: D2 sr_count: 1 # SPI für Display spi: clk_pin: D0 mosi_pin: D1 # Ventile definieren switch: - platform: gpio name: "Ventil Ost" id: v1 pin: sn74hc595: sn74hc595_hub number: 1 inverted: false interlock: [v2,v4,v5] # Bestimmte Ventile nicht gleichzeitig einschalten -> Druckverlust on_turn_on: - switch.turn_on: pump - delay: !lambda "return id(maxtime);" - switch.turn_off: v1 - platform: gpio name: "Ventil West" id: v2 pin: sn74hc595: sn74hc595_hub number: 2 inverted: false interlock: [v1,v4,v5] on_turn_on: - switch.turn_on: pump - delay: !lambda "return id(maxtime);" - switch.turn_off: v2 - platform: gpio name: "Ventil Beet" id: v3 pin: sn74hc595: sn74hc595_hub number: 3 inverted: false interlock: [v2] on_turn_on: - switch.turn_on: pump - delay: !lambda "return id(maxtime);" - switch.turn_off: v3 - platform: gpio name: "Ventil Vorgarten" id: v4 pin: sn74hc595: sn74hc595_hub number: 4 inverted: false interlock: [v1,v2] on_turn_on: - switch.turn_on: pump - delay: !lambda "return id(maxtime);" - switch.turn_off: v4 - platform: gpio name: "Ventil Einfahrt" id: v5 pin: sn74hc595: sn74hc595_hub number: 5 inverted: false interlock: [v2,v5] on_turn_on: - switch.turn_on: pump - delay: 1h #Ventil 5 darf max. 1 Stunde an sein -> Wasserentnahme - switch.turn_off: v5 # Solid State Relais Ausgang für Pumpensteuerung - platform: gpio name: "SSR Pumpe" internal: true # Pumpe nicht in HA anzeigen id: pump pin: sn74hc595: sn74hc595_hub number: 0 inverted: false # Display einrichten display: - platform: max7219 cs_pin: D3 num_chips: 1 update_interval: 500ms lambda: |- // Page 5 Uhrzeit anzeigen if ((id(enc).state == 5) && (id(setpage) == false)) { it.print(" "); it.strftime("%H.%M.%S", id(homeassistant_time).now()); } // Page 4 Wifi Level if ((id(enc).state == 4) && (id(setpage) == false)) { it.print(" "); it.printf("Wi %.0fdB", id(wlan_signal).state); } // Page 1 Wasserstand Höhe if ((id(enc).state == 1) && (id(setpage) == false)) { it.print(" "); it.printf("FH %.1fcn", id(zisterne_cm).state); } // Page 2 Wasserstand Liter if ((id(enc).state == 2) && (id(setpage) == false)) { it.print(" "); it.printf("FS %.0fL", id(zisterne_liter).state); } // Page 3 Wasserverbrauch heute if ((id(enc).state == 3) && (id(setpage) == false)) { it.print(" "); it.printf(1,"= %.0f L", id(zisterne_delta_heute).state); } // Page 0 Status Ventile anzeigen if ((id(enc).state == 0) && (id(setpage) == false)) { it.print(" "); if ((id(v1).state)) { it.print("o"); } else { it.print("_"); } if ((id(v2).state)) { it.print(1,"o"); } else { it.print(1,"_"); } if ((id(v3).state)) { it.print(2,"o"); } else { it.print(2,"_"); } if ((id(v4).state)) { it.print(3,"o"); } else { it.print(3,"_"); } if ((id(v5).state)) { it.print(4,"o"); } else { it.print(4,"_"); } if ((id(pump).state)) { it.print(6,"P"); } else { it.print(6,"_"); } } // Erste Seite Setup-Page if (id(setpage) == true && id(enc).state == 0) { it.print(" S"); if ((id(v1).state)) { it.print("o"); } else { it.print("_"); } if ((id(v2).state)) { it.print(1,"o"); } else { it.print(1,"_"); } if ((id(v3).state)) { it.print(2,"o"); } else { it.print(2,"_"); } if ((id(v4).state)) { it.print(3,"o"); } else { it.print(3,"_"); } if ((id(v5).state)) { it.print(4,"o"); } else { it.print(4,"_"); } if ((id(pump).state)) { it.print(6,"P"); } else { it.print(6,"_"); } } // Ventil 1 einstellen if (id(setpage) == true && id(enc).state == 1) { if ((id(v1).state)) { it.print("o."); } else { it.print("_."); } if ((id(v2).state)) { it.print(1,"o"); } else { it.print(1,"_"); } if ((id(v3).state)) { it.print(2,"o"); } else { it.print(2,"_"); } if ((id(v4).state)) { it.print(3,"o"); } else { it.print(3,"_"); } if ((id(v5).state)) { it.print(4,"o"); } else { it.print(4,"_"); } } // Ende V1 // Ventil 2 einstellen if (id(setpage) == true && id(enc).state == 2) { if ((id(v1).state)) { it.print("o"); } else { it.print("_"); } if ((id(v2).state)) { it.print(1,"o."); } else { it.print(1,"_."); } if ((id(v3).state)) { it.print(2,"o"); } else { it.print(2,"_"); } if ((id(v4).state)) { it.print(3,"o"); } else { it.print(3,"_"); } if ((id(v5).state)) { it.print(4,"o"); } else { it.print(4,"_"); } } if (id(setpage) == true && id(enc).state == 3) { if ((id(v1).state)) { it.print("o"); } else { it.print("_"); } if ((id(v2).state)) { it.print(1,"o"); } else { it.print(1,"_"); } if ((id(v3).state)) { it.print(2,"o."); } else { it.print(2,"_."); } if ((id(v4).state)) { it.print(3,"o"); } else { it.print(3,"_"); } if ((id(v5).state)) { it.print(4,"o"); } else { it.print(4,"_"); } } if (id(setpage) == true && id(enc).state == 4) { if ((id(v1).state)) { it.print("o"); } else { it.print("_"); } if ((id(v2).state)) { it.print(1,"o"); } else { it.print(1,"_"); } if ((id(v3).state)) { it.print(2,"o"); } else { it.print(2,"_"); } if ((id(v4).state)) { it.print(3,"o."); } else { it.print(3,"_."); } if ((id(v5).state)) { it.print(4,"o"); } else { it.print(4,"_"); } } if (id(setpage) == true && id(enc).state == 5) { if ((id(v1).state)) { it.print("o"); } else { it.print("_"); } if ((id(v2).state)) { it.print(1,"o"); } else { it.print(1,"_"); } if ((id(v3).state)) { it.print(2,"o"); } else { it.print(2,"_"); } if ((id(v4).state)) { it.print(3,"o"); } else { it.print(3,"_"); } if ((id(v5).state)) { it.print(4,"o."); } else { it.print(4,"_."); } } sensor: - platform: rotary_encoder # Drehencoder einrichten name: "Rotary Encoder" id: enc publish_initial_value: true pin_a: number: TX inverted: true mode: input: true pullup: true pin_b: number: RX inverted: true mode: input: true pullup: true max_value: 5 min_value: 0 # Füllstand in Liter von HA holen - platform: homeassistant id: zisterne_liter entity_id: sensor.zisterne_liter # Verbrauch heute von HA holen - platform: homeassistant id: zisterne_delta_heute entity_id: sensor.zisterne_delta_heute # Füllstand in cm von HA holen - platform: homeassistant id: zisterne_cm entity_id: sensor.wasserstandraw # Notabschaltung Wasserstand < 12 cm -> Pumpenschutz on_value_range: - below: 12 then: - switch.turn_off: v1 - switch.turn_off: v2 - switch.turn_off: v3 - switch.turn_off: v4 - switch.turn_off: v5 - switch.turn_off: pump # WLAN Signalstärke holen ... weil man es kann - platform: wifi_signal name: "Bewaesserung ESP Wifi Signal" update_interval: 30s id: wlan_signal binary_sensor: - platform: template name: "Any Valve On" # Wenn alle Ventile aus, Pumpe ausschalten internal: true lambda: 'return id(v1).state or id(v2).state or id(v3).state or id(v4).state or id(v5).state ;' on_release: then: - switch.turn_off: pump - platform: gpio # Taster am Encoder einrichten id: encswitch pin: number: GPIO2 mode: INPUT_PULLUP inverted: True on_click: - min_length: 50ms # Kurzer Betätigung, um ins Ventil-Setup zu kommen max_length: 250ms then: - lambda: |- if(id(setpage)) { id(setpage) = false; } else { id(setpage) = true; } - min_length: 600ms # lange Betätigung, um ausgewähltes Ventil ein/aus zu schalten max_length: 1500ms then: - if: condition: lambda: 'return (id(setpage) == true && id(enc).state == 1);' then: switch.toggle: v1 - if: condition: lambda: 'return (id(setpage) == true && id(enc).state == 2);' then: switch.toggle: v2 - if: condition: lambda: 'return (id(setpage) == true && id(enc).state == 3);' then: switch.toggle: v3 - if: condition: lambda: 'return (id(setpage) == true && id(enc).state == 4);' then: switch.toggle: v4 - if: condition: lambda: 'return (id(setpage) == true && id(enc).state == 5);' then: switch.toggle: v5 - min_length: 3000ms # gaaanz lange Betätigung, um alle Ventile und die Pumpe auszuschalten max_length: 60000ms then: - switch.turn_off: v1 - switch.turn_off: v2 - switch.turn_off: v3 - switch.turn_off: v4 - switch.turn_off: v5 - switch.turn_off: pump
Code-Sprache: YAML (yaml)

Bewässerungssteuerung mit Home Assistant

Die eigentliche Bewässerungssteuerung wird Home Assistant übernehmen. Da hier bereits diverse Sensoren wie der Regensensor der LCN-WIH Wetterstation, Regenmengensensor sowie die Wettervorhersage als Entitäten in HA vorhanden sind, kann man diese für eine optimale und sparsame Bewässerung nutzen.

Installation im Gerätehaus

Die Füllstandsmessung der Zisterne ist übrigens auch ein hervorragender Sensor, was Niederschlagsmengen angeht, bekommt er doch den Niederschlag von 75 qm Dachfläche. Bei niedrigem Wasserstand in der Zisterne kann man auch die Bewässerungszeiten verkürzen usw.

Bodenfeuchtesensor
Neues Projekt: Der DIY-Bodenfeuchtesensor

Die wichtigsten Werte für die Bewässerung kommen über einen Bodenfeuchtesensor. Kapazitive Sensoren sind zwar relativ robust, messen die Bodenfeuchte jedoch nur in einem engen Bereich von wenigen Quadratzentimetern. Ich habe mir daher einen resistiven Sensor aus zwei 1 Meter langen Edelstahlgewindestangen gebaut, die mit 20 mm Abstand in 10 cm Tiefe vergraben werden.

Der DIY-Bodenfeuchtesensor

Edelstahl ist korrosionsbeständig und robust. Die zwei M5 Stangen kosteten im Sonderpreis Baumarkt 3 Euro. Mit diesem Sensor erfasst man einen repräsentativen Bereich und nicht nur punktuell. Da sich durch den Messstrom und die dadurch verursachte Elektrolyse mit der Zeit Salze und Mineralien an den Elektroden ablagern könnten, aktiviert man die Messung nur sehr kurz und in größeren Intervallen. Hierzu wird es einen separaten Beitrag geben.


Die mit Sternchen (*) gekennzeichneten Verweise sind sogenannte Provision-Links. Wenn du auf so einen Verweislink klickst und über diesen Link einkaufst, bekomme ich von deinem Einkauf eine Provision. Für dich verändert sich der Preis nicht und du unterstützt damit meine Arbeit. Preisänderungen und Irrtümer vorbehalten.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.

Cookie Consent mit Real Cookie Banner