Drucken

Meine Fußbodenheizung (Warmwasser) wurde bisher mit Busch-Jäger Bimetall-Thermostaten gesteuert. Das lief zwar gut, aber es gab keine Möglichkeit für Nachtabsenkung oder Abwesenheitsschaltung. Als SmartHome-Freak will ich aber alles per Tablett steuern.

Es folgten einige Versuche mit fertigen Elektronik-Thermostaten, MAX! und HomeMatic, aber nichts war wirklich befriedigend - teils auch sehr teuer. Seit längerer Zeit setze ich im Haus Shellies für die Lichtschalter ein, welche per WiFi angebunden sind und in eine Unterputzdose passen. Diese sind preisgünstig, zuverlässig und können per MQTT in OpenHAB eingebunden werden.

Den Shelly HT setze ich nicht ein, weil er ein Standalone-Gerät mit Batteriebetrieb ist und deshalb nur sehr selten Temperatur-Updates an OpenHAB sendet. Seit Allterco einen Temperatursensor-Addon für den Shelly 1 anbietet, habe ich mit dem Gedanken gespielt, dieses Duo für das Thermostat zu verwenden.

 

Funktionsweise

Der Shelly 1 mit dem Addon läuft als Zweipunktregler über die "Temperature Actions". Das funktioniert auch, wenn das WLAN oder OpenHAB nicht funktionieren sollten. Die Schaltschwellen werden dem Shelly 1 über HTTP-Befehle aus OpenHAB vorgegeben. MQTT funktioniert nicht für diese Parameter, evtl. einmal in einer späteren Firmware.

Der Shelly gibt alle Messwerte und die Relaisstellung per MQTT an OpenHAB zurück, so dass sie dort in der Sitemap angezeigt werden können. Das Relais steuert meine Heisswasserventile im Heizverteiler an.

Es gibt ein paar globale virtuelle Schalter für alle Thermostatventile:

Meine Fußboden-Heizungspumpe ist leider nicht elektronisch geregelt, weshalb sie früher den gesamten Winter hindurch lief. Die Pumpe hat einen eigenen Shelly 1 erhalten, welcher von der Gruppe aller Thermostatventile gesteuert wird. Ist mindestens ein Ventil eingeschaltet, läuft auch die Pumpe. Erst wenn alle Ventile aus sind, wird auch die Pumpe ausgeschaltet.

Hardware

Kauf-Hardware

Die Gesamtkosten für ein Thermostat betragen also 19€.

Links der Shelly 1 und rechts das Temperatursensor-Addon. Das Addon wird in die Programmierbuchse des Shelly eingesteckt.

Der Temperatursensor DS18B20 im TO92-Gehäuse

 

3D-Druck-Gehäuse

Es gibt kein passendes Thermostatgehäuse von Busch Jäger, deshalb habe ich selbst eines konstruiert - es besteht aus der Wandplatte, dem Shelly-Adapter und dem Deckel für den Sensor. Ihr könnt es bei Thingiverse herunterladen: https://www.thingiverse.com/thing:4579411

Oben der runde Shelly-Adapter, darunter die Wandplatte und die Abdeckung.

 

Software für die Shellies

Der Shelly 1 ist mit der derzeit aktuellen Shelly-Firmware 1.8.0 bestückt.

Bei der Einrichtung über die Weboberfläche muß man im Shelly die Zugangsdaten des eigene WLAN und des MQTT-Servers eingeben. Der MQTT-Server Mosquitto befindet sich mit OpenHAB auf dem Raspberry Pi.

 

Montage

Der Shelly-Adapter wird mit M3x12-Schrauben an der Wandplatte befestigt. Die Schraube in der Mitte ist eine M3x16 für die Verschraubung des Deckels. 
 Die M3-Muttern werden mit einem Lötkolben in das PLA-Gehäuse eingepresst. Das dauert nur wenige Sekunden.
Der Shelly 1 wird jetzt von oben in den Adapter gedrückt, bis er auf der Verschraubung sitzt. Der Adapter ist einige Millimeter von der Wandplatte entfernt. Dies verringert eine Wärmeübertragung des Shelly auf die Wandplatte, hinter welcher der Sensor sitzt.
Das Temperatursensor-Addon wird jetzt auf der Programmierbuchse des Shelly aufgesteckt. Die drei Drähte werden durch das Loch der Wandplatte geführt.

Auf der Vorderseite werden die drei Drähte herausgeführt. Der Busch Jäger-Rahmen passt sehr gut auf die Wandplatte.

Die Drähte werden etwas gekürzt und dann an den DS18B20 angelötet. Schrumpfschläuche verhindern einen Kurzschluss. Die Belegung:

