-- ======================
-- Description
-- ======================
--
-- Logika umożliwiająca sterowanie gruntową pompą ciepła:
--
-- - sprężarka on/off
-- - pompa górnego źródła c.w.u.
-- - pompa górnego źródła c.o.
-- - pompę dolnego źródła
-- - chłodzenie pasywne
-- - chłodzenie aktywne
-- - regeneracja GWC dolnym źródłem
--
-- ======================
-- Parameters
-- ======================
--
-- SubLogic supports following variables:
--
-- input.supply.t.value
-- input.supply.t.err - temperatura zasilania c.o. (wyjścia z PC)
--
-- input.return.t.value
-- input.return.t.err - temperatura powrotu c.o. (powrotu na PC)
--
-- input.ground.out.t.value
-- input.ground.out.t.err - temperatura wyjścia dolnego źródła (z gruntu) do PC
--
-- input.ground.in.t.value
-- input.ground.in.t.err - temperatura powrotu dolnego źródła (do gruntu) z PC
--
-- input.cool.return.t.value
-- input.cool.return.t.err - temperatura powrotu dolnego źródła do pompy ciepła. Istotne dla chłodzenia aktywnego.
-- Jest to temperatura powrotu z chłodnicy (temperatura tego co wchodzi
-- na wymiennik dolnego źródła na pompę ciepła)
--
-- input.ghe.liq.out.t.value
-- input.ghe.liq.out.t.err - temperatura powrotu płynu z GWC
--
-- input.season - 0 - winter, 1 - summer [0..1]
--
-- input.alert.low - alarm niskiego ciśnienia układu gazowego [0..1]
--
-- input.alert.medium - alarm średniego ciśnienia układu gazowego [0..1]
--
-- input.alert.high - alarm wysokiego ciśnienia układu gazowego [0..1]
--
-- input.alert.other - alarm innego typu, skutkujący zatrzymaniem kompresora i kontrolowanym zatrzymaniem PC [0..1]
--
-- input.demand.dw.heating - żądanie aby pompa ciepła ładowała zbiornik c.w.u.
--
-- input.demand.buff.heating - żądanie aby pompa ciepła ładowała zbiornik buforowy
--
-- input.demand.cool - żądanie aby pompa ciepła chłodziła pasywnie
--
-- input.demand.activcool - żądanie aby pompa ciepła chłodziła aktywnie
--
-- input.demand.ghe - żądanie aby pompa ciepła regenerowała GWC
--
-- output.compr - kompresor PC [0..1]
--
-- output.ground.pump - pompa dolnego źródła (gruntowa) PC [0..1]
--
-- output.dw.pump - pompa górnego źródła PC (ładowanie c.w.u.) [0..1]
--
-- output.buff.pump - pompa górnego źródła PC (ładowanie bufora) [0..1]
--
-- output.cool.passive - zawór załączający pasywny tryb chłodzenia (0 - ogrzewanie; 1 - chłodzenie) [0..1]
--
-- output.cool.active - pompa i zawór załączający aktywny tryb chłodzenia (0 - ogrzewanie; 1 - aktywne chłodzenie) [0..1]
--
-- output.ghe - kierowanie dolnego źródła na GWC (0 - powrót do gruntu, 1 - powrót przez GWC) [0..1]
--
-- setting.alert.med.dw.pump.state - czy w czasie przerwy w ładowaniu c.w.u. pompa dw ma pracować cały czas
--
-- setting.alert.med.buff.load.state - czy w czasie przerwy w ładowaniu c.w.u. ma być ładowany zbiornik buforowy
-- (0 - nie; 1 - tak; 2 - AUTO: w zimie tak, w lecie nie)
--
-- setting.alert.med.buff.load.max.supply.t.value
-- - jeżeli setting.alert.med.buff.load.state jest ustawiony to (po czasie zwłoki counter.alert.med.buff.load.max.supply.t.delay)
-- przy jakiej maksymalnej temperaturze zasilania ma zostać wyłączone żądanie grzania bufora
--
-- setting.dw.t.supply.buff.pump.cool - czy pompa buforowa ma być używana do obniżania temperatury zasilania PC (na podstawie counter.dw.t.supply.max.status)
--
-- setting.buff.enabled - czy pompa ciepa jest aktywna do ogrzewania bufora
--
-- setting.dw.enabled - czy pompa ciepa jest aktywna do ogrzewania c.w.u.
--
-- setting.cool.enabled - czy pompa ciepa jest aktywna do chłodzenia pasywnego
--
-- setting.activcool.enabled - czy pompa ciepa jest aktywna do chłodzenia aktywnego
--
-- setting.dw.t.supply.max - maksymalna temperatura zasilania (wyjścia z pompy ciepła) kiedy jest wymagane ogrzewanie c.w.u. i nie jest wymagane chłodzenie aktywne
--
-- setting.dw.t.supply.hyst - histereza dla setting.dw.t.supply.max
--
-- setting.activcool.t.suppl.max - maksymalna temperatura zasilania (wyjścia z pompy ciepła) kiedy jest wymagane chłodzenie aktywne i równocześnie jest wymagane ogrzewanie c.w.u.
--
-- setting.activcool.t.supply.hyst - histereza dla setting.activcool.t.suppl.max
--
-- setting.activcool.t.ground.out.min - minimalna temperatura dolnego źródła kiedy jest wymagane chłodzenie aktywne, oraz do odpadowego
-- chłodzenia pasywnego w trakcie ogrzewania c.w.u. (puszczenie przepływu wprost na grunt aby zapobiec zamrożeniu DZ)
--
-- setting.activcool.t.ground.out.hyst - histereza dla setting.activcool.t.ground.out.min
--
-- setting.activcool.t.ground.out.ghe.min - minimalna temperatura dolnego źródła kiedy jest wymagane chłodzenie aktywne, oraz do odpadowego chłodzenia pasywnego
-- w trakcie ogrzewania c.w.u. (regeneracja GWC)
--
-- setting.alert.compr.delay - czas przerwy w pracy kompresora po wystąpieniu alertu błędu [s]
--
-- setting.alert.med.break.time - czas przerwy w ładowaniu c.w.u. po wystąpieniu alarmu średniego ciśnienia [s]
--
-- setting.alert.med.buff.load.max.supply.t.delay
-- - czas powiązany z setting.alert.med.buff.load.max.supply.t.value [s]
--
-- setting.compr.start.delay - czas opóźnienia startu kompresora względem uruchomienia dolnego i górnego źródła (po fladze uruchomienia pompy ciepła) [s]
--
-- setting.compr.stop.delay - czas opóźnienia zatrzymania pomp dolnego i górnego źródła względem zatrzymania kompresora (po fladze zatrzymania pompy ciepła) [s]
--
-- setting.compr.main.delay - czas minimalnej przerwy między kolejnymi startami kompresora [s]
--
-- setting.alert.service.blocked.reset - wpisanie 1 powoduje resetowanie blokady serwisowej pompy ciepła
--
-- setting.logic.delay - czas zwłoki działania logiki. Dopiero po tym czasie logika zacznie wysterowywać wyjścia i odczytywać błędy [s]
--
-- counter.alert.med.buff.load.status - flaga: w czasie przerwy w ładowaniu c.w.u. ma być ładowany zbiornik buforowy
--
-- counter.dw.t.supply.max.status - flaga: czy warunek maksymalnej temperatury zasilania (wyjścia z pompy ciepła) kiedy jest wymagane ogrzewanie c.w.u. i kiedy nie jest
-- wymagane aktywne chłodzenie jest spełniony
--
-- counter.activcool.t.supply.max.status - flaga: czy warunek maksymalnej temperatury zasilania (wyjścia z pompy ciepła) kiedy jest wymagane chłodzenie aktywne i równocześnie
-- jest wymagane ogrzewanie c.w.u. jest spełniony
--
-- counter.activcool.t.ground.out.min.status
-- - flaga: czy warunek minimalnej temperatury dolnego źródła kiedy jest wymagane chłodzenie aktywne lub podczas realizacji odpadowego
-- chłodzenia jest spełniony
--
-- counter.activcool.t.ground.out.ghe.min.status
-- - flaga: czy warunek minimalnej temperatury dolnego źródła kiedy jest wymagane chłodzenie aktywne lub podczas realizacji odpadowego
-- chłodzenia dla przełączenia na regeneracje GHE jest spełniony
--
-- counter.alert.compr.delay - licznik przerwy w pracy kompresora po wystąpieniu alertu błędu [s]
--
-- counter.alert.med.break.time - licznik przerwy w ładowaniu c.w.u. po wystąpieniu alarmu średniego ciśnienia [s]
--
-- counter.alert.med.buff.load.max.supply.t.delay
-- - licznik powiązany z setting.alert.med.buff.load.max.supply.t.value [s]
--
-- counter.compr.start.delay - licznik opóźnienia startu kompresora względem uruchomienia dolnego i górnego źródła (po fladze uruchomienia pompy ciepła) [s]
--
-- counter.compr.stop.delay - licznik opóźnienia zatrzymania pomp dolnego i górnego źródła względem zatrzymania kompresora (po fladze zatrzymania pompy ciepła) [s]
--
-- counter.compr.main.delay - licznik minimalnej przerwy między kolejnymi startami kompresora [s]
--
-- counter.work.main.status - flaga: czy logika chce załączyć pompę ciepła
--
-- counter.work.dw.status - flaga: czy logika chce aby pompa ciepła ładowała zbiornik c.w.u.
--
-- counter.work.buff.status - flaga: czy logika chce aby pompa ciepła ładowała zbiornik buforowy
--
-- counter.work.cool.status - flaga: czy logika chce aby pompa ciepła chłodziła pasywnie
--
-- counter.work.activcool.status - flaga: czy logika chce aby pompa ciepła chłodziła aktywnie
--
-- counter.work.ghe.status - flaga: czy logika chce aby pompa ciepła regenerowała GWC
--
-- counter.work.mode - faza pracy pompy ciepła (0 - wyłączanie, 1 - uruchamianie i normalna praca)
--
-- counter.alert.service.blocked.state - flaga: czy jest aktywna blokada serwisowa pompy ciepła
--
-- counter.alert.service.blocked.last.err - kod błędy który spowodował blokadę serwisową:
--
-- 0 - brak błędu
-- 1 - alarm niskiego ciśnienia układu gazowego
-- 2 - alarm wysokiego ciśnienia układu gazowego
-- 3 - alarm innego typu, skutkujący zatrzymaniem kompresora i kontrolowanym zatrzymaniem PC
--
-- counter.alert.t.state - flaga: wartość 1 oznacza uszkodzenie jakiegokolwiek czujnika. Uszkodzenie jakiegokolwiek czujnika wyłącza wszystkie urządzenia.
--
-- counter.logic.delay - licznik czas zwłoki działania logiki. [s]
--
-- Logic uses lua language to implement own behaviour
--
-- ======================
-- mandatory variables
-- ======================
--
-- Logic expects following mandatory variables:
--
-- reload.trigger - causes reloading lua script
--
-- memcnt - current amount of memory used by lua in bytes
--
-- Logic expects following kv settings:
--
-- LuaScriptPath - path to the lua script - must be absolute
--
-- ======================
-- ChangeLog
-- ======================
--
-- 2019-09-20 ver 0.0.0
--
-- # First release
--
-- user can use some functions provided by ibmanager.
-- ibmanager provides following functions to use:
--
-- function returns value of required ibmanager variable
-- @param fullName - string - variable name - name of variable of which value must be returned, for example "rs.0.id.255.input.t.0.value"
-- @return - string or integer - variable value or "nil" if variable not exist or is not readable
--
-- getValue(fullName)
-- function set value of given ibmanager variable
-- @param fullName - string - variable name - name of variable of which value we want to set, for example "rs.0.id.255.input.t.0.value"
-- @param value - string, int or boolean - value to set
-- @return - nothing
--
-- setValue(fullName, value)
-- function returns value of required ibmanager variable
-- @param key - placed in xml logic configuration file:
-- * as attribute: Name, in Var, RemoteVar and ImportVar elements in the case of stand alone variables
-- * as concatenation of two attributes: ListName.Postfix in VarListItem, RemoteVarListItem and ImportVarListItem elements
-- in the case of variables that are placed in lists
-- @return - string or integer - variable value or "nil" if variable not exist or is not readable
--
-- getLogicValue(key)
-- function set value of given ibmanager variable
-- @param key - placed in xml logic configuration file:
-- * as attribute: Name, in Var, RemoteVar and ImportVar elements in the case of stand alone variables
-- * as concatenation of two attributes: ListName.Postfix in VarListItem, RemoteVarListItem and ImportVarListItem elements
-- in the case of variables that are placed in lists
-- @param value - string, int or boolean - value to set
-- @return - nothing
--
-- setLogicValue(key, value)
-- function returns two sections of kvsettings from xml configuration file
-- returned value is two element table, each of these elements is table too.
-- indices of returned table are strings and equal "instance" and "global"
-- values of returned tables are tables and contain KVsettings for applicable section.
-- nested tables have form key = value, where key is index in nested table and value is value.
-- example: {"instance" = {"ikey1" = "ivalue1", "ikey2" = "gvalue2"}, "global" = {"gkey1" = "gvalue1", "gkey2" = "gvalue2", "gkey3" = "gvalue3"}}
-- @return - two dimensional array - kvsettings for global and instance sections
-- getKvSettings()
-- function schedules alert to send.
-- rules are defined in separated alert configuration files and are described in ibmanager instruction manual
-- @param id - alert identifier - must be defined in current logic configuration file in section: <Alert Id="any_identifier" ...
-- scheduleAlert(id)
-- function cancels alert sending, if was previously scheduled. if not then only wakes up alerts handling thread, so if there is no need to call this function, then do not call it.
-- rules are defined in separated alert configuration files and are described in ibmanager instruction manual
-- @param id - alert identifier - must be defined in current logic configuration file in section: <Alert Id="any_identifier" ...
-- cancelAlert(name)
-- function returns table, containing Variables that belongs to required list.
-- @param listName - Name attribute of VarList, RemoteVarList or ImportVarList elemetnst in configurationfile
-- @return array of key-value pairs. Key - variable postfix, Value - Variable value
-- getVarList(listName)
-- function returns monotonic system clock value, that elapsed since specific epoch
-- returned time is expressed in milliseconds.
-- getClock()
-- function logs message to file, if defined in configuration file log level is less than passed to this function
-- @param logLevel - one of:
-- LogLevel.TraceLo
-- LogLevel.Trace
-- LogLevel.TraceHi
-- LogLevel.DebugLo
-- LogLevel.Debug
-- LogLevel.DebugHi
-- LogLevel.Info
-- LogLevel.Notice
-- LogLevel.Warning
-- LogLevel.Error
-- LogLevel.Critical
-- @param logMessage - string to log
-- log(logLevel, logMessage)
-- ibmanager provides following global variables:
-- logic type, (in this case it will always be "Lua") - the same as in logic configuration file in section: <Logic Type="Lua" ...
-- LOGIC_TYPE
-- logic version, the same as in logic configuration file in section: <Logic ... Version="x.y.z" ...
-- LOGIC_VERSION
-- logic sub-type, the same as in logic configuration file in section: <Logic ... SubType="Hysteresis" ...
-- LOGIC_SUBTYPE
-- logic sub-version, the same as in logic configuration file in section: <Logic ... SubVersion="x.y.z" ...
-- LOGIC_SUBVERSION
-- logic instance name - the same as in logic configuration file, in section: <Instance Name="0">
-- LOGIC_INSTANCE_NAME
-- add script directory to package path
package.path = package.path .. ";./logic/scripts/utils/?.lua";
-- use script - without .lua extension - delta class
require("State");
require("DownCounter");
g_outputCompr = nil;
g_outputGroundPump = nil;
g_outputDwPump = nil;
g_outputBuffPump = nil;
g_outputCoolPassive = nil;
g_outputCoolActive = nil;
g_outputGhe = nil;
g_counterAlertComprDelay = nil;
g_counterAlertMedBreakTime = nil;
g_counterAlertMedBuffLoadMaxSupplyTDelay = nil;
g_counterComprStartDelay = nil;
g_counterComprStopDelay = nil;
g_counterComprMainDelay = nil;
g_counterLogicDelay = nil;
g_counterAlertMedBuffLoadStatus = nil;
g_counterDwTSupplyMaxStatus = nil;
g_counterActivcoolTSupplyMaxStatus = nil;
g_counterActivcoolTGroundOutMinStatus = nil;
g_counterActivcoolTGroundOutGheMinStatus = nil;
g_counterWorkMainStatus = nil;
g_counterWorkDwStatus = nil;
g_counterWorkBuffStatus = nil;
g_counterWorkCoolStatus = nil;
g_counterWorkActivcoolStatus = nil;
g_counterWorkGheStatus = nil;
g_counterWorkMode = nil;
g_counterAlertServiceBlockedState = nil;
g_counterAlertServiceBlockedLastErr = 0;
g_oldInputAlertMedium = 0;
SUPPORTED_SUBLOGIC_TYPE = "HP01";
SUPPORTED_SUBLOGIC_VERSION = "1.0.0";
g_versionChecked = false;
-- entry point to the logic
-- @param firstCall - tells if logic is called first time
-- @return - nothing
function onLogicCall(firstCall)
if not g_versionChecked then
-- checking sublogic type and sublogic version
if LOGIC_SUBTYPE ~= SUPPORTED_SUBLOGIC_TYPE then
error("Wrong logic sub-type. expected " .. SUPPORTED_SUBLOGIC_TYPE .. " but used " .. LOGIC_SUBTYPE);
end
local versionWithoutBuild = string.match(LOGIC_SUBVERSION, "[0-9]+%.[0-9]+%.[0-9]+");
if versionWithoutBuild ~= SUPPORTED_SUBLOGIC_VERSION then
error("Wrong logic sub-version. expected " .. SUPPORTED_SUBLOGIC_VERSION .. " but used " .. LOGIC_SUBVERSION);
end
g_versionChecked = true;
end
local inputSupplyTValue = getLogicValue("input.supply.t.value");
local inputSupplyTErr = getLogicValue("input.supply.t.err");
local inputReturnTValue = getLogicValue("input.return.t.value");
local inputReturnTErr = getLogicValue("input.return.t.err");
local inputGroundOutTValue = getLogicValue("input.ground.out.t.value");
local inputGroundOutTErr = getLogicValue("input.ground.out.t.err");
local inputGroundInTValue = getLogicValue("input.ground.in.t.value");
local inputGroundInTErr = getLogicValue("input.ground.in.t.err");
local inputGheLiqOutTValue = getLogicValue("input.ghe.liq.out.t.value");
local inputGheLiqOutTErr = getLogicValue("input.ghe.liq.out.t.err");
local inputCoolReturnTValue = getLogicValue("input.cool.return.t.value");
local inputCoolReturnTErr = getLogicValue("input.cool.return.t.err");
local inputSeason = getLogicValue("input.season");
local inputAlertLow = getLogicValue("input.alert.low");
local inputAlertMedium = getLogicValue("input.alert.medium");
local inputAlertHigh = getLogicValue("input.alert.high");
local inputAlertOther = getLogicValue("input.alert.other");
local inputDemandDwHeating = getLogicValue("input.demand.dw.heating");
local inputDemandBuffHeating = getLogicValue("input.demand.buff.heating");
local inputDemandCool = getLogicValue("input.demand.cool");
local inputDemandActivCool = getLogicValue("input.demand.activcool");
local inputDemandGhe = getLogicValue("input.demand.ghe");
local settingAlertMedDwPumpState = getLogicValue("setting.alert.med.dw.pump.state");
local settingAlertMedBuffLoadState = getLogicValue("setting.alert.med.buff.load.state");
local settingAlertMedBuffLoadMaxSupplyTValue = getLogicValue("setting.alert.med.buff.load.max.supply.t.value");
local settingDwTSupplyBuffPumpCool = getLogicValue("setting.dw.t.supply.buff.pump.cool");
local settingBuffEnabled = getLogicValue("setting.buff.enabled");
local settingDwEnabled = getLogicValue("setting.dw.enabled");
local settingCoolEnabled = getLogicValue("setting.cool.enabled");
local settingActivcoolEnabled = getLogicValue("setting.activcool.enabled");
local settingDwTSupplyMax = getLogicValue("setting.dw.t.supply.max");
local settingDwTSupplyHyst = getLogicValue("setting.dw.t.supply.hyst");
local settingActivcoolTSupplMax = getLogicValue("setting.activcool.t.suppl.max");
local settingActivcoolTSupplyHyst = getLogicValue("setting.activcool.t.supply.hyst");
local settingActivcoolTGroundOutMin = getLogicValue("setting.activcool.t.ground.out.min");
local settingActivcoolTGroundOutHyst = getLogicValue("setting.activcool.t.ground.out.hyst");
local settingActivcoolTGroundOutGheMin = getLogicValue("setting.activcool.t.ground.out.ghe.min");
local settingAlertComprDelay = getLogicValue("setting.alert.compr.delay");
local settingAlertMedBreakTime = getLogicValue("setting.alert.med.break.time");
local settingAlertMedBuffLoadMaxSupplyTDelay = getLogicValue("setting.alert.med.buff.load.max.supply.t.delay");
local settingComprStartDelay = getLogicValue("setting.compr.start.delay");
local settingComprStopDelay = getLogicValue("setting.compr.stop.delay");
local settingComprMainDelay = getLogicValue("setting.compr.main.delay");
local settingAlertServiceBlockedReset = getLogicValue("setting.alert.service.blocked.reset");
local settingLogicDelay = getLogicValue("setting.logic.delay");
local counterAlertComprDelay = 0;
local counterAlertMedBreakTime = 0;
local counterAlertMedBuffLoadMaxSupplyTDelay = 0;
local counterComprStartDelay = 0;
local counterComprStopDelay = 0;
local counterComprMainDelay = 0;
local counterLogicDelay = 0;
local counterAlertTState = 0;
-- timers
if g_counterAlertComprDelay == nil or firstCall then
g_counterAlertComprDelay = DownCounter.create();
end
-- g_counterAlertComprDelay:updateParams(settingAlertComprDelay * 1000);
-- if g_counterAlertComprDelay:elapsed() then
-- g_counterAlertComprDelay:reset();
-- end
counterAlertComprDelay = g_counterAlertComprDelay:timeTo0() / 1000;
counterAlertComprDelay = (counterAlertComprDelay < 0) and 0 or counterAlertComprDelay;
if g_counterAlertMedBreakTime == nil or firstCall then
g_counterAlertMedBreakTime = DownCounter.create();
end
-- g_counterAlertMedBreakTime:updateParams(settingAlertMedBreakTime * 1000);
-- if g_counterAlertMedBreakTime:elapsed() then
-- g_counterAlertMedBreakTime:reset();
-- end
counterAlertMedBreakTime = g_counterAlertMedBreakTime:timeTo0() / 1000;
counterAlertMedBreakTime = (counterAlertMedBreakTime < 0) and 0 or counterAlertMedBreakTime;
if g_counterAlertMedBuffLoadMaxSupplyTDelay == nil or firstCall then
g_counterAlertMedBuffLoadMaxSupplyTDelay = DownCounter.create();
end
-- g_counterAlertMedBuffLoadMaxSupplyTDelay:updateParams(settingAlertMedBuffLoadMaxSupplyTDelay * 1000);
-- if g_counterAlertMedBuffLoadMaxSupplyRDelay:elapsed() then
-- g_counterAlertMedBuffLoadMaxSupplyRDelay:reset();
-- end
counterAlertMedBuffLoadMaxSupplyTDelay = g_counterAlertMedBuffLoadMaxSupplyTDelay:timeTo0() / 1000;
counterAlertMedBuffLoadMaxSupplyTDelay = (counterAlertMedBuffLoadMaxSupplyTDelay < 0) and 0 or counterAlertMedBuffLoadMaxSupplyTDelay;
if g_counterComprStartDelay == nil or firstCall then
g_counterComprStartDelay = DownCounter.create();
end
-- g_counterComprStartDelay:updateParams(settingComprStartDelay * 1000);
-- if g_counterComprStartDelay:elapsed() then
-- g_counterComprStartDelay:reset();
-- end
counterComprStartDelay = g_counterComprStartDelay:timeTo0() / 1000;
counterComprStartDelay = (counterComprStartDelay < 0) and 0 or counterComprStartDelay;
if g_counterComprStopDelay == nil or firstCall then
g_counterComprStopDelay = DownCounter.create();
end
-- g_counterComprStopDelay:updateParams(settingComprStopDelay * 1000);
-- if g_counterComprStopDelay:elapsed() then
-- g_counterComprStopDelay:reset();
-- end
counterComprStopDelay = g_counterComprStopDelay:timeTo0() / 1000;
counterComprStopDelay = (counterComprStopDelay < 0) and 0 or counterComprStopDelay;
if g_counterComprMainDelay == nil or firstCall then
g_counterComprMainDelay = DownCounter.create();
end
-- g_counterComprMainDelay:updateParams(settingComprMainDelay * 1000);
-- if g_counterComprMainDelay:elapsed() then
-- g_counterComprMainDelay:reset();
-- end
counterComprMainDelay = g_counterComprMainDelay:timeTo0() / 1000;
counterComprMainDelay = (counterComprMainDelay < 0) and 0 or counterComprMainDelay;
if g_counterLogicDelay == nil or firstCall then
g_counterLogicDelay = DownCounter.create();
end
g_counterLogicDelay:updateParams(settingLogicDelay * 1000);
-- if g_counterLogicDelay:elapsed() then
-- g_counterLogicDelay:reset();
-- end
counterLogicDelay = g_counterLogicDelay:timeTo0() / 1000;
counterLogicDelay = (counterLogicDelay < 0) and 0 or counterLogicDelay;
-- states
if g_outputCompr == nil or firstCall then
g_outputCompr = State.create(0, 0, 1, true);
end
g_outputCompr:call();
if g_outputGroundPump == nil or firstCall then
g_outputGroundPump = State.create(0, 0, 1, true);
end
g_outputGroundPump:call();
if g_outputDwPump == nil or firstCall then
g_outputDwPump = State.create(0, 0, 1, true);
end
g_outputDwPump:call();
if g_outputBuffPump == nil or firstCall then
g_outputBuffPump = State.create(0, 0, 1, true);
end
g_outputBuffPump:call();
if g_outputCoolPassive == nil or firstCall then
g_outputCoolPassive = State.create(0, 0, 1, true);
end
g_outputCoolPassive:call();
if g_outputCoolActive == nil or firstCall then
g_outputCoolActive = State.create(0, 0, 1, true);
end
g_outputCoolActive:call();
if g_outputGhe == nil or firstCall then
g_outputGhe = State.create(0, 0, 1, true);
end
g_outputGhe:call();
if g_counterAlertMedBuffLoadStatus == nil or firstCall then
g_counterAlertMedBuffLoadStatus = State.create(0, 0, 1, true);
end
g_counterAlertMedBuffLoadStatus:call();
if g_counterDwTSupplyMaxStatus == nil or firstCall then
g_counterDwTSupplyMaxStatus = State.create(0, 0, 1, true);
end
g_counterDwTSupplyMaxStatus:call();
if g_counterActivcoolTSupplyMaxStatus == nil or firstCall then
g_counterActivcoolTSupplyMaxStatus = State.create(0, 0, 1, true);
end
g_counterActivcoolTSupplyMaxStatus:call();
if g_counterActivcoolTGroundOutMinStatus == nil or firstCall then
g_counterActivcoolTGroundOutMinStatus = State.create(0, 0, 1, true);
end
g_counterActivcoolTGroundOutMinStatus:call();
if g_counterActivcoolTGroundOutGheMinStatus == nil or firstCall then
g_counterActivcoolTGroundOutGheMinStatus = State.create(0, 0, 1, true);
end
g_counterActivcoolTGroundOutGheMinStatus:call();
if g_counterWorkMainStatus == nil or firstCall then
g_counterWorkMainStatus = State.create(0, 0, 1, true);
end
g_counterWorkMainStatus:call();
if g_counterWorkDwStatus == nil or firstCall then
g_counterWorkDwStatus = State.create(0, 0, 1, true);
end
g_counterWorkDwStatus:call();
if g_counterWorkBuffStatus == nil or firstCall then
g_counterWorkBuffStatus = State.create(0, 0, 1, true);
end
g_counterWorkBuffStatus:call();
if g_counterWorkCoolStatus == nil or firstCall then
g_counterWorkCoolStatus = State.create(0, 0, 1, true);
end
g_counterWorkCoolStatus:call();
if g_counterWorkActivcoolStatus == nil or firstCall then
g_counterWorkActivcoolStatus = State.create(0, 0, 1, true);
end
g_counterWorkActivcoolStatus:call();
if g_counterWorkGheStatus == nil or firstCall then
g_counterWorkGheStatus = State.create(0, 0, 1, true);
end
g_counterWorkGheStatus:call();
if g_counterWorkMode == nil or firstCall then
g_counterWorkMode = State.create(0, 0, 1, true);
end
g_counterWorkMode:call();
if g_counterAlertServiceBlockedState == nil or firstCall then
g_counterAlertServiceBlockedState = State.create(0, 0, 1, true);
end
g_counterAlertServiceBlockedState:call();
if (counterLogicDelay == 0) then
-- obsługa alarmu temperatur
if ((inputSupplyTErr ~= 0)
or (inputReturnTErr ~=0)
or (inputGroundOutTErr ~=0)
or (inputGroundInTErr ~=0)
or (inputCoolReturnTErr ~=0)
or (inputGheLiqOutTErr ~=0)) then
counterAlertTState = 1;
g_outputCompr:setValue(0);
g_outputGroundPump:setValue(0);
g_outputDwPump:setValue(0);
g_outputBuffPump:setValue(0);
g_outputCoolPassive:setValue(0);
g_outputCoolActive:setValue(0);
g_outputGhe:setValue(0);
end
-- obsługa licznika przerwy w pracy kompresora po wystąpieniu alertu błędu
if ((inputAlertLow ~= 0) or (inputAlertHigh ~= 0) or (inputAlertOther ~= 0)) then
g_counterAlertComprDelay:updateParams(settingAlertComprDelay * 1000);
g_counterAlertComprDelay:reset();
end
-- obsługa licznika przerwy w ładowaniu c.w.u. po wystąpieniu alarmu średniego ciśnienia
if (inputAlertMedium ~= 0) then
g_counterAlertMedBreakTime:updateParams(settingAlertMedBreakTime * 1000);
g_counterAlertMedBreakTime:reset();
end
-- reakcja na alarm niskiego ciśnienia
if (inputAlertLow ~= 0) then
-- wyłączenie pompy ciepła
g_counterWorkMainStatus:setValue(0);
-- natychmiastowe zatrzymanie kompresora
g_outputCompr:setValue(0);
-- natychmiastowe zatrzymanie pompy dolnego źródła
g_outputGroundPump:setValue(0);
end
-- reakcja na alarm wysokiego ciśnienia, pozostałe alarmy, blokadę serwisową oraz gdy licznik alarmowy liczy
if ((inputAlertHigh ~= 0)
or (inputAlertOther ~= 0)
or (g_counterAlertServiceBlockedState:getValue() ~= 0)
or (counterAlertComprDelay ~= 0) ) then
-- wyłączenie pompy ciepła
g_counterWorkMainStatus:setValue(0);
-- natychmiastowe zatrzymanie kompresora
g_outputCompr:setValue(0);
end
-- blokada serwisowa pompy ciepła
if ((inputAlertLow ~= 0)
or (inputAlertHigh ~= 0)
or (inputAlertOther ~= 0) ) then
g_counterAlertServiceBlockedState:setValue(1);
if (g_counterAlertServiceBlockedLastErr == 0) then
if (inputAlertLow ~= 0) then
g_counterAlertServiceBlockedLastErr = 1;
end
if (inputAlertHigh ~= 0) then
g_counterAlertServiceBlockedLastErr = 2;
end
if (inputAlertOther ~= 0) then
g_counterAlertServiceBlockedLastErr = 3;
end
end;
end
-- obsługa alarmu średniego ciśnienia
-- ustalenie wartości counter.alert.med.buff.load.status
if ((settingAlertMedBuffLoadState == 0) or (settingAlertMedBuffLoadState == 1) ) then
g_counterAlertMedBuffLoadStatus:setValue(settingAlertMedBuffLoadState);
else
if (inputSeason == 0) then
-- zimą tak
g_counterAlertMedBuffLoadStatus:setValue(1);
else
-- latem nie
g_counterAlertMedBuffLoadStatus:setValue(0);
end
end
-- jeżeli jest przerwa w ładowaniu c.w.u. ze względu na alarm średniego ciśnienia
if (counterAlertMedBreakTime ~= 0) then
-- jeżeli jest odpowiedni setting i zbiornik dw jest do grzania to pompa dw cały czas chodzi
if (settingAlertMedDwPumpState ~= 0) then
-- włączenie pompy dw
g_outputDwPump:setValue(1);
-- przy aktywnym chłodzeniu włącz pompę buff
if (g_counterWorkActivcoolStatus:getValue() ~= 0) then
g_outputBuffPump:setValue(1);
end
end
-- jeżeli jest flaga counter.alert.med.buff.load.status
if (g_counterAlertMedBuffLoadStatus:getValue() ~= 0) then
-- jeżeli jest zewnętrzny sygnał ładowania bufora to należy go ładować
-- pod warunkiem, że jest aktywna pompa ciepła do ładowania bufora
if (inputDemandBuffHeating ~= 0) then
if (settingBuffEnabled ~= 0) then
g_counterWorkBuffStatus:setValue(1);
else
g_counterWorkBuffStatus:setValue(0);
end
end
-- jeżeli sprężarka nie pracuje i nie ma zewnętrznego sygnału ładowania bufora
-- to nie ma sensu ładować bufora
if ((inputDemandBuffHeating == 0) and (g_outputCompr:getValue() == 0)) then
g_counterWorkBuffStatus:setValue(0);
end
-- jeżeli przed chwilą wybiło alarm średniego ciśnienia to zresetuj licznik
if ((inputAlertMedium ~= 0) and (g_oldInputAlertMedium ~= inputAlertMedium)) then
g_counterAlertMedBuffLoadMaxSupplyTDelay:updateParams(settingAlertMedBuffLoadMaxSupplyTDelay * 1000);
g_counterAlertMedBuffLoadMaxSupplyTDelay:reset();
end
-- jeżeli licznik counter.alert.med.buff.load.status odlicza to włącz zapotrzebowanie
-- na ładowanie bufora
if (counterAlertMedBuffLoadMaxSupplyTDelay ~= 0) then
g_counterWorkBuffStatus:setValue(1);
else
-- jeżeli licznik dojdzie do 0 to ładowanie bufora uzależnione od temperatury
-- zasilania c.o.
g_counterWorkBuffStatus:set1IfLowerThan(inputSupplyTValue, settingAlertMedBuffLoadMaxSupplyTValue, 10);
end
else
g_counterWorkBuffStatus:setValue(inputDemandBuffHeating);
end
-- kasujemy zapotrzebowanie na ogrzewanie c.w.u.
g_counterWorkDwStatus:setValue(0);
else
-- ustalamy zapotrzebowanie na c.w.u. w zależności od aktywności pompy do celów c.w.u.
if (settingDwEnabled == 1) then
g_counterWorkDwStatus:setValue(inputDemandDwHeating);
else
g_counterWorkDwStatus:setValue(0);
end
g_counterWorkBuffStatus:setValue(inputDemandBuffHeating);
end
-- sprawdzenie warunku przekroczenia temperatury zasilania PC przy ładowaniu c.w.u.
g_counterDwTSupplyMaxStatus:set1IfHigherThan(inputSupplyTValue, settingDwTSupplyMax, settingDwTSupplyHyst);
-- sprawdzenie warunku przekroczenia temperatury zasilania PC przy aktywnym
g_counterActivcoolTSupplyMaxStatus:set1IfHigherThan(inputSupplyTValue, settingActivcoolTSupplMax, settingActivcoolTSupplyHyst);
-- sprawdzenie warunku przekroczenia minimalnego progu temperatury wejścia DZ
g_counterActivcoolTGroundOutMinStatus:set1IfLowerThan(inputCoolReturnTValue, settingActivcoolTGroundOutMin, settingActivcoolTGroundOutHyst);
-- sprawdzenie warunku przekroczenia minimalnego progu temperatury wejścia DZ dla regeneracji GHE
g_counterActivcoolTGroundOutGheMinStatus:set1IfLowerThan(inputGheLiqOutTValue, settingActivcoolTGroundOutGheMin, settingActivcoolTGroundOutHyst);
-- ustawiamy żądanie chłodzenia aktywnego na podstawie flagi aktywności pompy ciepła dla chłodzenia aktywnego
-- oraz żądania zewnętrznego dla chłodzenia aktywnego
if (settingActivcoolEnabled == 1) then
g_counterWorkActivcoolStatus:setValue(inputDemandActivCool);
else
g_counterWorkActivcoolStatus:setValue(0);
end
-- jeżeli jest żądany activcool to zawsze musi być żądany cool (chłodzenie pasywne)
if (g_counterWorkActivcoolStatus:getValue() == 1) then
g_counterWorkCoolStatus:setValue(1);
end
-- ocena czy chcemy załączyć pompę ciepła (na podstawie żądania grzania c.o., c.w.u. lub active cool)
if ( (g_counterWorkDwStatus:getValue() == 1)
or (g_counterWorkBuffStatus:getValue() == 1)
or (g_counterWorkActivcoolStatus:getValue() == 1)) then
g_counterWorkMainStatus:setValue(1);
else
g_counterWorkMainStatus:setValue(0);
end
-- ustalenie fazy pracy pompy ciepła, czy zmienił się status
if (g_counterWorkMainStatus:isChanged() == true) then
if (g_counterWorkMainStatus:getValue() == 1) then
-- włączono żądanie pracy pompy ciepła - faza rozruchu
g_counterWorkMode:setValue(1);
g_counterComprStartDelay:updateParams(settingComprStartDelay * 1000);
g_counterComprStartDelay:reset();
g_counterComprStopDelay:updateParams(1);
g_counterComprStopDelay:reset();
else
-- wyłączono żądanie pracy pompy ciepła - faza wyłączania
g_counterWorkMode:setValue(0);
g_counterComprStartDelay:updateParams(1);
g_counterComprStartDelay:reset();
g_counterComprStopDelay:updateParams(settingComprStopDelay * 1000);
g_counterComprStopDelay:reset();
end
end
-- ustawiamy żądanie chłodzenia pasywnego na podstawie flagi aktywności pompy ciepła dla chłodzenia pasywnego
-- oraz żądania zewnętrznego dla chłodzenia pasywnego
if (settingCoolEnabled == 1) then
g_counterWorkCoolStatus:setValue(inputDemandCool);
else
g_counterWorkCoolStatus:setValue(0);
end
-- jeżeli jest wyłączone żądanie aktywnego chłodzenia, jest włączone żądanie pasywnego chłodzenia
-- i temperatura dolnego źródła jest poniżej minimalnej DZ dla aktywnego chłodzenia to jest ryzyko
-- zamrożenia chłodnicy dlatego przełącz zawór chłodzenia pasywnego na przepływ bezpośrednio do gruntu
if ( (g_counterWorkActivcoolStatus:getValue() == 0)
or (g_counterWorkCoolStatus:getValue() == 1)
or (g_counterActivcoolTGroundOutMinStatus:getValue() == 1)) then
g_outputCoolPassive:setValue(0);
end
-- ustawiamy zawór chłodzenia pasywnego
if (g_counterWorkCoolStatus:getValue() == 1) then
g_outputCoolPassive:setValue(1);
else
g_outputCoolPassive:setValue(0);
end
-- załączamy pompę dolnego źródła jeżeli chcemy chłodzić lub regenerować GWC
if ( (g_counterWorkCoolStatus:getValue() == 1)
or (g_counterWorkGheStatus:getValue() == 1)) then
g_outputGroundPump:setValue(1);
end
-- faza włączania i normalnej pracy
if ( (g_counterWorkMainStatus:getValue() == 1)
and (g_counterWorkMode:getValue() == 1)) then
-- obsługa kompresora
if (counterComprStartDelay ~= 0) then
g_outputCompr:setValue(0);
else
-- uruchom kompresor tylko jeżeli była odpowiednia przerwa od poprzedniego jej zatrzymania
if (counterComprMainDelay == 0) then
g_outputCompr:setValue(1);
end
end
-- włączenie pompy dolnego źródła
g_outputGroundPump:setValue(1);
-- obsługa żądania ładowania dw
if (g_counterWorkDwStatus:getValue() == 1) then
-- włączenie pompy dw
g_outputDwPump:setValue(1);
end
-- włączenie pompy buff po przekroczeniu temperatury zasilania i przy aktywnym wychładzaniu zasilania przy pomocy pompy buff
if ( (settingDwTSupplyBuffPumpCool == 1)
and (g_counterDwTSupplyMaxStatus:getValue() == 1)
and (g_counterWorkActivcoolStatus:getValue() == 0)) then
g_outputBuffPump:setValue(1);
end
-- włączenie pompy buff na podstawie wewnętrznego żądania buff
if (g_counterWorkBuffStatus:getValue() == 1) then
g_outputBuffPump:setValue(1);
end
-- obsługa żądania chłodzenia aktywnego (activcool)
if (g_counterWorkActivcoolStatus:getValue() == 1) then
-- włącz pompę activecool i zawór
g_outputCoolActive:setValue(1);
-- włączenie regeneracji GHE (równocześnie podniesienie temperatury na powrocie do PC
if (g_counterActivcoolTGroundOutGheMinStatus:getValue() == 1) then
g_counterWorkGheStatus:setValue(1);
end
if (g_counterWorkDwStatus:getValue() == 1) then
-- jeżeli jest żądanie chłodzenia aktywnego i równocześnie
-- jest żądanie ładowania dw to system ma utrzymać temperaturę na wyjściu z PC
-- na maksymalnym zadanym poziomie. Włączenie output.buff.pump powoduje spadek temperatury
-- na zasilaniu. Wyłączenie output.buff.pump powoduje wzrost temperatury na zasilaniu.
g_outputBuffPump:setValue(g_counterActivcoolTSupplyMaxStatus:getValue());
else
-- jeżeli jest żądanie chłodzenia aktywnego i nie ma żądania ładowania dw
-- to utrzymujemy wejście dolnego źródła (powrotu z chłodnicy) na minimalnym poziomie. Jeżeli temperatura
-- wejścia DZ spadnie poniżej wartości minimalnej to należy podnieść temperaturę na zasilaniu PC
-- tak aby spadła sprawność PC (zaczęła chłodzić z mniejszą mocą). Aby zwiększyć temperaturę wejścia DZ
-- i równocześnie temperaturę zasilania PC należy wyłączyć output.buff.pump i włączyć output.dw.pump.
-- jeżeli temperatura wejścia DZ jest OK to output.buff.pump jest włączona i output.dw.pump jest wyłączona.
if (g_counterActivcoolTGroundOutMinStatus:getValue() == 1) then
g_outputBuffPump:setValue(0);
g_outputDwPump:setValue(1);
else
g_outputBuffPump:setValue(1);
g_outputDwPump:setValue(0);
end
end
end
-- wyłączenie pomp które nie zostały włączone wcześniej
g_outputDwPump:setValue(0);
g_outputBuffPump:setValue(0);
g_outputCoolActive:setValue(0);
end
-- faza wyłączania
if ( (g_counterWorkMainStatus:getValue() == 0)
and (g_counterWorkMode:getValue() == 0)) then
-- wyłączenie kompresora
g_outputCompr:setValue(0);
-- wyłączenie pomp górnego źródła, dolnego źródła, activcool
if (counterComprStopDelay== 0) then
g_outputGroundPump:setValue(0);
g_outputDwPump:setValue(0);
g_outputBuffPump:setValue(0);
g_outputCoolActive:setValue(0);
else
-- pozostaw włączone te pompy które pracowały w poprzednim przejściu logiki
-- (nie zmieniamy ich stanów ale blokujemy możliwośc ich zmienienia dalej)
g_outputGroundPump:setValue(g_outputGroundPump:getValue());
g_outputDwPump:setValue(g_outputDwPump:getValue());
g_outputBuffPump:setValue(g_outputBuffPump:getValue());
g_outputCoolActive:setValue(g_outputCoolActive:getValue());
end
end
-- wyłączamy pompę dolnego źródła, jeżeli wcześniejsze warunki ją nie załączyły
g_outputGroundPump:setValue(0);
-- reset licznika minimalnej przerwy między kolejnymi startami kompresora
if ( (g_outputCompr:isChanged() == true)
and (g_outputCompr:getValue() == 0)) then
g_counterComprMainDelay:updateParams(settingComprMainDelay * 1000);
g_counterComprMainDelay:reset();
end
-- ustawiamy żądanie regeneracji GWC zgodnie z sygnałem żądania
g_counterWorkGheStatus:setValue(inputDemandGhe);
-- ustawiamy zawór regeneracji GWC
if (g_counterWorkGheStatus:getValue() == 1) then
g_outputGhe:setValue(1);
else
g_outputGhe:setValue(0);
end
end
if (settingAlertServiceBlockedReset == 1) then
setLogicValue("setting.alert.service.blocked.reset", 0);
g_counterAlertServiceBlockedState:setValue(0);
g_counterAlertServiceBlockedLastErr = 0;
end
-- send logic variables to ibmanager
setLogicValue("output.compr", g_outputCompr:getValue());
setLogicValue("output.ground.pump", g_outputGroundPump:getValue());
setLogicValue("output.dw.pump", g_outputDwPump:getValue());
setLogicValue("output.buff.pump", g_outputBuffPump:getValue());
setLogicValue("output.cool.passive", g_outputCoolPassive:getValue());
setLogicValue("output.cool.active", g_outputCoolActive:getValue());
setLogicValue("output.ghe", g_outputGhe:getValue());
setLogicValue("counter.alert.compr.delay", counterAlertComprDelay);
setLogicValue("counter.alert.med.break.time", counterAlertMedBreakTime);
setLogicValue("counter.alert.med.buff.load.max.supply.t.delay", counterAlertMedBuffLoadMaxSupplyTDelay);
setLogicValue("counter.compr.start.delay", counterComprStartDelay);
setLogicValue("counter.compr.stop.delay", counterComprStopDelay);
setLogicValue("counter.compr.main.delay", counterComprMainDelay);
setLogicValue("counter.logic.delay", counterLogicDelay);
setLogicValue("counter.alert.med.buff.load.status", g_counterAlertMedBuffLoadStatus:getValue());
setLogicValue("counter.dw.t.supply.max.status", g_counterDwTSupplyMaxStatus:getValue());
setLogicValue("counter.activcool.t.supply.max.status", g_counterActivcoolTSupplyMaxStatus:getValue());
setLogicValue("counter.activcool.t.ground.out.min.status", g_counterActivcoolTGroundOutMinStatus:getValue());
setLogicValue("counter.activcool.t.ground.out.ghe.min.status", g_counterActivcoolTGroundOutGheMinStatus:getValue());
setLogicValue("counter.work.main.status", g_counterWorkMainStatus:getValue());
setLogicValue("counter.work.dw.status", g_counterWorkDwStatus:getValue());
setLogicValue("counter.work.buff.status", g_counterWorkBuffStatus:getValue());
setLogicValue("counter.work.cool.status", g_counterWorkCoolStatus:getValue());
setLogicValue("counter.work.activcool.status", g_counterWorkActivcoolStatus:getValue());
setLogicValue("counter.work.ghe.status", g_counterWorkGheStatus:getValue());
setLogicValue("counter.work.mode", g_counterWorkMode:getValue());
setLogicValue("counter.alert.service.blocked.state", g_counterAlertServiceBlockedState:getValue());
setLogicValue("counter.alert.service.blocked.last.err", g_counterAlertServiceBlockedLastErr);
setLogicValue("counter.alert.t.state", counterAlertTState);
g_oldInputAlertMedium = inputAlertMedium;
end