Entwickelt für CCU2 mit Firmware 2.7.8

Die Fußbodenheizung in meinem Haus (Baujahr 2006) wurde bisher von thermischen Stellantrieben mit Bimetallthermostaten gesteuert. Dies funktionierte auch ganz gut, leider konnten damit keine individuellen Absenkzeiten vorgegeben werden. Die Heizung lief Tag und Nacht mit derselben Temperatur, die Zirkulationspumpe war rund um die Uhr eingeschaltet (ca. 90W). Als jetzt einige der Stellantriebe den Geist aufgaben, war es an der Zeit, die Fußbodenheizung mit der HomeMatic zu steuern.

Erst einmal musste ich übers Internet herausfinden, wie eine Fußbodenheizung funktioniert. Sie ist vom thermischen Verhalten nicht mit der Radiatorheizung vergleichbar. Eine Fußbodenheizung muß über die Wärmetauscherschlangen eine große Betonmenge erwärmen, welche eine große thermische Trägheit (5-10 Stunden für Aufheizen/Abkühlen) hat. Eine normale Proportionalregelung - wie bei den Radiatoren - scheidet damit aus.

Die Vorlauftemperatur muß mit dem Mischer auf die Temperatur des wärmsten Raumes eingestellt werden. Mit den Stellmotoren werden dann die Heizkreise der kühler gewünschten Räume komplett geöffnet/geschlossen, bis die eingestellte Temperatur erreicht ist. Will man eine Nachtabsenkung haben, sollte man am Morgen die Fußbodenheizung bereits 3-4 Stunden vor dem Aufstehen hochfahren, sonst hat man einen kalten Fußboden. Eine Komplettabschaltung der Fußbodenheizung über Nacht ist nicht sinnvoll.

Zusammenfassend müssen folgende Dinge berücksichtigt werden:

  • Vorlauftemperatur konstant auf die höchste gewünschte Temperatur aller Heizkreise einstellen (z.B. 25 °C)
  • Steuerung der Heizkreis mit thermischen Stellmotoren 230VAC
  • Zweipunktregelung (Ein/Aus) der Stellmotoren über Raumthermostate HomeMatic und Aktuatoren
  • Eine Temperaturabsenkung beim Lüften ist sinnlos, weil die Fußbodenheizung gar nicht so schnell folgen kann
  • Nur eine geringe Nachtabsenkung wählen, weil die thermische Trägheit des Bodens so hoch ist.
  • Gibt es einem Raum mehrere Heizkreise, so sind diese immer gemeinsam anzusteuern. In meinem Wohnzimmer waren es vier Heizkreise im Wohnzimer, welche über einen HM-Ausgang zusammengefasst wurden
  • Die Zirkulationspumpe wird immer dann ausgeschaltet, wenn alle Heizkreise geschlossen sind

Vorgaben

Die Fußbodenheizung soll folgende Dinge berücksichtigen:

  • Heizperiode Sommer/Winter
  • Feier- und Urlaubstage führen zu einem anderen Heizprofil als Wochentags
  • Bei Abwesenheit ein abgesenktes Temperaturprofil verwenden

Sommer: Heizung aus, jede Woche einmal Entkalkungsfahrt der Ventile
Winter: Heizungsregelung aktiv, keine Entkalkungsfahrten

Anwesenheit: Heizungsregelung aktiv
Abwesenheit: angesenktes Profil bis wieder Anwesenheit gegeben ist

Wochentags: eigene Heizprofile für jeden Wochentag
Feier-/Urlaubstag: eigene Heizprofile

 

HomeMatic Hardware für die Fußbodenheizung

Aus diesen Anforderungen ergeben sich folgende Module der HomeMatic mit der CCU2:

  • 8x Buderus-Stellmotoren Normally-Closed, 230V, 1,8W
  • 5x Raumthermostat HM-CC-TC (ohne Stellmotor, einer pro Raum)
  • 1x RS485-Modul HMW-IO-12-Sw14-DR mit 12 Eingängen und 14 Ausgängen
  • 1x RS485-LAN-Gateway (max. 1 pro CCU2 möglich!)
  • 1x RS485-Abschlusswiderstand  HMW-Sys-Tm
  • 1x Hutschienennetzteil 24V/60Watt (Meanwell)
  • 2x Relaisplatinen mit Solid-State-Relais für das Schalten der 230V-Stellmotoren