Draht Addon Funktion DS18B20
schwarz GND  Pin 1
rot +3,3V  Pin 3
gelb Data  Pin 2

Unbedingt die Sicherung ausschalten und nachprüfen, ob die Drähte  spannungsfrei sind!

Nach Abnehmen des alten Thermostats, werden jetzt die 230V-Drähte an den Shelly angeschlossen.

Nach Festziehen und Kontrolle der Klemmen, wird der Addon aufgesteckt.
Das Modul wird in die Unterputzdose eingeschoben und die Wandplatte mit zwei Schrauben befestigt.
Der angelötete Temperatursensor wird in die Nut des Deckels eingeklemmt. Evtl. mit etwas Heißkleber sichen.

Jetzt setzt man die Busch Jäger Rahmen auf und verschraubt des Deckel mit der Zentralschraube.

Fertig! Jetzt kann man die Sicherung wieder einschalten und testen, ober der Shelly 1 per Web-Interface erreichbar ist.

 

OpenHAB Things

Jedes Thermostat ist ein eigenes Thing mit jeweils zwei Channels: Temperatur und Relais. Erstellt eine Datei things/mqtt.things mit folgendem Inhalt:

//----------------------------------------------------------------------------------
// Shelly 1 mit Temperature Addon for WZ-Thermostat
Thing mqtt:topic:HZ_WZ_FloorThermostat "Th-HZ-WZ-FloorThermostat" {
	Channels:
		Type number : chTemp 	"Temperatur" [ 
		    stateTopic="shellies/shelly1-A4CF12F3E44D/ext_temperature/0" ]
		Type switch : chRelais  "Ventilausgang" [ 
		    stateTopic="shellies/shelly1-A4CF12F3E44D/relay/0", 
		    on="on", off="off", 
		    commandTopic="shellies/shelly1-A4CF12F3E44D/relay/0/command", 
		    on="on", off="off" ]
}

Den MQTT-Pfad zum Shelly findet man am Besten mit dem "MQTT-Explorer" (Windows) heraus:

Könnt Ihr über den Windows-Store für Windows 10 herunterladen.

 

OpenHAB Items

Für jedes Thing (=Thermostat) müssen zwei Items angelegt werden. Erstellt eine Datei items/mqtt.items mit folgendem Inhalt:

// shelly1-A4CF12F3E44D
Number It_WZ_ActTemperature "Wohnzimmer Temperatur [%.1f °C]" 	                 	(gPersistMapDB, Thermostat)
    { channel="mqtt:topic:HZ_WZ_FloorThermostat:chTemp", alexa="TemperatureSensor.temperature" }

Switch It_WZ_RelaisThermostat "Wohnzimmer Thermostatventil [MAP(onoff.map):%s]"  	(gPersistMapDB, gHeatingValves)
    { channel="mqtt:topic:HZ_WZ_FloorThermostat:chRelais" }

 

Zusätzlich werden noch virtuelle Items für die Temperaturen und Tag/Nacht- bzw. Sommer/Winter-Einstellung benötigt:

//--------------------------------------------------------------------------------------------------------------------------------------------------------------------
// Fußbodenheizung mit Shelly 1 & Temperatur-Addon:
// Globale Werte:
Group:Switch:OR(ON, OFF)           gHeatingValves  "Heizventile [MAP(onoff.map):%s]"             (Home)   
Number vIt_HZ_Hysterese		  "Fußbodenheizung Hysterese [%.1f °C]" 		(gPersistMapDB)
Switch vIt_HZ_OnOff		  "Fußbodenheizung [MAP(onoff.map):%s]" 		(gPersistMapDB)
Switch vIt_HZ_DayNight		  "Fußbodenheizung Programm [MAP(heating.map):%s]" 	(gPersistMapDB)
Group Thermostat "Wohnzimmer"     {alexa="Endpoint.Thermostat"}

// Thermostat GF_LivingRoom:
Number vIt_HZ_WZ_SollTag_upper	  "Wohnzimmer Solltemperatur Tag [%.1f °C]" 		(gPersistMapDB, Thermostat)	{alexa="ThermostatController.upperSetpoint"}
Number vIt_HZ_WZ_SollTag_lower	  "Wohnzimmer Solltemperatur Tag Start [%.1f °C]" 	(gPersistMapDB)
Number vIt_HZ_WZ_SollNacht_upper  "Wohnzimmer Solltemperatur Nacht [%.1f °C]" 		(gPersistMapDB)
Number vIt_HZ_WZ_SollNacht_lower  "Wohnzimmer Solltemperatur Nacht Start [%.1f °C]" 	(gPersistMapDB)

 

