Hieronder een zo compleet mogelijke uitleg van hoe ik de structuur heb opgebouwd rond de sturing van mijn verwarming. Ik begin met de meest eenvoudige stapjes en voeg dan stilletjes zaken toe om te komen tot de uiteindelijke programmatie.
Een basis kamer met een radiator en een schema.
Stel, je hebt een kamer met 1 radiator. Nu wil je een tijdsafhankelijke sturing, zodat je bijvoorbeeld het volgende kan instellen:
- tussen 8u en 10u: 21°C
- tussen 10u en 15u: 19°C
- tussen 15u en 22u: 20°C
- tussen 22u en 8u: 18°C
Om dit volgens een LUA sturing handig op te splitsen moet je een stapje ervoor toevoegen en het laatste stapje opsplitsen:
- 00:00 tot 08:00 : 18°C
- 08:01 tot 10:00 : 21°C
- 10:01 tot 15:00 : 19°C
- 15:01 tot 22:00 : 20°C
- 22:01 tot 23:59 : 18°C
Dit schema vertaalt zich in de finale LUA in een structuur:
local schema_x={ {00,00,08,00,18}, {08,01,10,00,21}, {10,01,15,00,19}, {15,01,22,00,20}, {22,01,23,59,18} }
En dan heb je nog de code die de temperatuur hieruit haalt die nodig is op dat moment:
local parsetemp=schema_x local time=tonumber(os.date("%H"))*60+tonumber(os.date("%M")) --huidige tijd local setlevel=errortemp -- errortemp wanneer er iets misgaat (18°C) local levelttl=0 -- hoe lang de temperatuur geldig is local logtotime="--:--" -- voor de log for i=1,#parsetemp do local mintime=parsetemp[i][1]*60+parsetemp[i][2] local maxtime=parsetemp[i][3]*60+parsetemp[i][4] if ((time>=mintime) and (time<maxtime)) then setlevel=parsetemp[i][5] levelttl=(maxtime-time-1) logtotime=parsetemp[i][3]..":"..parsetemp[i][4] end end
Een kamer met meerdere schema’s.
In sommige kamers wil je misschien meerdere schema’s gebruiken. Eentje voor als het een weekdag is, en een ander voor wanneer het een dag in het weekend is. Naar analogie met hierboven krijg je dan verschillende local’s (hieronder ingekort weergegeven)
local thuisweekdag ={ {00,00,08,00,18}, {08,01,22,00,20}, {22,01,23,59,18} } local thuisweekenddag = { {00,00,09,00,18}, {09,01,23,00,21}, {23,01,23,59,18} }
En de code om het juiste schema te selecteren:
local parsetemp=nil local schemaName="" if ((tonumber(os.date("%w"))~=0) and (tonumber(os.date("%w"))~=6)) then parsetemp=thuisweekdag schemaName="thuisweekdag" else parsetemp=thuisweekenddag schemaName="thuisweekenddag" end
Toevoeging: niemand-thuis schema
Wanneer er niemand thuis is, kan je de verwarming best een graadje lager schakelen. Dit bestaat dus uit twee zaken, enerzijds een soort van “schakelaar” of alarmsysteem-codepaneel waarmee je aan de HC2 kan laten weten of er iemand thuis is of niet, anderzijds een schema specifiek voor de radiator dat geselecteerd moet worden wanneer er niemand thuis is.
Bij mij is dit bepaald door de globale variabele “G_IemandThuis”.
local nietthuis={ {0,0,23,59,18} }
En de selectiecode:
local iemandthuis=tonumber(fibaro:getGlobalValue("G_IemandThuis")) local parsetemp=nietthuis local schemaName="nietthuis" if (iemandthuis==0) then parsetemp=nietthuis schemaName="nietthuis" elseif ((tonumber(os.date("%w"))~=0) and (tonumber(os.date("%w"))~=6)) then parsetemp=thuisweekdag schemaName="thuisweekdag" else parsetemp=thuisweekenddag schemaName="thuisweekenddag" end
Toevoeging: schema afhankelijk van de buitentemperatuur
Wanneer het buiten meer dan 18 graden is, hoef je eigenlijk binnen geen verwarming meer op te zetten vind ik. Vandaar dat ik een schema hiervoor heb toegevoegd.
local buitenwarm={ {0,0,23,59,16} }
En de selectie hier is weer gebaseerd op een globale variabele, die ingevuld wordt vanuit een buitenweerstation of bijvoorbeeld vanuit Yahoo Weather.
local buitenwarmtemp=16 --temperatuur buiten zonder verwarming local tempbuiten=tonumber(fibaro:getGlobalValue("G_TempBuiten")) if (tempbuiten>=buitenwarmtemp) then parsetemp=buitenwarm schemaName="buitenwarm" elseif (iemandthuis==0) then parsetemp=nietthuis schemaName="nietthuis" elseif ((tonumber(os.date("%w"))~=0) and (tonumber(os.date("%w"))~=6)) then parsetemp=thuisweekdag schemaName="thuisweekdag" else parsetemp=thuisweekenddag schemaName="thuisweekenddag" end
Een kamer met een radiator en een temperatuur sensor (en dus ook aansturing van de warmtevraag naar de ketel)
Wanneer je een sensor hebt hangen in de kamer, die de actuele temperatuur meet, kan je uit het verschil met de ingestelde waarde in de thermostaatkop bepalen of de ketel warmte moet produceren of niet. In mijn opstelling zet ik op voorhand een globale variabele op 0, ga ik alle radiator-LUA-settings schema’s af en als nadien die globale variabele op 1 staat, betekent dit dat er ergens een kamer warmte nodig heeft.
Enerzijds betekent dit een toevoeging in de scene om de radiatorkop in te stellen
local exttemp=74 --id van de externe temperatuursensor if (exttemp~=0) then if (setlevel>tonumber(fibaro:getValue(exttemp,"value"))) then fibaro:setGlobal("G_KetelWarmte",1) fibaro:debug("Demanding Boiler Heat: "..setlevel.." requested "..fibaro:getValue(exttemp,"value").." measured") fibaro:sleep(100) end end
Anderzijds dus ook een aparte scene die alle 5 minuten loopt en alle scenes van de radiatoren afloopt en daarna de ketel al dan niet om warmte vraagt.
--[[ %% properties %% autostart %% events %% globals --]] local heatsetids={30,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48} -- de id's van alle set-scenes van de Danfoss Radiatorkoppen local nestDevice=196 local ketelHeating=0 while true do fibaro:debug("Running scene at: "..os.date()) local setp=tonumber(fibaro:getValue(nestDevice,"ui.settemp.value")) local curlivtmp=tonumber(fibaro:getValue(nestDevice,"ui.curtemp.value")) fibaro:debug("SetPoint: "..setp.." - Current: "..curlivtmp) if (setp>curlivtmp) then ketelHeating=1 else ketelHeating=0 end fibaro:setGlobal("G_KetelWarmte",0) for i=1,#heatsetids do fibaro:startScene(heatsetids[i]) end fibaro:sleep(10*1000) if (tonumber(fibaro:getGlobalValue("G_KetelWarmte"))==1) then fibaro:debug("Outcome: G_Ketelwarmte=1") if (ketelHeating==1) then if (setp>curlivtmp) then fibaro:debug("Boiler Heat requested - boiler still active") else fibaro:debug("Boiler Heat requested - boiler still active - updating temp") fibaro:call(nestDevice,"setProperty", "ui.setpoint.value", curlivtmp+1) end else fibaro:call(nestDevice,"setProperty", "ui.setpoint.value", curlivtmp+1) fibaro:debug("Boiler Heat requested - Activating boiler setting temp to: "..curlivtmp+1) fibaro:sleep(100) end else fibaro:debug("Outcome: G_Ketelwarmte=0") if (ketelHeating==0) then if (setp<curlivtmp) then fibaro:debug("Not Requesting Boiler Heat - boiler still inactive") else fibaro:call(nestDevice,"setProperty", "ui.setpoint.value", curlivtmp-1) fibaro:debug("Not Requesting Boiler Heat - boiler still inactive - updating temp") fibaro:sleep(1000) end --check for temp and adjust not heating temp else fibaro:call(nestDevice,"setProperty", "ui.setpoint.value", curlivtmp-1) fibaro:sleep(1000) fibaro:debug("Not Requesting Boiler Heat - Deactivating boiler setting temp to: "..curlivtmp-1) end end fibaro:sleep(4*60*1000) -- slaap 4 minuten end
In de scene hierboven zit ineens de integratie van mijn eigen gecreëerde NEST Thermostaat aansturing in. Zie daarvoor de specifieke pagina verderdoor.
Toevoeging: open/toe sensor(en)
Wanneer je een kamer aan het verluchten bent, is het niet nodig van de verwarming te laten opstaan. Als je een “open-toe sensor” op de raam installeert, kan je dit schema ook ineens mee verwerken in de scene voor de instelling van de radiatorkop. Ik heb ervoor gekozen om dan het “buitenwarm” schema toe te passen
local extopen=72 --id van de externe open deur/raam sensor if (extopen~=0) then if (tonumber(fibaro:getValue(extopen,"value"))==1) then parsetemp=buitenwarm schemaName="verluchtingopen" end end
Toevoeging: bewegingssensor
Indien er een kamer is waar een bewegingsdetector hangt, kan je bijvoorbeeld de temperatuur automatisch een graadje hoger zetten, wanneer er het afgelopen half uur nog beweging gedetecteerd is. Perfect om bijvoorbeeld de living op 20°C te zetten normaal gezien, en als er iemand aanwezig is net dat extra beetje gezellige warmte te creëren.
local extmotion=0 --id van de externe bewegingsdetector if (extmotion~=0) then if ((os.time()-fibaro:getValue(extmotion, "lastBreached"))<1800) then setlevel=setlevel+1 end end
Toevoeging: extra warmte – knop
Wil je toch nog iets extra doen voor de mensen waarmee je samenwoont die het gemakkelijk kou hebben, kan je in een kamer een extra drukknop toevoegen zodat je manueel de temperatuur een graadje hoger kan schakelen.
local extmanplus=37 --id van een externe heat schakelaar +1 graden if (extmanplus~=0) then if (tonumber(fibaro:getValue(extmanplus,"value"))==1) then setlevel=setlevel+1 end end
Finale LUA script voor de scene die de radiator instelt
Het finale LUA script ziet er dan zo uit:
--[[ %% properties %% events %% globals --]] local heaterid=133 --id van de thermostaatkop local heaterfloor="gelijkvloers" local heaterroom="living" local extopen1=56 --id van de externe open deur/raam sensor local extopen2=189 --id van de externe open deur/raam sensor local extopen3=0 --id van de externe open deur/raam sensor local exttemp=196 --id van de externe temperatuursensor local extmotion=149 --id van de externe bewegingsdetector local extmanplus=37 --id van een externe heat schakelaar +1 graden local buitenwarmtemp=19 --temperatuur buiten zonder verwarming local errortemp=18 local iemandthuis=tonumber(fibaro:getGlobalValue("G_IemandThuis")) local tempbuiten=tonumber(fibaro:getGlobalValue("G_TempBuiten")) --per "soort" een scrn : vanuut,vanminuut,totuur,totminuut,setvalue -- voor een normale weekdag local thuisweekdag={ {0,0,6,0,18}, {6,1,20,0,20}, {20,1,22,0,21}, {22,1,23,0,20}, {23,1,23,59,18} } local thuisweekenddag={ {0,0,6,0,18}, {6,1,23,0,20}, {23,1,23,59,18} } local nietthuis={ {0,0,17,0,18}, {17,1,18,0,19}, {18,1,19,00,20}, {19,01,23,59,18} } local buitenwarm={ {0,0,23,59,16} } local parsetemp=nietthuis local schemaName="nietthuis" if (tempbuiten>=buitenwarmtemp) then parsetemp=buitenwarm schemaName="buitenwarm" elseif (iemandthuis==0) then parsetemp=nietthuis schemaName="nietthuis" elseif ((tonumber(os.date("%w"))~=0) and (tonumber(os.date("%w"))~=6)) then parsetemp=thuisweekdag schemaName="thuisweekdag" else parsetemp=thuisweekenddag schemaName="thuisweekenddag" end if (extopen1~=0) then if (tonumber(fibaro:getValue(extopen1,"value"))==1) then parsetemp=buitenwarm schemaName="verluchtingopen" end end if (extopen2~=0) then if (tonumber(fibaro:getValue(extopen2,"value"))==1) then parsetemp=buitenwarm schemaName="verluchtingopen" end end fibaro:debug("T ext.:"..tempbuiten.."; Selected Schema: "..schemaName) local time=tonumber(os.date("%H"))*60+tonumber(os.date("%M")) local setlevel=errortemp local levelttl=0 local logtotime="--:--" for i=1,#parsetemp do local mintime=parsetemp[i][1]*60+parsetemp[i][2] local maxtime=parsetemp[i][3]*60+parsetemp[i][4] if ((time>=mintime) and (time<maxtime)) then setlevel=parsetemp[i][5] levelttl=(maxtime-time-1) logtotime=parsetemp[i][3]..":"..parsetemp[i][4] end end if (extmotion~=0) then if ((os.time()-fibaro:getValue(extmotion, "lastBreached"))<1800) then setlevel=setlevel+1 end end if (extmanplus~=0) then if (tonumber(fibaro:getValue(extmanplus,"value"))==1) then setlevel=setlevel+1 end end if (exttemp~=0) then if (setlevel>tonumber(fibaro:getValue(exttemp,"ui.curtemp.value"))) then fibaro:setGlobal("G_KetelWarmte",1) fibaro:debug("Demanding Boiler Heat: "..setlevel.." requested "..fibaro:getValue(exttemp,"ui.curtemp.value").." measured") end end fibaro:debug("Selected Temp: "..setlevel.." for: "..levelttl.." minutes until "..logtotime) local currentlevel=tonumber(fibaro:getValue(heaterid,"value")) if (currentlevel~=setlevel) then fibaro:call(heaterid,"setTargetLevel",setlevel) fibaro:debug("SETTING - Current setLevel: "..currentlevel.." new level: "..setlevel) fibaro:call(heaterid,"setTime",tonumber(os.time(t))+levelttl*60) end
Aansturing van de ketel
Er zijn een paar mogelijkheden om je centrale verwarmingsketel aan te sturen, afhankelijk van het soort ketel dat je hebt. Wanneer er gewerkt wordt met een eenvoudige “Aan-Uit” thermostaat kan je hiervoor een Fibaro Relais gebruiken. Wat ook mogelijk is, is een intelligente thermostaat, voordeel hiervan is dat je indien je een OpenTherm compatibele thermostaat hebt, zoals ik, deze de ketelsturing ook nog intelligent moduleert. Ik heb hiervoor een NEST thermostaat gekozen. De aansturing daarvan is wel wat moeilijker, maar hiervoor heb ik een oplossing gemaakt.
Voor de finale gedocumenteerde LUA zie de specifieke pagina