Ich habe mich für RS485 entschieden, weil das HomeMatic-Modul sehr viele Ein- und Ausgänge hat und mein komplett aus Metall bestehender Heizkreisverteiler keine Funkverbindung zur HomeMatic zuläßt. Da meine Stellmotoren mit 230V arbeiten, benötigte ich noch eine Relais-Platine, da die HomeMatic keine Netzspannung schalten kann. Hier habe ich mich für eine sehr preisgünstige Lösung aus China (Ebay) entschieden, welche 2 bzw. 8 Solid-State-Relais für maximal 2A bietet und deren Logikeingänge per TTL-Pegel ansteuerbar ist. Mit etwa 9€ (2 SSR) und 16€ (8 SSR) ist das sehr günstig und verschleißfrei. Da die HomeMatic nur Open Collector Ausgänge hat, mussten auf der Relaisplatine noch jeweils ein 2,2kOhm-Pullup-Widerstand gegen 5V (kleines Platinennetzteil) gelötet werden. Durch den OC-Ausgang kehrt sich allerdings die Steuerlogik um:

  • HomeMatic = True bedeutet Stellmotor Aus
  • HomeMatic = False bedeutet Stellmotor Ein

Das kann man aber im Skript berücksichtigen. Bei der 2-Punkt-Regelung benötigt man noch einen Temperaturparameter, die Schalthytherese. Das ist der Unterschied in Grad Celsius zwischen Ein- und Ausschalten der Stellmotoren. Ich habe bei mir empirisch eine Hytherese von 0,2°C ermittelt.

Bisher lief die Zirkulationspumpe mit 90W Leistung permanent. Das bedeutet einen nicht unerheblichen Energieverbrauch. Per HomeMatic wird die Pumpe nur noch dann eingeschaltet, wenn mindestens einer der Heizkreise geöffnet ist. Im Skript wird dies durch die Variable "pumpValue" vorgenommen, welche am Anfang des Skripts auf "off" gesetzt wird. Beim Abarbeiten der einzelnen Heizkreise wird die Variable dann auf "on" gesetzt, wenn das zugeordnete Heizkreisventil "on" ist. Eine klassische ODER-Schaltung, welche für beliebig viele Heizkreise erweiterbar ist.

Um in der CCU2 und auf dem Smartphone eine übersichtliche Anzeige zu erhalten, wird pro Heizkreis eine String-Systemvariable mit Ist-, Solltemperatur und Heizkreiszustand belegt.

In der aktuellen Version 0.8 wird die Variable "Heizperiode" noch nicht ausgewertet. Die "WriteLine"-Kommandos werden nur fürs Debugging benötigt und sind deshalb im Normalbetrieb auskommentiert.

Sehr informativ für meine Entwicklung war der Forusbeitrag http://homematic-forum.de/forum/viewtopic.php?f=31&t=5233

 

Fußbodenheizung HomeMatic Programm

Das Skript wird alle 10 Minuten durch das Programm "FBH-Thermostat" aufgerufen:

Programm Fußbodenheizung HomeMatic

Details des Programms:

Programm Fußbodenheizung HomeMatic

Zeiteinstellungsdetails:

Programm Fußbodenheizung HomeMatic

Die Systemvariablen werden aus den einzelnen Messwerten und Stati zusammengesetzt. In der WebUI der HomeMatic werden die Variablen folgendermaßen dargestellt:

Anzeige Heizkreis

Anzeige Pumpe

 

Fußbodenheizung HomeMatic-Skript