OpenHAB Rules

Erstellt eine Datei rules/heating.rules mit folgendem Inhalt:

//==================================================================================
// Global Thermostat Rules:
//----------------------------------------------------------------------------------
// Nightly temperature reduction for all thermostats:
// http://www.cronmaker.com/;jsessionid=node01fm60c8kkb5fb1uiiavit2knbt5438.node0?0
// Night reduction starting everyday at 19:30
rule "FloorHeating_NightReduction"
when
    Time cron "0 30 19 1/1 * ? *"
then
	vIt_HZ_DayNight.sendCommand( 'OFF' )
	logInfo(	"FloorHeating_NightReduction", "Rule FloorHeating_NightReduction ...")
end

//----------------------------------------------------------------------------------
// Daily temperature operation for all thermostats:
// http://www.cronmaker.com/;jsessionid=node01fm60c8kkb5fb1uiiavit2knbt5438.node0?0
// Day operation starting everyday at 07:00
rule "FloorHeating_DayOperation"
when
    Time cron "0 0 7 1/1 * ? *"
then
	vIt_HZ_DayNight.sendCommand( 'ON' )
	logInfo(	"FloorHeating_DayOperation", "Rule FloorHeating_DayOperation ...")
end

//----------------------------------------------------------------------------------
// Floor Heating Pump: shellies/shelly1-A4CF12F48853
rule "FL_FloorHeatingPump"
when
	Item gHeatingValves received update
then
	if(gHeatingValves.state==ON){
		// Switch ON=pump running
		It_FL_Pump.sendCommand( "ON" ) 
		logInfo( "FL_FloorHeatingPump", "Heating ON" )
	} else {
		// Switch OFF=pump not running
		It_FL_Pump.sendCommand( "OFF" ) 
		logInfo( "FL_FloorHeatingPump", "Heating OFF" )
	}
end

//==================================================================================
// Thermostat Wohnzimmer:
//----------------------------------------------------------------------------------
// Calculate lower DAY setpoint if hysterese or upper setpoint have changed
rule "WZ_Thermostat_LowerSetpointDay"
when
    Item vIt_HZ_Hysterese changed or
	Item vIt_HZ_WZ_SollTag_upper changed
then
	var Double UpperSetpoint = ( vIt_HZ_WZ_SollTag_upper.state as Number ).doubleValue()
	var Double Hysterese     = ( vIt_HZ_Hysterese.state as Number ).doubleValue()
	var Double LowerSetpoint = UpperSetpoint - Hysterese

	vIt_HZ_WZ_SollTag_lower.sendCommand( LowerSetpoint ) 

    logInfo( "WZ_Thermostat_LowerSetpointDay", "Rule WZ_Thermostat_LowerSetpointDay: " + "TagLower= " + LowerSetpoint )
end

//----------------------------------------------------------------------------------
// Calculate lower NIGHT setpoint if hysterese or upper setpoint have changed
rule "WZ_Thermostat_LowerSetpointNight"
when
    Item vIt_HZ_Hysterese changed or
	Item vIt_HZ_WZ_SollNacht_upper changed
then
	var Double UpperSetpoint = ( vIt_HZ_WZ_SollNacht_upper.state as Number ).doubleValue()
	var Double Hysterese     = ( vIt_HZ_Hysterese.state as Number ).doubleValue()
	var Double LowerSetpoint = UpperSetpoint - Hysterese
	vIt_HZ_WZ_SollNacht_lower.sendCommand( LowerSetpoint )
	
	logInfo( "WZ_Thermostat_LowerSetpointNight", "Rule WZ_Thermostat_LowerSetpointNight: " + " NachtLower= " + LowerSetpoint )
end

//----------------------------------------------------------------------------------
// Send new values to the Shelly via HTTP if one of the values has been switched or
// The switch DAY/NIGHT has changed
rule "WZ_Thermostat_SetShelly"
when
    Item vIt_HZ_WZ_SollTag_upper changed or
	Item vIt_HZ_WZ_SollTag_lower changed or
	Item vIt_HZ_WZ_SollNacht_upper changed or
	Item vIt_HZ_WZ_SollNacht_lower changed or
	Item vIt_HZ_DayNight changed
