Als erstes suche ich mir meine Kanäle zusammen, die die Heizung steuern.
- Haushaltskeller.Heizung.Waermeanforderung ist der Aktor, der den Brenner schaltet
- Haushaltskeller.Heizung.Vorlauftemperatur ist der Temperaturfühler
Eine Heizungssteuerung unter Einbeziehung der Raumtemperatur
Auf dieser Seite
Mein Wärmebedarfsrelais war ganz OK, meine Vorlauftemperatursteuerung war ziemlich gut, aber ein Problem gab es bei beiden: Da sie sich ausschließlich an den Ventilantrieben orientierten, die häufig etwas träge auf Temperaturänderungen reagieren, wurde es beim Aufheizen von Räumen oft zu warm. Ich bin daher meinem früher geäußerten Grundsatz untreu geworden und habe ein Script entwickelt, das sich primär an der Raumtemperatur orientiert.
Hier also mein raumtemperaturdifferenzgesteuertes Vorlauftemperaturregelungsscript.
Neue Script-Funktionen
Mit Firmware 2.29.22 wurden neue Funktionen in der Scriptsprache der CCU eingeführt, die auf dieser Seite genutzt werden. Achten Sie darauf, als Logikschicht-Version in den Systemeinstellungen der CCU nicht „Legacy“ zu wählen.
Wenn Sie eine ältere Firmware verwenden oder als Logikschicht-Version „Legacy“ ausgewählt haben, werden Sie Script-Fehler angezeigt bekommen, wenn Sie diese Anleitung umsetzen. Die Programme werden nicht funktionieren.
Aktualisieren Sie die Firmware Ihrer CCU! Wählen Sie „Standard“ als Logikschicht-Version aus!
Variablen in HomeMatic-Scripten
Die CCU hatte früher ein Limit von maximal 200 Variablen, das mit Firmware-Version 2.29.18 aufgehoben wurde. Dieses Limit bezog sich auf alle Variablen, die in allen Scripten verwendet werden. Gemeint sind Variablen, die direkt im Script definiert werden: object x; object y; var z;
Wenn Scripte nicht mehr funktionieren und bei der Prüfung unerklärliche Syntax-Fehler auftreten, sollte versuchsweise dieses Programm wieder gelöscht oder deaktiviert werden – oder, noch besser, auf die aktuelle Firmware-Version aktualisiert werden.
Strings in HomeMatic-Scripten
Durch String-Verwendung in HomeMatic-Scripten kann die CCU fehlerhaft arbeiten, instabil werden oder sogar abstürzen. Grundsätzlich gilt: Je öfter mit Strings hantiert wird, desto eher führt dies zu Problemen.
Ich empfehle daher, nach Umsetzung dieser Anleitung die CCU unter Beobachtung zu halten.
Benennung von Systemvariablen
Prinzipiell kann man Systemvariablen – so wie allen Objekten in der CCU – beliebige Namen geben, also z. B. auch Umlaute und Sonderzeichen verwenden. Ich empfehle jedoch, sich auf reguläre Buchstaben (a-z, A-Z) zu beschränken: Bei Umlauten und Sonderzeichen besteht die Gefahr, dass Systemvariablen in Scripten nicht überall gefunden werden.
Ich orientiere mich an der vorherigen Vorlauftemperatursteuerung. Der Temperaturfühler für die Vorlauftemperatur ist schon installiert (und funktioniert, nebenbei bemerkt, seit Jahren mit den mitgelieferten Batterien) und ich werde ihn weiterhin als Taktgeber nutzen, um zyklisch die Heizung auszuwerten.
Den Öffnungsgrad der Ventilantriebe verwende ich nur noch als „Hauptschalter“: Irgendwo muss irgendein Antrieb mindestens zu 10% geöffnet sein, sonst springt die Heizung nicht an. Darüber hinaus verwende ich zur Berechnung der gewünschten Vorlauftemperatur aber die Soll- und Ist-Werte der einzelnen Raumthermostate: Je größer die Differenz, desto weiter wird die Vorlauftemperatur erhöht. In der Theorie sollte ich damit einigermaßen nah an meine gewünschte Soll-Temperatur kommen, ohne sie zu weit zu überschreiten.
Und weil ich auch an meine Leser denke, plane ich auch die Auswertung von Heizkörperthermostaten gleich mit ein.
Das WebUI-Programm entspricht ungefähr dem vorherigen: Immer, wenn der Temperaturfühler für die Vorlauftemperatur seinen Status aktualisiert, wird ein Script ausgeführt.
Die eigentliche Programmlogik steckt, wie üblich, im Script.
gesamtes Script markieren / kopieren
! HomeMatic-Script ! ERWEITERTES WäRMEBEDARFSRELAIS MIT VORLAUFREGELUNG ! http://www.christian-luetgens.de/homematic/programmierung/klima/vorlauf2/Vorlauf_II.htm ! Aktor für Brenner object o_heizung_state = dom.GetObject ("Haushaltskeller.Heizung.Waermeanforderung").DPByHssDP ("STATE"); object o_heizung_time = dom.GetObject ("Haushaltskeller.Heizung.Waermeanforderung").DPByHssDP ("ON_TIME"); ! Temperaturfühler object o_vorlauftemp = dom.GetObject ("Haushaltskeller.Heizung.Vorlauftemperatur").DPByHssDP ("TEMPERATURE"); ! temp. Variablen string s; object o_chn; object o_dev; real r_ist; real r_soll; ! Summen real r_summe = 0.0; boolean b_ventil = false; real r_anforderung; ! Anforderung berechnen foreach (s, dom.GetObject ("Heizung").EnumUsedIDs()) { o_chn = dom.GetObject (s); if (o_chn.HssType() == "WEATHER") { o_dev = dom.GetObject (o_chn.Device()); if (o_dev.HssType() == "HM-CC-TC") { r_ist = o_chn.DPByHssDP ("TEMPERATURE").Value(); r_soll = o_dev.Channels().GetAt (2).DPByHssDP ("SETPOINT").Value(); r_summe = r_summe + (r_soll - r_ist).Max (0); b_ventil = b_ventil || (r_soll >= 29.5); } } if (o_chn.HssType() == "CLIMATECONTROL_RT_TRANSCEIVER") { r_ist = o_chn.DPByHssDP ("ACTUAL_TEMPERATURE").Value(); r_soll = o_chn.DPByHssDP ("SET_TEMPERATURE").Value(); r_summe = r_summe + (r_soll - r_ist).Max (0); b_ventil = b_ventil || (r_soll >= 29.5); } if ((o_chn.HssType() == "CLIMATECONTROL_VENT_DRIVE") || (o_chn.HssType() == "CLIMATECONTROL_RT_TRANSCEIVER")) { b_ventil = b_ventil || (o_chn.DPByHssDP ("VALVE_STATE").Value() >= 10); } } r_anforderung = (20.0 + 20.0 * r_summe).Min (100.0); ! Heizung ein-/ausschalten r_ist = o_vorlauftemp.Value(); if ((r_ist > r_anforderung) || (!b_ventil)) { o_heizung_state.State (false); } else { if ((r_anforderung > r_ist + 5.0) || (o_heizung_state.Value())) { o_heizung_time.State (450); o_heizung_state.State (true); } } ! Status-Variablen setzen ! Systemvariable für berechnete Wärmeanforderung dom.GetObject ("Waermeanforderung").State (r_anforderung); ! Systemvariable für gemessene Vorlauftemperatur dom.GetObject ("Vorlauftemperatur").State (o_vorlauftemp.Value()); ! Systemvariable für Heizungsstatus object o_heizungssteuerung = dom.GetObject ("Zentralheizung"); if (o_heizungssteuerung.Value() != o_heizung_state.Value()) { o_heizungssteuerung.State (o_heizung_state.Value()); } ! Ende des Scripts
Das Script ist zwar fast selbsterklärend, aber vielleicht sollte ich doch noch ein paar Worte darüber verlieren.
Kanäle bestimmen
Als erstes suche ich mir meine Kanäle zusammen, die die Heizung steuern.
Variablen deklarieren
Variablen, die in HomeMatic-Scripten verwendet werden, müssen vor ihrer Benutzung deklariert werden. Das passiert als nächstes.
Einige Variablen werden nur temporär in irgendwelchen Schleifen gebraucht, der Rest sammelt die akkumulierten Daten meiner Raumthermostate ein.
Anforderung berechnen
Der Hauptteil des Scripts besteht aus einer Schleife.
Meine Heizungskomponenten liegen im Gewerk Heizung. Dieses Gewerk gehe ich der Reihe nach durch, um alle Komponenten auszuwerten. Theoretisch könnte ich auch durch sämtliche Kanäle auf der CCU gehen – das Script könnte auch damit umgehen –, doch das würde aufgrund der Anzahl meiner Geräte etwas auf die Performance gehen. Also: nur Heizung wird bearbeitet.
Jeder Kanal wird darauf geprüft, ob er zu einem Raumthermostat gehört. Wenn ja, werden Soll- und Ist-Wert ausgelesen und in r_summe addiert – natürlich nur, wenn der Soll-Wert größer ist als der Ist-Wert. Zusätzlich wird geprüft, ob der Thermostat auf 29,5 °C oder mehr steht. Wenn ja, wird b_ventil auf true gesetzt. Dazu komme ich später.
Meine Kombination aus Raumthermostat und Ventilantrieb ist ja etwas veraltet, darum spiele ich dasselbe Spiel danach für die etwas neueren Heizkörperthermostate durch. Theoretisch sollte das Script also auch unverändert mit diesen laufen.
Zum Schluss prüfe ich, ob es sich beim aktuell bearbeiteten Kanal um einen Ventilantrieb oder einen Heizkörperthermostat handelt. Wenn ja, prüfe ich den Öffnungsgrad. Das ist der „Hauptschalter“, den ich eingangs beschrieben hatte: Wenn kein Antrieb auf mindestens 10% Ventilöffnung steht, bleibt die Heizung aus. Ausnahme ist, wenn irgendwo die Soll-Temperatur größer oder gleich 29,5 °C ist: Dann geht die Heizung immer an, weil ich dann sicher bin, dass irgendwo ein Ventil offen ist, auch wenn es womöglich noch nicht seinen Status an die CCU gemeldet hat.
Soll-Vorlauftemperatur
Die gewünschte Vorlauftemperatur beträgt bei mir mindestens 20 °C. Dazu addiere ich für 0,1 °C Differenz bei der gewünschten Raumtemperatur 2 °C Soll-Vorlauftemperatur. Aus ästhetischen Gründen begrenze ich den Maximalwert auf 100 °C – soviel schafft meine Heizung nicht, dieser Wert entspricht also Dauerbetrieb.
Rechenbeispiel:
Brenner schalten
Fast zum Schluss wird der Brenner geschaltet. Wenn die gemessene Vorlauftemperatur höher ist als die gewünschte Soll-Vorlauftemperatur, wird der Aktor sofort ausgeschaltet – und zwar immer, auch wenn er schon ausgeschaltet ist. Ich möchte sichergehen, dass die Heizung nicht ewig weiterläuft, weil der Aktor vielleicht seinen letzten Status nicht korrekt übermittelt hat. Das geht zwar etwas auf den Duty Cycle, aber sicher ist sicher.
Wenn die Ist-Temperatur niedriger oder gleich der Soll-Temperatur ist, wird geprüft, ob die Ist-Temperatur mindestens 5 °C unter der Soll-Temperatur ist oder ob der Brenner schon läuft. Die 5 °C dienen als Hysterese: Wenn die Soll-Temperatur erreicht ist, muss die Ist-Temperatur mindestens 5 °C abfallen, bevor die Heizung wieder anspringt. Wenn der Brenner schon läuft, läuft er weiter.
Damit auch bei Funkstörungen die Heizung nicht dauerhaft läuft, setze ich vor dem Einschalten eine Einschaltzeit. 450 Sekunden entsprechen 7,5 Minuten. Bei rund 2,5 Minuten Aktualisierungsintervall des Temperaturfühlers bedeutet das, dass nach drei verpassten Aktualisierungen die Heizung sicherheitshalber abschaltet.
Statusvariablen
Der letzte Teil des Programms füllt nur einige Systemvariablen. Ich lasse mir damit auf der WebUI-Startseite und auf meiner Wetterstation die aktuelle Wärmeanforderung, Vorlauftemperatur und den Brennerstatus anzeigen.
Wer diese Variablen nicht definiert hat, muss den Teil ersatzlos weglassen. Es ist reine Optik und für die Funktion nicht erforderlich, kann aber bei der Fehlersuche hilfreich sein.
Ich habe das Programm jetzt einige Zeit in Betrieb und bisher macht es seinen Job recht gut. Hier eine Kurve, als ich mal einen Tag abwesend war und absolut nichts die Heizung gestört hat:
Die grüne Linie ist die Wärmeanforderung, also die Soll-Vorlauftemperatur. Sie schwankt im Tagesverlauf etwas, je nachdem, wie weit die Temperatur in den einzelnen Räumen von der Soll-Temperatur entfernt ist. Die rote Linie ist die Vorlauftemperatur – gut zu sehen, wie der Brenner immer wieder anspringt, kurz bis zur Soll-Temperatur aufheizt und dann mindestens 5 °C abkühlt.
Um 08:00 und 15:00 lasse ich die Heizung abschalten, weil jeweils eine Stunde später gelüftet wird, wenn ich zu Hause bin. Bei Abwesenheit natürlich nicht, also werden die Raumthermostate wieder hochgedreht – das passiert sonst erst, wenn die Fenster wieder geschlossen sind. Da das Haus in der einen Stunde jeweils etwas abgekühlt ist, ist der Wärmebedarf etwas größer, aber innerhalb einer weiteren knappen Stunde geht alles wieder seinen geregelten Gang.
Die Raumtemperaturen selbst werden größtenteils recht gut getroffen. Nur im Gäste-WC natürlich nicht. Keine Temperaturregelung der Welt kann den zu kleinen Heizkörper und die zu schlechte Isolierung ausgleichen.
Eine Nebenwirkung, die man auf der obigen Kurve bereits sieht, ist, dass der Brenner relativ häufig eingeschaltet wird. Der Heizung sollte das eigentlich nicht schaden, da der Aktor letztlich nur einen Eingang der Heizungselektronik schaltet, die dann selbstständig entscheidet, ob sie nun wirklich gerade brennen mag oder lieber nicht. Ein Ausweg wäre, die Hysterese zu erhöhen: Wenn die Vorlauftemperatur nicht um 5 °C fallen muss, sondern um 10 °C, dauert das entsprechend länger und sie wird später wieder eingeschaltet. Das bedeutet natürlich auch, dass in der Zeit die Heizkörper weiter abkühlen und die Temperatur im Haus damit stärker schwankt.
Eine zweite Nebenwirkung: In meinem Gäste-WC, wo der kleine Heizkörper eh nicht gegen die schlechte Isolierung ankommt, wird niemals genug Wärme abgeliefert, um die Soll-Temperatur zu erreichen. Der Ventilantrieb ist entsprechend praktisch dauerhaft sehr weit aufgedreht. Andererseits war genau dieser Raum der Hauptgrund, warum meine bisherige Steuerung sehr kräftig geheizt hat und damit in allen anderen Räumen die Soll-Temperatur überschritten wurde.
Einen Tod muss man sterben, wie es so schön heißt. Ich wähle den energiesparenden Kältetod auf dem WC, statt den Rest des Hauses zur Sauna zu machen.