!-------------------------------------------------------------------------------------------
! HM-Skript Fußbodenheizung Rev.0.6, 15.12.2013 / 03:11 A. Kriwanek
!-------------------------------------------------------------------------------------------
! Systemvariablen (String) anlegen:
!     FBH EG-Diele
!     FBH EG-Küche
!     FBH EG-WC
!     FBH EG-Wohnbereich
!     FBH OG-Bad
!     FBH Pumpe
!
! Systemvariablen (Boolean) anlegen:
!     Heizperiode
!
!-------------------------------------------------------------------------------------------
! Globale Variablen definieren:
!-------------------------------------------------------------------------------------------
real THyst = 0.2;             		! Hysterese für Ventilschluß in °C vorgeben
boolean PumpValue = 1;        		! Set pump 1=off, 0=on
real TIst;												! Aktuelle Raumtemperatur
real TSoll;												! Solltemperatur
integer NachkommaStellen = 1; 		! Anzahl Nachkommastellen bei Temperaturen
string stringPart = "";						! Zwischenstring eines float-Wertes
string stringResult = "";     		! Kompletter Ergebnisstring eines Heizkreises
integer DotPos;										! Position des Dezimalpunktes
var Valve;												! FBH-Ventilstellung

!-------------------------------------------------------------------------------------------
! FBH EG-Diele:
!-------------------------------------------------------------------------------------------
!WriteLine("<<< EG-Diele >>>");

! >>> Ist-Temperatur auslesen:
TIst = dom.GetObject("BidCos-RF.JEQ0225263:1.TEMPERATURE");
stringPart = TIst.Value().ToString();
DotPos = stringPart.Find(".");
stringResult = stringPart.Substr(0, DotPos + NachkommaStellen + 1) # "°C (Soll ";
!Write("Ist-Temperatur:"); !WriteLine(TIst.Value());

! >>> Soll-Temperatur auslesen:
TSoll = dom.GetObject("BidCos-RF.JEQ0225263:2.SETPOINT");
stringPart = TSoll.Value().ToString();
DotPos = stringPart.Find(".");
stringResult = stringResult # stringPart.Substr(0, DotPos + NachkommaStellen + 1) # "°C), ";
!Write("Soll-Temperatur:"); !WriteLine(TSoll.Value());

! >>> Heizkreisventil ansteuern:
Valve = dom.GetObject("BidCos-Wired.KEQ0182073:10.STATE");

! Neuen Ventilstatus berechnen und setzen:
var mySysVar = dom.GetObject('FBH EG-Diele');
if(TIst.Value() < TSoll.Value()) {
  	Valve.State(0);
  	PumpValue = 0;
  	stringResult = stringResult # "EIN";
  	mySysVar.Variable(stringResult);
  	!WriteLine("Heizkreis ein!");
}

if(TIst.Value() > (TSoll.Value() + THyst)) {
  	Valve.State(1);
    stringResult = stringResult # "AUS";
  	mySysVar.Variable(stringResult);
  	!WriteLine("Heizkreis aus!");
}

!-------------------------------------------------------------------------------------------
! FBH EG-WC:
!-------------------------------------------------------------------------------------------
!WriteLine("<<< EG-WC >>>");

! >>> Ist-Temperatur auslesen:
TIst = dom.GetObject("BidCos-RF.JEQ0225289:1.TEMPERATURE");
stringPart = TIst.Value().ToString();
DotPos = stringPart.Find(".");
stringResult = stringPart.Substr(0, DotPos + NachkommaStellen + 1) # "°C (Soll ";
!Write("Ist-Temperatur:"); !WriteLine(TIst.Value());

! >>> Soll-Temperatur auslesen:
TSoll = dom.GetObject("BidCos-RF.JEQ0225465:2.SETPOINT");
stringPart = TSoll.Value().ToString();
DotPos = stringPart.Find(".");
stringResult = stringResult # stringPart.Substr(0, DotPos + NachkommaStellen + 1) # "°C), ";
!Write("Soll-Temperatur:"); !WriteLine(TSoll.Value());

! >>> Heizkreisventil ansteuern:
Valve = dom.GetObject("BidCos-Wired.KEQ0182073:9.STATE");

! Neuen Ventilstatus berechnen und setzen:
var mySysVar = dom.GetObject('FBH EG-WC');
if(TIst.Value() < TSoll.Value()) {
  	Valve.State(0);
  	PumpValue = 0;
  	stringResult = stringResult # "EIN";
  	mySysVar.Variable(stringResult);
  	!WriteLine("Heizkreis ein!");
}

