Heizungskontrolle Einfach

Aus FHEMWiki
Version vom 18. November 2015, 00:02 Uhr von Markusbloch (Diskussion | Beiträge) (@@ => @)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)

For the English version, see Heating Control Basic.

Ziel dieses Projekts ist die Ansteuerung einer Zentralheizung mit FHEM. Dieser Artikel basiert hauptsächlich auf einem Forumsbeitrag von borsti. Die Heizungslogik schaltet die Heizung ein, falls einer oder mehrere Radiatoren offen sind und schaltet sie wieder aus, sobald alle Radiatoren geschlossen sind.

Hardware

Das System ist aus den folgenden Komponenten aufgebaut:

  • Zentralheizung mit Thermostat-Eingang.
  • FHEM, installiert auf einem Server.
  • CUL USB, am Server eingesteckt.
  • FS20 AS1 Funkschalter, am Thermostat-Eingang der Heizung angeschlossen.
  • 3x FHT80b Raumthermostate für 3 Räume.
  • Ein FHT8V pro Radiator in den 3 Räumen.

FHEM Konfiguration

Nachdem die Hardware wie in den Anleitungen beschrieben in Betrieb genommen wurde, können wir mit der Konfiguration der Heizungssteuerung beginnen. Für den Rest des Artikels werden wir den Inhalt der Datei fhem.cfg Schritt für Schritt durchgehen und kommentieren. Diese Datei kann einfach aus FHEM heraus direkt bearbeitet werden.

define CUL1 CUL /dev/CUL@9600 5643

define raum1 FHT 5030
define raum2 FHT 235d
define raum3 FHT 2d28

define heizung FS20 5643 53

Die Konfiguration beginnt mit der Definition der Hardware-Komponenten. Der CUL wird zuerst initialisiert, gefolgt von den FHT80b-Thermostaten mit deren jeweiligen Hauscodes (die natürlich individuell verschieden sind). Die letzte Zeile definiert den Funkschalter FS20 AS1, der an die Heizung angeschlossen ist. Beachte, dass wir die eigentlichen Ventilantriebe (FHT8V) der Radiatoren ignorieren. Diese werden autark und direkt von den FHT-Thermostaten geregelt und FHEM muss sich in diesen Prozess nicht einmischen.

