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