![]() |
|
Pid - Printable Version +- LogicMachine Forum (https://forum.logicmachine.net) +-- Forum: LogicMachine eco-system (https://forum.logicmachine.net/forumdisplay.php?fid=1) +--- Forum: Scripting (https://forum.logicmachine.net/forumdisplay.php?fid=8) +--- Thread: Pid (/showthread.php?tid=6245) |
Pid - Michael - 12.01.2026 Hello everyone, I hope you're all well. I'm writing to you because I'm having a problem with a script related to a PI controller for a radiant floor heating system. The system consists of a 0/10 valve and a flow sensor. To prevent the controller from becoming too sensitive to temperature variations, a moving average filter was added. However, despite this precaution, the PID remains very lazy and unstable. I've attached the script and an image of the configured parameters. The setpoints, proportional, and integral values are adjustable via the supervisory system. I feel like I'm a bit lost in the dark, so I'm counting on your expert help to resolve this situation. I forgot about the Pt1000 sensors read by the KNX module with a 2-minute cyclic variation and a value change of 0.2K, but the valves are 0/10 controlled by the KNX module. Thank you so much for your support and availability. Michael -- ============================================================ -- REGOLATORE PI – MISCELATRICE PAVIMENTO RADIANTE -- SOLO SONDA MANDATA -- ============================================================ --------------------------------------------------------------- -- PARAMETRI BASE (persistenti) --------------------------------------------------------------- local Kp = storage.get('Kp_PINT') or 3.0 local Ki = storage.get('Ki_PINT') or 0.02 local integral = storage.get('integral_PINT') or 0 local last_mode = storage.get('last_mode') --------------------------------------------------------------- -- CONFIGURAZIONE KNX --------------------------------------------------------------- local group_mode = '5/0/0' -- 1=inverno / 0=estate local group_in = '5/2/1' -- temperatura mandata local group_out = '5/0/1' -- 0–10 V miscelatrice local group_set_winter = '5/2/4' local group_set_summer = '5/2/5'---- local group_kp = '5/2/6' local group_ki = '5/2/7' --------------------------------------------------------------- -- COSTANTI DI CONTROLLO --------------------------------------------------------------- local cycle_time = 120 -- secondi local filter_samples = 3 -- filtro ridotto local out_min, out_max = 0, 100 -- % local max_delta = 2 -- base rampa local deadband = 0.3 -- °C --------------------------------------------------------------- -- VARIABILI --------------------------------------------------------------- local readings = {} local last_output = storage.get('last_output') or 0 --------------------------------------------------------------- -- MEDIA MOBILE TEMPERATURA MANDATA --------------------------------------------------------------- local function moving_average(v) if type(v) ~= 'number' then return nil end table.insert(readings, v) if #readings > filter_samples then table.remove(readings, 1) end local s = 0 for _, x in ipairs(readings) do s = s + x end return s / #readings end --------------------------------------------------------------- -- CICLO PRINCIPALE --------------------------------------------------------------- while true do ------------------------------------------------------------- -- Aggiornamento Kp / Ki da KNX ------------------------------------------------------------- local v = grp.getvalue(group_kp) if type(v) == 'number' then Kp = v storage.set('Kp_PINT', Kp) end v = grp.getvalue(group_ki) if type(v) == 'number' then Ki = v storage.set('Ki_PINT', Ki) end ------------------------------------------------------------- -- Modalità estate / inverno ------------------------------------------------------------- local is_winter = grp.getvalue(group_mode) and true or false if last_mode ~= is_winter then integral = 0 last_mode = is_winter storage.set('last_mode', is_winter) end ------------------------------------------------------------- -- Setpoint ------------------------------------------------------------- local set = is_winter and grp.getvalue(group_set_winter) or grp.getvalue(group_set_summer) if type(set) ~= 'number' then set = is_winter and 35 or 25 end ------------------------------------------------------------- -- Temperatura mandata filtrata ------------------------------------------------------------- local T = grp.getvalue(group_in) local Tf = moving_average(T) if Tf then ----------------------------------------------------------- -- LIMITI TEMPERATURA MANDATA ----------------------------------------------------------- local Tmax = set + 2.0 local Tstop = set + 3.0 ----------------------------------------------------------- -- ERRORE ------------------------------------------------------- |