if(TIst.Value() > (TSoll.Value() + THyst)) {
  	Valve.State(1);
    stringResult = stringResult # "AUS";
  	mySysVar.Variable(stringResult);
  	!WriteLine("Heizkreis aus!");
}

!-------------------------------------------------------------------------------------------
! FBH EG-Küche:
!-------------------------------------------------------------------------------------------
!WriteLine("<<< EG-Küche >>>");

! >>> Ist-Temperatur auslesen:
TIst = dom.GetObject("BidCos-RF.JEQ0225465:1.TEMPERATURE");
stringPart = TIst.Value().ToString();
DotPos = stringPart.Find(".");
stringResult = stringPart.Substr(0, DotPos + NachkommaStellen + 1) # "°C (Soll ";
!Write("Ist-Temperatur:"); !WriteLine(TIst.Value());

! >>> Soll-Temperatur auslesen:
TSoll = dom.GetObject("BidCos-RF.JEQ0225465:2.SETPOINT");
stringPart = TSoll.Value().ToString();
DotPos = stringPart.Find(".");
stringResult = stringResult # stringPart.Substr(0, DotPos + NachkommaStellen + 1) # "°C), ";
!Write("Soll-Temperatur:"); !WriteLine(TSoll.Value());

! >>> Heizkreisventil ansteuern:
Valve = dom.GetObject("BidCos-Wired.KEQ0182073:11.STATE");

! Neuen Ventilstatus berechnen und setzen:
var mySysVar = dom.GetObject('FBH EG-Küche');
if(TIst.Value() < TSoll.Value()) {
  	Valve.State(0);
  	PumpValue = 0;
  	stringResult = stringResult # "EIN";
  	mySysVar.Variable(stringResult);
  	!WriteLine("Heizkreis ein!");
}

if(TIst.Value() > (TSoll.Value() + THyst)) {
  	Valve.State(1);
    stringResult = stringResult # "AUS";
  	mySysVar.Variable(stringResult);
  	!WriteLine("Heizkreis aus!");
}

!-------------------------------------------------------------------------------------------
! FBH OG-Bad:
!-------------------------------------------------------------------------------------------
!WriteLine("<<< OG-Bad >>>");

! >>> Ist-Temperatur auslesen:
TIst = dom.GetObject("BidCos-RF.JEQ0225453:1.TEMPERATURE");
stringPart = TIst.Value().ToString();
DotPos = stringPart.Find(".");
stringResult = stringPart.Substr(0, DotPos + NachkommaStellen + 1) # "°C (Soll ";
!Write("Ist-Temperatur:"); !WriteLine(TIst.Value());

! >>> Soll-Temperatur auslesen:
TSoll = dom.GetObject("BidCos-RF.JEQ0225453:2.SETPOINT");
stringPart = TSoll.Value().ToString();
DotPos = stringPart.Find(".");
stringResult = stringResult # stringPart.Substr(0, DotPos + NachkommaStellen + 1) # "°C), ";
!Write("Soll-Temperatur:"); !WriteLine(TSoll.Value());

! >>> Heizkreisventil ansteuern:
Valve = dom.GetObject("BidCos-Wired.KEQ0182073:8.STATE");

! Neuen Ventilstatus berechnen und setzen:
var mySysVar = dom.GetObject('FBH OG-Bad');
if(TIst.Value() < TSoll.Value()) {
  	Valve.State(0);
  	PumpValue = 0;
  	stringResult = stringResult # "EIN";
  	mySysVar.Variable(stringResult);
  	!WriteLine("Heizkreis ein!");
}

if(TIst.Value() > (TSoll.Value() + THyst)) {
  	Valve.State(1);
    stringResult = stringResult # "AUS";
  	mySysVar.Variable(stringResult);
  	!WriteLine("Heizkreis aus!");
}

!-------------------------------------------------------------------------------------------
! FBH EG-Wohnbereich:
!-------------------------------------------------------------------------------------------
!WriteLine("<<< OG-Bad >>>");

! >>> Ist-Temperatur auslesen:
TIst = dom.GetObject("BidCos-RF.JEQ0226105:1.TEMPERATURE");
stringPart = TIst.Value().ToString();
DotPos = stringPart.Find(".");
stringResult = stringPart.Substr(0, DotPos + NachkommaStellen + 1) # "°C (Soll ";
!Write("Ist-Temperatur:"); !WriteLine(TIst.Value());