then
	Thread::sleep(200)
	var Double UpperSetpoint 
	var Double LowerSetpoint
	if(vIt_HZ_DayNight.state==ON){
		// Switch ON=Day setpoints
		UpperSetpoint = ( vIt_HZ_WZ_SollTag_upper.state as Number ).doubleValue()
		LowerSetpoint = ( vIt_HZ_WZ_SollTag_lower.state as Number ).doubleValue()
	} else {
		// Switch OFF=Night setpoints
		UpperSetpoint = ( vIt_HZ_WZ_SollNacht_upper.state as Number ).doubleValue()
		LowerSetpoint = ( vIt_HZ_WZ_SollNacht_lower.state as Number ).doubleValue()
	}
	// Send http to Shelly:
	var String httpString = ""
	
	httpString = "http://10.2.10.56/settings/ext_temperature/0?overtemp_threshold_tC=" + String::format("%.2f",UpperSetpoint)
	sendHttpGetRequest(httpString)
	logInfo( "WZ_Thermostat_SetShelly", "Rule WZ_Thermostat_SetShelly: " + httpString )
	
	httpString = "http://10.2.10.56/settings/ext_temperature/0?undertemp_threshold_tC=" + String::format("%.2f",LowerSetpoint)
	sendHttpGetRequest(httpString)
    logInfo( "WZ_Thermostat_SetShelly", "Rule WZ_Thermostat_SetShelly: " + httpString )
end

//----------------------------------------------------------------------------------EVERY Thermostat
// Switch Shelly ON/OFF for SUMMER/WINTER switch
rule "WZ_Thermostat_HeatingOnOff"
when
	Item vIt_HZ_OnOff changed
then
	var String httpString = ""
	if(vIt_HZ_OnOff.state==ON){
		// Switch ON=heating running
		httpString = "http://10.2.10.56/settings/ext_temperature/0?overtemp_act=relay_off"
		sendHttpGetRequest(httpString)
		logInfo( "WZ_Thermostat_HeatingOnOff", "Heating ON: " + httpString )
		httpString = "http://10.2.10.56/settings/ext_temperature/0?undertemp_act=relay_on"
		sendHttpGetRequest(httpString)
		logInfo( "WZ_Thermostat_HeatingOnOff", "Heating ON: " + httpString )
	} else {
		// Switch OFF=heating switched off
		httpString = "http://10.2.10.56/settings/ext_temperature/0?overtemp_act=disabled"
		sendHttpGetRequest(httpString)
		logInfo( "WZ_Thermostat_HeatingOnOff", "Heating ON: " + httpString )
		httpString = "http://10.2.10.56/settings/ext_temperature/0?undertemp_act=disabled"
		sendHttpGetRequest(httpString)
		It_WZ_RelaisThermostat.sendCommand( OFF )
		logInfo( "WZ_Thermostat_HeatingOnOff", "Heating ON: " + httpString )
	}
end

 

OpenHAB Map

Erstellt eine Datei transform/onoff.map mit folgendem Inhalt:

ON=EIN
on=EIN
On=EIN
1=EIN
OFF=AUS
off=AUS
Off=AUS
0=AUS
NULL=undefiniert
UNDEF=undefiniert
-=undefiniert

 

OpenHAB Sitemap

Erstellt eine Datei sitemaps/heating.sitemap mit folgendem Inhalt:

sitemap heating label="Fußbodenheizung" {
    Frame label="Globale Einstellung Fußbodenheizung" {
		Setpoint item=vIt_HZ_Hysterese minValue=0.1 maxValue=4.0 step=0.1
		Switch item=vIt_HZ_OnOff
		Switch item=vIt_HZ_DayNight
		Default item=gHeatingValves
		Default item=It_FL_Pump
    }
	Frame label="Heizung Wohnzimmer" {
		Text item=It_WZ_ActTemperature
		Switch item=It_WZ_RelaisThermostat
		Setpoint item=vIt_HZ_WZ_SollTag_upper minValue=4.5 maxValue=35 step=0.5
		Text item=vIt_HZ_WZ_SollTag_lower
		Setpoint item=vIt_HZ_WZ_SollNacht_upper minValue=4.5 maxValue=35 step=0.5
		Text item=vIt_HZ_WZ_SollNacht_lower
    }
}

Das Ergebnis im Browser:

Die verwendeten Icons für Ventile und Pumpe sind nicht in OpenHAB enthalten, Ihr müsst eigene verwenden.

 

Fazit und Ausblick

Das Projekt mit seinen fünf Thermostaten hat mich ein paar Tage beschäftigt, speziell das Design und der 3D-Druck. Nach dem Einbau und der Konfiguration funktioniert es fehlerfrei. Jetzt muß nur noch der Winter kommen - das ist dann der harte Praxistest. Aktuell versuche ich die Steuerung der Temperaturen über Alexa vorzunehmen, aber das ist ein anderes Thema.

Was könnte man noch verbessern?