diff --git a/coordinator/startup.lua b/coordinator/startup.lua index 1289dd8..36df275 100644 --- a/coordinator/startup.lua +++ b/coordinator/startup.lua @@ -17,7 +17,7 @@ local config = require("coordinator.config") local coordinator = require("coordinator.coordinator") local renderer = require("coordinator.renderer") -local COORDINATOR_VERSION = "alpha-v0.6.12" +local COORDINATOR_VERSION = "alpha-v0.6.13" local print = util.print local println = util.println diff --git a/coordinator/ui/components/unit_detail.lua b/coordinator/ui/components/unit_detail.lua index 5568611..34850ef 100644 --- a/coordinator/ui/components/unit_detail.lua +++ b/coordinator/ui/components/unit_detail.lua @@ -84,16 +84,6 @@ local function init(parent, id) DataIndicator{parent=main,x=21,label="",format="%6.2f",value=0,unit="mSv/h",lu_colors=lu_cpair,width=12,fg_bg=stat_fg_bg} main.line_break() - -- TextBox{parent=main,text="FL",x=21,y=19,height=1,width=2,fg_bg=style.label} - -- TextBox{parent=main,text="WS",x=24,y=19,height=1,width=2,fg_bg=style.label} - -- TextBox{parent=main,text="CL",x=28,y=19,height=1,width=2,fg_bg=style.label} - -- TextBox{parent=main,text="HC",x=31,y=19,height=1,width=2,fg_bg=style.label} - - -- local fuel = VerticalBar{parent=main,x=21,y=12,fg_bg=cpair(colors.black,colors.gray),height=6,width=2} - -- local waste = VerticalBar{parent=main,x=24,y=12,fg_bg=cpair(colors.brown,colors.gray),height=6,width=2} - -- local ccool = VerticalBar{parent=main,x=28,y=12,fg_bg=cpair(colors.lightBlue,colors.gray),height=6,width=2} - -- local hcool = VerticalBar{parent=main,x=31,y=12,fg_bg=cpair(colors.orange,colors.gray),height=6,width=2} - -- annunciator -- local annunciator = Div{parent=main,x=34,y=3} @@ -164,14 +154,14 @@ local function init(parent, id) annunciator.line_break() -- cooling - local c_brm = IndicatorLight{parent=annunciator,label="Boil Rate Mismatch",colors=cpair(colors.yellow,colors.gray)} local c_cfm = IndicatorLight{parent=annunciator,label="Coolant Feed Mismatch",colors=cpair(colors.yellow,colors.gray)} + local c_brm = IndicatorLight{parent=annunciator,label="Boil Rate Mismatch",colors=cpair(colors.yellow,colors.gray)} local c_sfm = IndicatorLight{parent=annunciator,label="Steam Feed Mismatch",colors=cpair(colors.yellow,colors.gray)} local c_mwrf = IndicatorLight{parent=annunciator,label="Max Water Return Feed",colors=cpair(colors.yellow,colors.gray)} local c_tbnt = IndicatorLight{parent=annunciator,label="Turbine Trip",colors=cpair(colors.red,colors.gray),flash=true,period=period.BLINK_250_MS} - r_ps.subscribe("BoilRateMismatch", c_brm.update) r_ps.subscribe("CoolantFeedMismatch", c_cfm.update) + r_ps.subscribe("BoilRateMismatch", c_brm.update) r_ps.subscribe("SteamFeedMismatch", c_sfm.update) r_ps.subscribe("MaxWaterReturnFeed", c_mwrf.update) r_ps.subscribe("TurbineTrip", c_tbnt.update) @@ -249,6 +239,15 @@ local function init(parent, id) -- reactor controls -- + local burn_control = Div{parent=main,x=2,y=22,width=19,height=3,fg_bg=cpair(colors.gray,colors.white)} + local burn_rate = SpinboxNumeric{parent=burn_control,x=2,y=1,whole_num_precision=4,fractional_precision=1,arrow_fg_bg=cpair(colors.gray,colors.white),fg_bg=cpair(colors.black,colors.white)} + TextBox{parent=burn_control,x=9,y=2,text="mB/t"} + + local set_burn = function () unit.set_burn(burn_rate.get_value()) end + PushButton{parent=burn_control,x=14,y=2,text="SET",min_width=5,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=set_burn} + + r_ps.subscribe("burn_rate", function (v) burn_rate.set_value(v) end) + local dis_colors = cpair(colors.white, colors.lightGray) local start = HazardButton{parent=main,x=2,y=26,text="START",accent=colors.lightBlue,dis_colors=dis_colors,callback=unit.start,fg_bg=scram_fg_bg} @@ -270,15 +269,6 @@ local function init(parent, id) r_ps.subscribe("rps_tripped", start_button_en_check) r_ps.subscribe("rps_tripped", function (active) if active then reset.enable() else reset.disable() end end) - local burn_control = Div{parent=main,x=2,y=22,width=19,height=3,fg_bg=cpair(colors.gray,colors.white)} - local burn_rate = SpinboxNumeric{parent=burn_control,x=2,y=1,whole_num_precision=4,fractional_precision=1,arrow_fg_bg=cpair(colors.gray,colors.white),fg_bg=cpair(colors.black,colors.white)} - TextBox{parent=burn_control,x=9,y=2,text="mB/t"} - - local set_burn = function () unit.set_burn(burn_rate.get_value()) end - PushButton{parent=burn_control,x=14,y=2,text="SET",min_width=5,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=set_burn} - - r_ps.subscribe("burn_rate", function (v) burn_rate.set_value(v) end) - local opts = { { text = "Auto", diff --git a/supervisor/session/unit.lua b/supervisor/session/unit.lua index 86df0dd..b8e9463 100644 --- a/supervisor/session/unit.lua +++ b/supervisor/session/unit.lua @@ -95,7 +95,7 @@ function unit.new(for_reactor, num_boilers, num_turbines) if self.deltas[key] then local data = self.deltas[key] - if time ~= data.last_t then + if time > data.last_t then data.dt = (value - data.last_v) / (time - data.last_t) data.last_v = value @@ -168,6 +168,9 @@ function unit.new(for_reactor, num_boilers, num_turbines) -- update deltas _dt__compute_all() + -- variables for boiler, or reactor if no boilers used + local total_boil_rate = 0.0 + ------------- -- REACTOR -- ------------- @@ -192,10 +195,15 @@ function unit.new(for_reactor, num_boilers, num_turbines) self.db.annunciator.RCSFlowLow = plc_db.mek_status.ccool_fill < 0.75 or plc_db.mek_status.hcool_fill > 0.25 self.db.annunciator.ReactorTempHigh = plc_db.mek_status.temp > 1000 self.db.annunciator.ReactorHighDeltaT = _get_dt(DT_KEYS.ReactorTemp) > 100 - self.db.annunciator.FuelInputRateLow = _get_dt(DT_KEYS.ReactorFuel) < 0.0 or plc_db.mek_status.fuel_fill <= 0.01 - self.db.annunciator.WasteLineOcclusion = _get_dt(DT_KEYS.ReactorWaste) > 0.0 or plc_db.mek_status.waste_fill >= 0.85 + self.db.annunciator.FuelInputRateLow = _get_dt(DT_KEYS.ReactorFuel) < -1.0 or plc_db.mek_status.fuel_fill <= 0.01 + self.db.annunciator.WasteLineOcclusion = _get_dt(DT_KEYS.ReactorWaste) > 1.0 or plc_db.mek_status.waste_fill >= 0.85 ---@todo this is dependent on setup, i.e. how much coolant is buffered and the turbine setup self.db.annunciator.HighStartupRate = not plc_db.mek_status.status and plc_db.mek_status.burn_rate > 40 + + -- if no boilers, use reactor heating rate to check for boil rate mismatch + if self.counts.boilers == 0 then + total_boil_rate = plc_db.mek_status.heating_rate + end end ------------- @@ -206,10 +214,10 @@ function unit.new(for_reactor, num_boilers, num_turbines) for i = 1, self.counts.boilers do self.db.annunciator.BoilerOnline[i] = false end -- aggregated statistics - local total_boil_rate = 0.0 local boiler_steam_dt_sum = 0.0 local boiler_water_dt_sum = 0.0 + if self.counts.boilers > 0 then -- go through boilers for stats and online for i = 1, #self.boilers do local session = self.boilers[i] ---@type unit_session @@ -223,7 +231,7 @@ function unit.new(for_reactor, num_boilers, num_turbines) end -- check heating rate low - if self.plc_s ~= nil then + if self.plc_s ~= nil and #self.boilers > 0 then local r_db = self.plc_i.get_db() -- check for inactive boilers while reactor is active @@ -238,25 +246,41 @@ function unit.new(for_reactor, num_boilers, num_turbines) self.db.annunciator.HeatingRateLow[idx] = false end end - - -- check for rate mismatch - local expected_boil_rate = r_db.mek_status.heating_rate / 10.0 - self.db.annunciator.BoilRateMismatch = math.abs(expected_boil_rate - total_boil_rate) > 25.0 + end + else + boiler_steam_dt_sum = _get_dt(DT_KEYS.ReactorHCool) + boiler_water_dt_sum = _get_dt(DT_KEYS.ReactorCCool) end - -- check coolant feed mismatch - local cfmismatch = false - for i = 1, #self.boilers do - local boiler = self.boilers[i] ---@type unit_session - local idx = boiler.get_device_idx() - local db = boiler.get_db() ---@type boilerv_session_db + --------------------------- + -- COOLANT FEED MISMATCH -- + --------------------------- - local gaining_hc = _get_dt(DT_KEYS.BoilerHCool .. idx) > 0 or db.tanks.hcool_fill == 1 + -- check coolant feed mismatch if using boilers, otherwise calculate with reactor + local cfmismatch = false + + if self.counts.boilers > 0 then + for i = 1, #self.boilers do + local boiler = self.boilers[i] ---@type unit_session + local idx = boiler.get_device_idx() + local db = boiler.get_db() ---@type boilerv_session_db + + local gaining_hc = _get_dt(DT_KEYS.BoilerHCool .. idx) > 10.0 or db.tanks.hcool_fill == 1 -- gaining heated coolant cfmismatch = cfmismatch or gaining_hc -- losing cooled coolant - cfmismatch = cfmismatch or _get_dt(DT_KEYS.BoilerCCool .. idx) < 0 or (gaining_hc and db.tanks.ccool_fill == 0) + cfmismatch = cfmismatch or _get_dt(DT_KEYS.BoilerCCool .. idx) < -10.0 or (gaining_hc and db.tanks.ccool_fill == 0) + end + elseif self.plc_s ~= nil then + local r_db = self.plc_i.get_db() + + local gaining_hc = _get_dt(DT_KEYS.ReactorHCool) > 10.0 or r_db.mek_status.hcool_fill == 1 + + -- gaining heated coolant (steam) + cfmismatch = cfmismatch or gaining_hc + -- losing cooled coolant (water) + cfmismatch = cfmismatch or _get_dt(DT_KEYS.ReactorCCool) < -10.0 or (gaining_hc and r_db.mek_status.ccool_fill == 0) end self.db.annunciator.CoolantFeedMismatch = cfmismatch @@ -285,9 +309,12 @@ function unit.new(for_reactor, num_boilers, num_turbines) self.db.annunciator.TurbineOnline[session.get_device_idx()] = true end + -- check for boil rate mismatch (either between reactor and turbine or boiler and turbine) + self.db.annunciator.BoilRateMismatch = math.abs(total_boil_rate - total_input_rate) > 4 + -- check for steam feed mismatch and max return rate local sfmismatch = math.abs(total_flow_rate - total_input_rate) > 10 - sfmismatch = sfmismatch or boiler_steam_dt_sum > 0 or boiler_water_dt_sum < 0 + sfmismatch = sfmismatch or boiler_steam_dt_sum > 2.0 or boiler_water_dt_sum < -2.0 self.db.annunciator.SteamFeedMismatch = sfmismatch self.db.annunciator.MaxWaterReturnFeed = max_water_return_rate == total_flow_rate and total_flow_rate ~= 0 @@ -312,7 +339,7 @@ function unit.new(for_reactor, num_boilers, num_turbines) local db = turbine.get_db() ---@type turbinev_session_db local idx = turbine.get_device_idx() - self.db.annunciator.TurbineOverSpeed[idx] = (db.state.flow_rate == db.build.max_flow_rate) and (_get_dt(DT_KEYS.TurbineSteam .. idx) > 0) + self.db.annunciator.TurbineOverSpeed[idx] = (db.state.flow_rate == db.build.max_flow_rate) and (_get_dt(DT_KEYS.TurbineSteam .. idx) > 0.0) end --[[ diff --git a/supervisor/startup.lua b/supervisor/startup.lua index 3886aab..95a050f 100644 --- a/supervisor/startup.lua +++ b/supervisor/startup.lua @@ -14,7 +14,7 @@ local svsessions = require("supervisor.session.svsessions") local config = require("supervisor.config") local supervisor = require("supervisor.supervisor") -local SUPERVISOR_VERSION = "beta-v0.7.8" +local SUPERVISOR_VERSION = "beta-v0.7.9" local print = util.print local println = util.println