! >>> Soll-Temperatur auslesen:
TSoll = dom.GetObject("BidCos-RF.JEQ0226105:2.SETPOINT");
stringPart = TSoll.Value().ToString();
DotPos = stringPart.Find(".");
stringResult = stringResult # stringPart.Substr(0, DotPos + NachkommaStellen + 1) # "°C), ";
!Write("Soll-Temperatur:"); !WriteLine(TSoll.Value());

! >>> Heizkreisventil ansteuern:
Valve = dom.GetObject("BidCos-Wired.KEQ0182073:12.STATE");

! Neuen Ventilstatus berechnen und setzen:
var mySysVar = dom.GetObject('FBH EG-Wohnbereich');
if(TIst.Value() < TSoll.Value()) {
  	Valve.State(0);
  	PumpValue = 0;
  	stringResult = stringResult # "EIN";
  	mySysVar.Variable(stringResult);
  	!WriteLine("Heizkreis ein!");
}

if(TIst.Value() > (TSoll.Value() + THyst)) {
  	Valve.State(1);
    stringResult = stringResult # "AUS";
  	mySysVar.Variable(stringResult);
  	!WriteLine("Heizkreis aus!");
}

!-------------------------------------------------------------------------------------------
! Pumpe abhängig von allen Heizkreisen berechnen:
!-------------------------------------------------------------------------------------------
var Pump = dom.GetObject("BidCos-Wired.KEQ0182073:7.STATE");

!WriteLine("");

var mySysVar = dom.GetObject('FBH Pumpe');

if(PumpValue == 0) {
  !WriteLine("Pumpe ein!");
  mySysVar.Variable("EIN");
  Pump.State(0);
} else {
  !WriteLine("Pumpe aus!");
  mySysVar.Variable("AUS");
  Pump.State(1);
}

! ----- Ende Skript -----

 

Erfahrungen und Probleme

Das Skript funktioniert einwandfrei, aber das RS485-Modul stieg mehrmals pro Tag aus. Der Fehler ist inzwischen gefunden: der HM-RS485-LAN-Adapter arbeitet nicht mit einem TP-Link-WiFi-Client zusammen. Der LAN-Adapter wird jetzt über einen Devolo Powerline-Adapter angeschlossen und alles funktioniert perfekt.

Die Regelung funktioniert einwandfrei, die Pumpe wird auch richtig geschaltet. Das Skript hat eine Laufzeit von etwa 10 Sekunden.

Nach jedem Reset der CCU2 fiel ein weiteres Problem auf: Es dauerte bis zu 24 Stunden, bis die Raumthermostate einen Sollwert zur Verfügung stellten. Bis dahin wurde bei jedem Sollwert 0°C abgezeigt und die Heizung blieb kalt. In den Foren bin ich schließlich fündig geworden: http://homematic-forum.de/forum/viewtopic.php?f=27&t=8258#p57994

Die Raumthermostate geben auf Grund der Batterieschonung ihre Sollwerte nur bei einer Änderung (z.B. Drehen am Stellrad oder Wechsel im Zeitprogramm) an die CCU2 zurück, nicht mit jeder Ist-Wert-Übertragung. Das ist für mich echt ein Bug. Man kann sich aber genauso behelfen, wie erwähnten Forumsbeitrag beschrieben - man führt Soll-Wert-Systemvariablen ein, mit deren Werten beim Boot die Thermostate neu gesetzt werden.

 

Geplante Erweiterungen für Script 1.00

In der nächsten Version (Januar 2014) sind folgende Erweiterungen für 1.00 geplant:

  • Heizkreise und Pumpe aus bei Heizperiode "Sommer" (in Arbeit)
  • Berücksichtigung der Systemvariablen "Anwesenheit" zum Herunterfahren der Heizungstemperatur (in Arbeit)
  • Partymodus für erhöhte Temperatur bei Anwesenheit von Gästen
  • Automatische Entkalkungsfahrt der Ventile einmal pro Woche (analog den Thermostaten der Radiatoren) (in Arbeit)
0
0
0
s2smodern