From 878c3b92e19287f84bcfb0d609548547c46e7d6a Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Fri, 12 Apr 2024 00:13:05 -0400 Subject: [PATCH] #366 added idling to config and adjusted/fixed some behaviors --- supervisor/configure.lua | 26 +++++++++++++++-- supervisor/facility.lua | 46 ++++++++++++++++--------------- supervisor/session/svsessions.lua | 2 +- supervisor/supervisor.lua | 3 ++ supervisor/unit.lua | 12 ++++---- supervisor/unitlogic.lua | 2 +- 6 files changed, 59 insertions(+), 32 deletions(-) diff --git a/supervisor/configure.lua b/supervisor/configure.lua index cd790e7..8cad070 100644 --- a/supervisor/configure.lua +++ b/supervisor/configure.lua @@ -91,6 +91,7 @@ local tmp_cfg = { CoolingConfig = {}, FacilityTankMode = 0, FacilityTankDefs = {}, + ExtChargeIdling = false, SVR_Channel = nil, ---@type integer PLC_Channel = nil, ---@type integer RTU_Channel = nil, ---@type integer @@ -120,6 +121,7 @@ local fields = { { "CoolingConfig", "Cooling Configuration", {} }, { "FacilityTankMode", "Facility Tank Mode", 0 }, { "FacilityTankDefs", "Facility Tank Definitions", {} }, + { "ExtChargeIdling", "Extended Charge Idling", false }, { "SVR_Channel", "SVR Channel", 16240 }, { "PLC_Channel", "PLC Channel", 16241 }, { "RTU_Channel", "RTU Channel", 16242 }, @@ -222,8 +224,9 @@ local function config_view(display) local svr_c_4 = Div{parent=svr_cfg,x=2,y=4,width=49} local svr_c_5 = Div{parent=svr_cfg,x=2,y=4,width=49} local svr_c_6 = Div{parent=svr_cfg,x=2,y=4,width=49} + local svr_c_7 = Div{parent=svr_cfg,x=2,y=4,width=49} - local svr_pane = MultiPane{parent=svr_cfg,x=1,y=4,panes={svr_c_1,svr_c_2,svr_c_3,svr_c_4,svr_c_5,svr_c_6}} + local svr_pane = MultiPane{parent=svr_cfg,x=1,y=4,panes={svr_c_1,svr_c_2,svr_c_3,svr_c_4,svr_c_5,svr_c_6,svr_c_7}} TextBox{parent=svr_cfg,x=1,y=2,height=1,text=" Facility Configuration",fg_bg=cpair(colors.black,colors.yellow)} @@ -329,7 +332,7 @@ local function config_view(display) else tmp_cfg.FacilityTankMode = 0 tmp_cfg.FacilityTankDefs = {} - main_pane.set_value(3) + svr_pane.set_value(7) end end @@ -563,7 +566,7 @@ local function config_view(display) local function submit_mode() tmp_cfg.FacilityTankMode = tank_mode.get_value() - main_pane.set_value(3) + svr_pane.set_value(7) end PushButton{parent=svr_c_5,x=1,y=14,text="\x1b Back",callback=function()svr_pane.set_value(4)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} @@ -577,6 +580,23 @@ local function config_view(display) PushButton{parent=svr_c_6,x=1,y=14,text="\x1b Back",callback=function()svr_pane.set_value(5)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} + TextBox{parent=svr_c_7,height=6,text="Charge control provides automatic control to maintain an induction matrix charge level. In order to have smoother control, reactors that were activated will be held on at 0.01 mB/t for a short period before allowing them to turn off. This minimizes overshooting the charge target."} + TextBox{parent=svr_c_7,y=8,height=3,text="You can extend this to a full minute to minimize reactors flickering on/off, but there may be more overshoot of the target."} + + local ext_idling = CheckBox{parent=svr_c_7,x=1,y=12,label="Enable Extended Idling",default=ini_cfg.ExtChargeIdling,box_fg_bg=cpair(colors.yellow,colors.black)} + + local function back_from_idling() + svr_pane.set_value(util.trinary(tmp_cfg.FacilityTankMode == 0, 3, 5)) + end + + local function submit_idling() + tmp_cfg.ExtChargeIdling = ext_idling.get_value() + main_pane.set_value(3) + end + + PushButton{parent=svr_c_7,x=1,y=14,text="\x1b Back",callback=back_from_idling,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} + PushButton{parent=svr_c_7,x=44,y=14,text="Next \x1a",callback=submit_idling,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} + --#endregion --#region Network diff --git a/supervisor/facility.lua b/supervisor/facility.lua index 40e8002..33cd267 100644 --- a/supervisor/facility.lua +++ b/supervisor/facility.lua @@ -23,7 +23,7 @@ local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE local WASTE_MODE = types.WASTE_MODE local WASTE = types.WASTE_PRODUCT -local IO = rsio.IO +local IO = rsio.IO local DTV_RTU_S_DATA = qtypes.DTV_RTU_S_DATA @@ -63,9 +63,9 @@ local facility = {} -- create a new facility management object ---@nodiscard ----@param num_reactors integer number of reactor units +---@param config svr_config supervisor configuration ---@param cooling_conf sv_cooling_conf cooling configurations of reactor units -function facility.new(num_reactors, cooling_conf) +function facility.new(config, cooling_conf) local self = { units = {}, status_text = { "START UP", "initializing..." }, @@ -134,8 +134,8 @@ function facility.new(num_reactors, cooling_conf) } -- create units - for i = 1, num_reactors do - table.insert(self.units, unit.new(i, cooling_conf.r_cool[i].BoilerCount, cooling_conf.r_cool[i].TurbineCount)) + for i = 1, config.UnitCount do + table.insert(self.units, unit.new(i, cooling_conf.r_cool[i].BoilerCount, cooling_conf.r_cool[i].TurbineCount, config.ExtChargeIdling)) table.insert(self.group_map, 0) end @@ -499,8 +499,10 @@ function facility.new(num_reactors, cooling_conf) self.saturated = output ~= out_c - -- stop idling early if the output is zero, we are at or above the setpoint, and are not losing charge - _set_idling(not ((out_c == 0) and (error <= 0) and (avg_outflow <= 0))) + if not config.ExtChargeIdling then + -- stop idling early if the output is zero, we are at or above the setpoint, and are not losing charge + _set_idling(not ((out_c == 0) and (error <= 0) and (avg_outflow <= 0))) + end -- log.debug(util.sprintf("CHARGE[%f] { CHRG[%f] ERR[%f] INT[%f] => OUT[%f] OUT_C[%f] <= P[%f] I[%f] D[%f] }", -- runtime, avg_charge, error, integral, output, out_c, P, I, D)) @@ -952,41 +954,41 @@ function facility.new(num_reactors, cooling_conf) function public.auto_stop() self.mode = PROCESS.INACTIVE end -- set automatic control configuration and start the process - ---@param config coord_auto_config configuration + ---@param auto_cfg coord_auto_config configuration ---@return table response ready state (successfully started) and current configuration (after updating) - function public.auto_start(config) + function public.auto_start(auto_cfg) local charge_scaler = 1000000 -- convert MFE to FE local gen_scaler = 1000 -- convert kFE to FE local ready = false -- load up current limits local limits = {} - for i = 1, num_reactors do + for i = 1, config.UnitCount do local u = self.units[i] ---@type reactor_unit limits[i] = u.get_control_inf().lim_br100 * 100 end -- only allow changes if not running if self.mode == PROCESS.INACTIVE then - if (type(config.mode) == "number") and (config.mode > PROCESS.INACTIVE) and (config.mode <= PROCESS.GEN_RATE) then - self.mode_set = config.mode + if (type(auto_cfg.mode) == "number") and (auto_cfg.mode > PROCESS.INACTIVE) and (auto_cfg.mode <= PROCESS.GEN_RATE) then + self.mode_set = auto_cfg.mode end - if (type(config.burn_target) == "number") and config.burn_target >= 0.1 then - self.burn_target = config.burn_target + if (type(auto_cfg.burn_target) == "number") and auto_cfg.burn_target >= 0.1 then + self.burn_target = auto_cfg.burn_target end - if (type(config.charge_target) == "number") and config.charge_target >= 0 then - self.charge_setpoint = config.charge_target * charge_scaler + if (type(auto_cfg.charge_target) == "number") and auto_cfg.charge_target >= 0 then + self.charge_setpoint = auto_cfg.charge_target * charge_scaler end - if (type(config.gen_target) == "number") and config.gen_target >= 0 then - self.gen_rate_setpoint = config.gen_target * gen_scaler + if (type(auto_cfg.gen_target) == "number") and auto_cfg.gen_target >= 0 then + self.gen_rate_setpoint = auto_cfg.gen_target * gen_scaler end - if (type(config.limits) == "table") and (#config.limits == num_reactors) then - for i = 1, num_reactors do - local limit = config.limits[i] + if (type(auto_cfg.limits) == "table") and (#auto_cfg.limits == config.UnitCount) then + for i = 1, config.UnitCount do + local limit = auto_cfg.limits[i] if (type(limit) == "number") and (limit >= 0.1) then limits[i] = limit @@ -1026,7 +1028,7 @@ function facility.new(num_reactors, cooling_conf) ---@param unit_id integer unit ID ---@param group integer group ID or 0 for independent function public.set_group(unit_id, group) - if (group >= 0 and group <= 4) and (unit_id > 0 and unit_id <= num_reactors) and self.mode == PROCESS.INACTIVE then + if (group >= 0 and group <= 4) and (unit_id > 0 and unit_id <= config.UnitCount) and self.mode == PROCESS.INACTIVE then -- remove from old group if previously assigned local old_group = self.group_map[unit_id] if old_group ~= 0 then diff --git a/supervisor/session/svsessions.lua b/supervisor/session/svsessions.lua index e191db6..7300162 100644 --- a/supervisor/session/svsessions.lua +++ b/supervisor/session/svsessions.lua @@ -201,7 +201,7 @@ function svsessions.init(nic, fp_ok, config, cooling_conf) self.nic = nic self.fp_ok = fp_ok self.config = config - self.facility = facility.new(config.UnitCount, cooling_conf) + self.facility = facility.new(config, cooling_conf) end -- find an RTU session by the computer ID diff --git a/supervisor/supervisor.lua b/supervisor/supervisor.lua index 75d71d8..1d79e72 100644 --- a/supervisor/supervisor.lua +++ b/supervisor/supervisor.lua @@ -26,6 +26,7 @@ function supervisor.load_config() config.CoolingConfig = settings.get("CoolingConfig") config.FacilityTankMode = settings.get("FacilityTankMode") config.FacilityTankDefs = settings.get("FacilityTankDefs") + config.ExtChargeIdling = settings.get("ExtChargeIdling") config.SVR_Channel = settings.get("SVR_Channel") config.PLC_Channel = settings.get("PLC_Channel") @@ -58,6 +59,8 @@ function supervisor.load_config() cfv.assert_type_int(config.FacilityTankMode) cfv.assert_range(config.FacilityTankMode, 0, 8) + cfv.assert_type_bool(config.ExtChargeIdling) + cfv.assert_channel(config.SVR_Channel) cfv.assert_channel(config.PLC_Channel) cfv.assert_channel(config.RTU_Channel) diff --git a/supervisor/unit.lua b/supervisor/unit.lua index 88fcfb9..6fa4d0a 100644 --- a/supervisor/unit.lua +++ b/supervisor/unit.lua @@ -54,8 +54,6 @@ local AISTATE = { -- burn rate to idle at local IDLE_RATE = 0.01 --- time (ms) to idle -local IDLE_TIME = 15000 ---@class reactor_control_unit local unit = {} @@ -65,7 +63,11 @@ local unit = {} ---@param reactor_id integer reactor unit number ---@param num_boilers integer number of boilers expected ---@param num_turbines integer number of turbines expected -function unit.new(reactor_id, num_boilers, num_turbines) +---@param ext_idle boolean extended idling mode +function unit.new(reactor_id, num_boilers, num_turbines, ext_idle) + -- time (ms) to idle for auto idling + local IDLE_TIME = util.trinary(ext_idle, 60000, 10000) + ---@class _unit_self local self = { r_id = reactor_id, @@ -543,7 +545,7 @@ function unit.new(reactor_id, num_boilers, num_turbines) if self.auto_engaged and not self.plc_i.is_auto_locked() then self.plc_i.auto_lock(true) end -- stop idling when completed - if self.auto_idling and ((util.time_ms() - self.auto_idle_start) > IDLE_TIME) then + if self.auto_idling and (((util.time_ms() - self.auto_idle_start) > IDLE_TIME) or not self.auto_idle) then log.info(util.c("UNIT ", self.r_id, ": completed idling period")) self.auto_idling = false self.plc_i.auto_set_burn(0, false) @@ -601,7 +603,7 @@ function unit.new(reactor_id, num_boilers, num_turbines) -- - disabling it will stop the reactor when commanded zero ---@param idle boolean true to enable, false to disable (and stop) function public.auto_set_idle(idle) - if not (idle and self.auto_idle) then + if idle and not self.auto_idle then self.auto_idling = false self.auto_idle_start = 0 end diff --git a/supervisor/unitlogic.lua b/supervisor/unitlogic.lua index 4be004b..ad2b522 100644 --- a/supervisor/unitlogic.lua +++ b/supervisor/unitlogic.lua @@ -332,7 +332,7 @@ function logic.update_annunciator(self) -- minimal change indicates the turbine is converging on a flow rate if last.time_tanks < turbine.tanks.last_update then if last.time_tanks > 0 then - rotation_stable = math.abs(rotation - last.rotation) < 0.00000004 + rotation_stable = math.abs(rotation - last.rotation) < 0.00000003 end last.time_tanks = turbine.tanks.last_update