define n_heizung notify n_heizung {\

Mit dieser Zeile definieren wir einen neuen notify namens n_heizung der den Code für die Steuerung enthalten wird. Notifies funktionieren so ähnlich wie ein Makro, das beliebig oft durch Eingabe eines einzigen Befehls ausgeführt werden kann. Von nun an verwenden wir normalen Perl Code. Da dieser in einem FHEM-Befehl eingebettet sein wird, müssen einige Sonderzeichen ersetzt werden (z.B. ;; statt ; und zusätzliche \ am Zeilenende). In der FHEM Referenz finden sich weitergehende Informationen zur Benutzung von Perl in FHEM.

   my $brauche_waerme=0;;\
   my $ventile_im_leerlauf=0;;\

Hier werden zwei Variablen definiert, die verfolgen, ob einer oder mehrere FHT Wärme benötigen, bzw. wieviele FHT keine Wärme brauchen.

 
  my $heizung_status=$fs20_c2b{ReadingsVal("heizung","state","off")};;\

Diese Variable speichert den aktuellen Zustand der Heizung selbst. ReadingsVal ist eine Funktion mit drei Argumenten: Gerätename (heizung), zu lesender Wert (state) und ein Standardwert der benutzt wird falls kein Wert gelesen werden konnte (off).

Die Funktion liefert entweder on oder off zurück. Weil programmieren mit Text umständlich ist, wandeln wir diesen in Codes um. Der Array fs20_c2b enthält Textwerte von FS20-Geräten und deren entsprechende Codes. Mit on bzw. off als Schlüsselwörtern können wir somit die jeweiligen Codes heraussuchen.

Schlussendlich bedeutet dies, dass $heizung_status am Ende entweder 00 an Stelle von off bzw. 11 statt on enthält.

  my @fhts=devspec2array("TYPE=FHT");;\

Hier erstellen wir einen Array der alle Geräteparameter enthält. FHEM hat eine eingebaute Funktion namens devspec2array die uns dies sehr vereinfacht. Das einzige Argument das wir angeben ist TYPE=FHT um das Ergebnis auf FHT-Geräte (die Thermostaten) zu beschränken.

  foreach(@fhts) {\
    my $ventil=ReadingsVal($_, "actuator", "101%");;\
    $ventil=(substr($ventil, 0, (length($ventil)-1)));;\
    if ($ventil > 50) {\
      $brauche_waerme=1\
    }\
    if ($ventil < 20) {\
      $ventile_im_leerlauf++\
    }\
  }\

In dieser Schleife testen wir nacheinander alle FHT auf die Stellung der Ventilantriebe (actuator). Die For-Schleife geht den Array (@fhts) durch, den wir weiter oben definiert haben. Für jeden FHT lesen wir anschliessend die Ventilstellung mittels ReadingsVal aus. Der erste Parameter $_ ist ein Platzhalter für die Schleifenvariable, dem aktuell zu lesenden FHT-Gerät in unserem Fall. Da Ventilstellungen bereits Zahlenwerte sind, brauchen wir den $fs20_c2b an dieser Stelle nicht. Allerdings müssen wir das Prozentzeichen loswerden, d.h. beispielsweise 10% in 10 umwandeln. Dazu verwenden wir substr und extrahieren den Textwert von Position 0 bis zur Vorletzten Stelle (Länge - 1) des Originaltexts. Konkret schneiden wir so das letzte Zeichen weg.

Nun können wir mit der Ventilstellung Rechnungen und Vergleiche durchführen. Zuerst testen wir ob der Wert grösser als 50 ist (d.h. dass der Radiator mehr als zur Hälfte geöffnet ist). Ist dies der Fall, wird die Variable $brauche_waerme auf 1 gesetzt.

Falls die Ventilstellung weniger als 20 beträgt, erhöhen wir die Variable $ventile_im_leerlauf um 1.

Schlussendlich bedeutet dies, dass am Ende der Schleife $brauche_waerme 1 beträgt falls einer oder mehrere FHT Wärme beantragen und $ventile_im_leerlauf die Anzahl der FHT, die keine Wärme benötigen.

  if ($brauche_waerme != 0) {\
    Log(3,"Wärme benoetigt. Vorheriger Heizungsstatus: " . $heizung_status);;\
    fhem("set heizung on") if ($heizung_status == 00)\
  } 

Jetzt können wir zur Tat schreiten. Falls wir weiter oben entschieden haben, dass Wärme benötigt wird, schreiben wir eine kurze Nachricht mit dem vorherigen Status der Heizung in das Logbuch. Das erste Argument von Log ist die Logstufe. Wichtige Meldungen haben die Stufe 1, weniger wichtige haben höhere Stufen. Das zweite Argument ist der zu druckende Text, in unserem Fall eine einzelner Satz gefolgt vom bisherigen Heizugsstatus den wir zuvor gespeichert hatten. Die eigentlichen Befehle an FHEM setzen wir mit der fhem Funktion ab. Dies erlaubt uns, normale FHEM-Befehle wie set, get, trigger etc. zu benutzen. In unserem Fall setzen wir das FS20-Gerät heizung auf on, aber nur falls die Heizung vorher ausgeschaltet war.

  else {\
    if ($ventile_im_leerlauf == @fhts) {\
      Log(3,"Keine Wärme (mehr) benoetigt. Vorheriger Heizungsstatus: " . $heizung_status);;\
      fhem("set heater off") if ($heizung_status == 11)\
    }
     else {\
      Log(3,"Heizbedarf: " . $ventile_im_leerlauf . " of " . @fhts . " actuators are idle.")\
    }\
  }\
}

Dieser letzte Abschitt wird ausfgeführt, falls keine Heizung benötigt wurde. In diesem Moment müssen wir abklären, ob die Heizung ausgeschaltet werden soll. Dazu vergleichen wir die Anzahl der FHT die keine Wärme mehr benötigen mit der Gesamtzahl der FHT-Geräte. @fhts ist der Array der FHT-Geräte. So geschrieben bekommen wir die Grösse des Arrays zurück und das ist genau was wir wollen. Falls die Zahlen identisch sind bedeutet dies, dass sich alle FHT einig sind, die Heizung auszuschalten. Wir schreiben wieder eine Nachricht ins Logbuch und schalten die Heizung aus, aber wieder nur falls Sie vorher eingeschaltet war.

Der einzige verbleibende Fall den wir noch behandeln müssen ist jener, in dem die Heizung unverändert bleiben soll. Wir fangen diese Bedingung mit dem letzten else-Statement ab und drucken eine Nachricht mit dem aktuellen Abstimmungsresultat zur Abschaltung der Heizung aus. Damit ist die notify abgeschlossen und wir können diese nun entweder durch Eintippen von trigger n_heizung in die Kommando-Box vom FHEM-Interface oder als Teil eines Zeitbefehls benutzen.

define a_heizung at +*00:10:00 trigger n_heizung

Um das Makro alle 10 Minuten ablaufen zu lassen definiren wir eine at-Struktur namens a_heizung. Das Pluszeichen lässt den Befehl in 10 Minuten (an Stelle von zehn Minuten nach Mitternacht) ausführen und * wiederholt den Befehl regelmässig. Konkret führt dies zur Ausführung unseres Makros alle 10 Minuten. Dies bestimmt auch die minimale Einschaltzeit der Heizung. Eine häufigere Ausführung des Makros würde zwar die Reaktionszeit der Regelung erhöhen, allerdings ist es wahrscheinlich keine gute Idee, die Heizung zu oft ein- und auszuschalten.

Resultat

Das Beispiel unten veranschaulicht, wie das Skript die Heizung ein- und ausschaltet. Schön zu sehen sind auch die Oszillationen der Temperaturen und Ventilstellungen in den drei Räumen.

Fhem heating example.png