rs485-lpc/lpc_modbus_lux.lua

90 lines
2.4 KiB
Lua

local tv = get_trigger_variable(1)
if tv == nil then return end
local lux = tv.integer
if lux == nil then return end
if lux < 0 then lux = 0 end
if lux > 200000 then lux = 200000 end
lux_value = lux
if lux_link_on == nil then lux_link_on = true end
if not lux_link_on then return end
if lux_poll_s == nil then lux_poll_s = 1 end
local okt, now = pcall(function() return os.time() end)
if okt and now ~= nil then
if lux_last_adj ~= nil and now - lux_last_adj < lux_poll_s then return end
lux_last_adj = now
else
lux_tick = (lux_tick or 0) + 1
if lux_tick % lux_poll_s ~= 0 then return end
end
if lux_fade == nil then lux_fade = 1.0 end
if lux_deadband == nil then lux_deadband = 1 end
if lux_target == nil then lux_target = 500 end
local TARGET_LUX = lux_target
local DEADBAND = lux_deadband
local MIN_LEVEL = 0.05
local MAX_LEVEL = 1.0
local STEP_MAX = 0.20
local ok, grp = pcall(get_group, 0)
if not ok or grp == nil then
ok, grp = pcall(get_group, 'All Fixtures')
end
if not ok or grp == nil then return end
local err = TARGET_LUX - lux
if lux_prev_cmd ~= nil and lux_prev_cur ~= nil and lux_prev_lux ~= nil then
local dl = lux_prev_cmd - lux_prev_cur
local clamped = (lux_prev_cmd <= MIN_LEVEL + 0.001) or (lux_prev_cmd >= MAX_LEVEL - 0.001)
if math.abs(dl) > 0.002 and not clamped then
local ki = (lux - lux_prev_lux) / dl
if ki > 100 and ki < 10000 then
if lux_k == nil then
lux_k = ki
else
lux_k = 0.7 * lux_k + 0.3 * ki
end
end
end
lux_prev_cmd = nil
end
if err >= -DEADBAND and err <= DEADBAND then
lux_last_err = err
return
end
local lv = grp.master_intensity_level
local hw
if lv ~= nil and lv.range ~= nil and lv.range > 0 then
hw = lv.integer / lv.range
end
local cur = lux_cur_level
if cur == nil or (hw ~= nil and math.abs(hw - cur) > 0.05) then
cur = hw or 0.5
end
local k = lux_k or 500
local delta = err / k
if lux_last_err ~= nil and (err > 0) ~= (lux_last_err > 0) then
delta = delta * 0.5
end
lux_last_err = err
if delta > STEP_MAX then delta = STEP_MAX end
if delta < -STEP_MAX then delta = -STEP_MAX end
local new = cur + delta
if new < MIN_LEVEL then new = MIN_LEVEL end
if new > MAX_LEVEL then new = MAX_LEVEL end
lux_prev_cur = cur
lux_prev_cmd = new
lux_prev_lux = lux
lux_cur_level = new
grp:set_master_intensity(new, lux_fade)