From 199ce53f52e5b26b92708f899d544c3f57e59dd2 Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Tue, 14 Feb 2023 22:55:40 -0500 Subject: [PATCH] #160 #161 linked up ASCRAM lights and added ASCRAM radiation condition --- coordinator/iocontrol.lua | 37 +++++++++++---- coordinator/startup.lua | 2 +- coordinator/ui/components/processctl.lua | 18 +++++--- coordinator/ui/components/unit_detail.lua | 2 +- supervisor/session/facility.lua | 56 +++++++++++++++++------ supervisor/startup.lua | 2 +- 6 files changed, 85 insertions(+), 32 deletions(-) diff --git a/coordinator/iocontrol.lua b/coordinator/iocontrol.lua index af27ab5..44f35c8 100644 --- a/coordinator/iocontrol.lua +++ b/coordinator/iocontrol.lua @@ -29,7 +29,16 @@ function iocontrol.init(conf, comms) auto_active = false, auto_ramping = false, auto_saturated = false, + auto_scram = false, + ---@type ascram_status + ascram_status = { + matrix_dc = false, + matrix_fill = false, + crit_alarm = false, + radiation = false, + gen_fault = false + }, radiation = types.new_zero_radiation_reading(), @@ -278,15 +287,22 @@ function iocontrol.update_facility_status(status) local ctl_status = status[1] - if type(ctl_status) == "table" and (#ctl_status == 9) then + if type(ctl_status) == "table" and (#ctl_status == 14) then fac.all_sys_ok = ctl_status[1] fac.auto_ready = ctl_status[2] fac.auto_active = ctl_status[3] > 0 fac.auto_ramping = ctl_status[4] fac.auto_saturated = ctl_status[5] + fac.auto_scram = ctl_status[6] - fac.status_line_1 = ctl_status[7] - fac.status_line_2 = ctl_status[8] + fac.ascram_status.matrix_dc = ctl_status[7] + fac.ascram_status.matrix_fill = ctl_status[8] + fac.ascram_status.crit_alarm = ctl_status[9] + fac.ascram_status.radiation = ctl_status[10] + fac.ascram_status.gen_fault = ctl_status[11] + + fac.status_line_1 = ctl_status[12] + fac.status_line_2 = ctl_status[13] fac.ps.publish("all_sys_ok", fac.all_sys_ok) fac.ps.publish("auto_ready", fac.auto_ready) @@ -294,10 +310,15 @@ function iocontrol.update_facility_status(status) fac.ps.publish("auto_ramping", fac.auto_ramping) fac.ps.publish("auto_saturated", fac.auto_saturated) fac.ps.publish("auto_scram", fac.auto_scram) + fac.ps.publish("as_matrix_dc", fac.ascram_status.matrix_dc) + fac.ps.publish("as_matrix_fill", fac.ascram_status.matrix_fill) + fac.ps.publish("as_crit_alarm", fac.ascram_status.crit_alarm) + fac.ps.publish("as_radiation", fac.ascram_status.radiation) + fac.ps.publish("as_gen_fault", fac.ascram_status.gen_fault) fac.ps.publish("status_line_1", fac.status_line_1) fac.ps.publish("status_line_2", fac.status_line_2) - local group_map = ctl_status[9] + local group_map = ctl_status[14] if (type(group_map) == "table") and (#group_map == fac.num_units) then local names = { "Manual", "Primary", "Secondary", "Tertiary", "Backup" } @@ -382,11 +403,11 @@ function iocontrol.update_facility_status(status) local rtu_faulted = rad_mon[1] ---@type boolean fac.radiation = rad_mon[2] ---@type number - fac.ps.publish("RadMonOnline", util.trinary(rtu_faulted, 2, 3)) + fac.ps.publish("rad_computed_status", util.trinary(rtu_faulted, 2, 3)) fac.ps.publish("radiation", fac.radiation) else fac.radiation = { radiation = 0, unit = "nSv" } - fac.ps.publish("RadMonOnline", 1) + fac.ps.publish("rad_computed_status", 1) end else log.debug(log_header .. "radiation monitor list not a table") @@ -605,11 +626,11 @@ function iocontrol.update_unit_statuses(statuses) local rtu_faulted = rad_mon[1] ---@type boolean unit.radiation = rad_mon[2] ---@type number - unit.unit_ps.publish("RadMonOnline", util.trinary(rtu_faulted, 2, 3)) + unit.unit_ps.publish("rad_computed_status", util.trinary(rtu_faulted, 2, 3)) unit.unit_ps.publish("radiation", unit.radiation) else unit.radiation = { radiation = 0, unit = "nSv" } - unit.unit_ps.publish("RadMonOnline", 1) + unit.unit_ps.publish("rad_computed_status", 1) end else log.debug(log_header .. "radiation monitor list not a table") diff --git a/coordinator/startup.lua b/coordinator/startup.lua index 73df848..872b3ce 100644 --- a/coordinator/startup.lua +++ b/coordinator/startup.lua @@ -19,7 +19,7 @@ local iocontrol = require("coordinator.iocontrol") local renderer = require("coordinator.renderer") local sounder = require("coordinator.sounder") -local COORDINATOR_VERSION = "beta-v0.9.11" +local COORDINATOR_VERSION = "beta-v0.9.12" local print = util.print local println = util.println diff --git a/coordinator/ui/components/processctl.lua b/coordinator/ui/components/processctl.lua index 5d18c91..98d04dd 100644 --- a/coordinator/ui/components/processctl.lua +++ b/coordinator/ui/components/processctl.lua @@ -60,7 +60,7 @@ local function new_view(root, x, y) facility.ps.subscribe("all_sys_ok", all_ok.update) facility.induction_ps_tbl[1].subscribe("computed_status", function (status) ind_mat.update(status > 1) end) - facility.ps.subscribe("RadMonOnline", rad_mon.update) + facility.ps.subscribe("rad_computed_status", rad_mon.update) main.line_break() @@ -76,13 +76,19 @@ local function new_view(root, x, y) main.line_break() - local auto_scram = IndicatorLight{parent=main,label="Automatic SCRAM",colors=cpair(colors.red,colors.gray),flash=true,period=period.BLINK_250_MS} - local _ = IndicatorLight{parent=main,label="Matrix Disconnected",colors=cpair(colors.yellow,colors.gray),flash=true,period=period.BLINK_250_MS} - local _ = IndicatorLight{parent=main,label="Matrix Charge High",colors=cpair(colors.red,colors.gray),flash=true,period=period.BLINK_250_MS} - local _ = IndicatorLight{parent=main,label="Unit Critical Alarm",colors=cpair(colors.red,colors.gray),flash=true,period=period.BLINK_250_MS} - local _ = IndicatorLight{parent=main,label="Gen. Control Fault",colors=cpair(colors.red,colors.gray),flash=true,period=period.BLINK_250_MS} + local auto_scram = IndicatorLight{parent=main,label="Automatic SCRAM",colors=cpair(colors.red,colors.gray),flash=true,period=period.BLINK_250_MS} + local matrix_dc = IndicatorLight{parent=main,label="Matrix Disconnected",colors=cpair(colors.yellow,colors.gray),flash=true,period=period.BLINK_500_MS} + local matrix_fill = IndicatorLight{parent=main,label="Matrix Charge High",colors=cpair(colors.red,colors.gray),flash=true,period=period.BLINK_500_MS} + local unit_crit = IndicatorLight{parent=main,label="Unit Critical Alarm",colors=cpair(colors.red,colors.gray),flash=true,period=period.BLINK_250_MS} + local fac_rad_h = IndicatorLight{parent=main,label="Facility Radiation High",colors=cpair(colors.red,colors.gray),flash=true,period=period.BLINK_250_MS} + local gen_fault = IndicatorLight{parent=main,label="Gen. Control Fault",colors=cpair(colors.yellow,colors.gray),flash=true,period=period.BLINK_500_MS} facility.ps.subscribe("auto_scram", auto_scram.update) + facility.ps.subscribe("as_matrix_dc", matrix_dc.update) + facility.ps.subscribe("as_matrix_fill", matrix_fill.update) + facility.ps.subscribe("as_crit_alarm", unit_crit.update) + facility.ps.subscribe("as_radiation", fac_rad_h.update) + facility.ps.subscribe("as_gen_fault", gen_fault.update) TextBox{parent=main,y=23,text="Radiation",height=1,width=21,fg_bg=style.label} local radiation = RadIndicator{parent=main,label="",format="%9.3f",lu_colors=lu_cpair,width=13,fg_bg=bw_fg_bg} diff --git a/coordinator/ui/components/unit_detail.lua b/coordinator/ui/components/unit_detail.lua index b08a319..ad66532 100644 --- a/coordinator/ui/components/unit_detail.lua +++ b/coordinator/ui/components/unit_detail.lua @@ -171,7 +171,7 @@ local function init(parent, id) u_ps.subscribe("PLCHeartbeat", plc_hbeat.update) u_ps.subscribe("status", r_active.update) u_ps.subscribe("AutoControl", r_auto.update) - u_ps.subscribe("RadMonOnline", rad_mon.update) + u_ps.subscribe("rad_computed_status", rad_mon.update) annunciator.line_break() diff --git a/supervisor/session/facility.lua b/supervisor/session/facility.lua index 864a0fe..0818210 100644 --- a/supervisor/session/facility.lua +++ b/supervisor/session/facility.lua @@ -15,6 +15,11 @@ local POWER_PER_BLADE = util.joules_to_fe(7140) local FLOW_STABILITY_DELAY_S = unit.FLOW_STABILITY_DELAY_MS / 1000 +-- background radiation 0.0000001 Sv/h (99.99 nSv/h) +-- "green tint" radiation 0.00001 Sv/h (10 uSv/h) +-- damaging radiation 0.00006 Sv/h (60 uSv/h) +local RADIATION_ALARM_LEVEL = 0.00001 + local HIGH_CHARGE = 1.0 local RE_ENABLE_CHARGE = 0.95 @@ -23,7 +28,8 @@ local AUTO_SCRAM = { MATRIX_DC = 1, MATRIX_FILL = 2, CRIT_ALARM = 3, - GEN_FAULT = 4 + RADIATION = 4, + GEN_FAULT = 5 } local START_STATUS = { @@ -70,10 +76,12 @@ function facility.new(num_reactors, cooling_conf) at_max_burn = false, ascram = false, ascram_reason = AUTO_SCRAM.NONE, + ---@class ascram_status ascram_status = { matrix_dc = false, matrix_fill = false, crit_alarm = false, + radiation = false, gen_fault = false }, -- closed loop control @@ -277,7 +285,7 @@ function facility.new(num_reactors, cooling_conf) if (self.last_mode == PROCESS.INACTIVE) or (self.last_mode == PROCESS.GEN_RATE_FAULT_IDLE) then self.start_fail = START_STATUS.OK - if (self.mode ~= PROCESS.MATRIX_FAULT_IDLE) and (self.mode ~= PROCESS.UNIT_ALARM_IDLE) then + if (self.mode ~= PROCESS.MATRIX_FAULT_IDLE) and (self.mode ~= PROCESS.SYSTEM_ALARM_IDLE) then -- auto clear ASCRAM self.ascram = false end @@ -488,12 +496,7 @@ function facility.new(num_reactors, cooling_conf) log.debug(util.sprintf("GEN_RATE[%f] { RATE[%f] ERR[%f] INT[%f] => OUT[%f] OUT_C[%f] <= P[%f] I[%f] D[%f] }", runtime, avg_inflow, error, integral, output, out_c, P, I, D)) - local _, fault = _allocate_burn_rate(out_c, false) - - if fault then - log.info("FAC: one or more units degraded, pausing GEN_RATE process control") - next_mode = PROCESS.GEN_RATE_FAULT_IDLE - end + _allocate_burn_rate(out_c, false) self.last_time = now self.last_error = error @@ -509,7 +512,7 @@ function facility.new(num_reactors, cooling_conf) next_mode = PROCESS.INACTIVE log.info("FAC: exiting matrix fault idle state due to critical unit alarm") end - elseif self.mode == PROCESS.UNIT_ALARM_IDLE then + elseif self.mode == PROCESS.SYSTEM_ALARM_IDLE then -- do nothing, wait for user to confirm (stop and reset) elseif self.mode == PROCESS.GEN_RATE_FAULT_IDLE then -- system faulted (degraded/not ready) while running generation rate mode @@ -529,7 +532,7 @@ function facility.new(num_reactors, cooling_conf) local astatus = self.ascram_status - if (self.mode ~= PROCESS.INACTIVE) and (self.mode ~= PROCESS.UNIT_ALARM_IDLE) then + if (self.mode ~= PROCESS.INACTIVE) and (self.mode ~= PROCESS.SYSTEM_ALARM_IDLE) then if self.induction[1] ~= nil then local matrix = self.induction[1] ---@type unit_session local db = matrix.get_db() ---@type imatrix_session_db @@ -548,10 +551,6 @@ function facility.new(num_reactors, cooling_conf) log.info("FAC: charge state of induction matrix entered acceptable range <= " .. (RE_ENABLE_CHARGE * 100) .. "%") end - -- system not ready, will need to restart GEN_RATE mode - -- clears when we enter the fault waiting state - astatus.gen_fault = self.mode == PROCESS.GEN_RATE and not self.units_ready - -- check for critical unit alarms for i = 1, #self.units do local u = self.units[i] ---@type reactor_unit @@ -561,6 +560,21 @@ function facility.new(num_reactors, cooling_conf) break end end + + -- check for facility radiation + if self.envd[1] ~= nil then + local envd = self.envd[1] ---@type unit_session + local e_db = envd.get_db() ---@type envd_session_db + + astatus.radiation = e_db.radiation_raw > RADIATION_ALARM_LEVEL + else + -- don't clear, if it is true then we lost it with high radiation, so just keep alarming + -- operator can restart the system or hit the stop/reset button + end + + -- system not ready, will need to restart GEN_RATE mode + -- clears when we enter the fault waiting state + astatus.gen_fault = self.mode == PROCESS.GEN_RATE and not self.units_ready else astatus.matrix_dc = true end @@ -579,11 +593,17 @@ function facility.new(num_reactors, cooling_conf) if astatus.crit_alarm then -- highest priority alarm - next_mode = PROCESS.UNIT_ALARM_IDLE + next_mode = PROCESS.SYSTEM_ALARM_IDLE self.ascram_reason = AUTO_SCRAM.CRIT_ALARM self.status_text = { "AUTOMATIC SCRAM", "critical unit alarm tripped" } log.info("FAC: automatic SCRAM due to critical unit alarm") + elseif astatus.radiation then + next_mode = PROCESS.SYSTEM_ALARM_IDLE + self.ascram_reason = AUTO_SCRAM.RADIATION + self.status_text = { "AUTOMATIC SCRAM", "facility radiation high" } + + log.info("FAC: automatic SCRAM due to high facility radiation") elseif astatus.matrix_dc then next_mode = PROCESS.MATRIX_FAULT_IDLE self.ascram_reason = AUTO_SCRAM.MATRIX_DC @@ -758,6 +778,7 @@ function facility.new(num_reactors, cooling_conf) -- get automatic process control status function public.get_control_status() + local astat = self.ascram_status return { self.all_sys_ok, self.units_ready, @@ -765,6 +786,11 @@ function facility.new(num_reactors, cooling_conf) self.waiting_on_ramp or self.waiting_on_stable, self.at_max_burn or self.saturated, self.ascram, + astat.matrix_dc, + astat.matrix_fill, + astat.crit_alarm, + astat.radiation, + astat.gen_fault or self.mode == PROCESS.GEN_RATE_FAULT_IDLE, self.status_text[1], self.status_text[2], self.group_map diff --git a/supervisor/startup.lua b/supervisor/startup.lua index 164624d..3e92d15 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.11.6" +local SUPERVISOR_VERSION = "beta-v0.11.7" local print = util.print local println = util.println