#171 unit auto SCRAM and improvements to emergency coolant control
This commit is contained in:
parent
1be57aaf13
commit
8df67245c5
@ -2,9 +2,9 @@
|
|||||||
"versions": {
|
"versions": {
|
||||||
"bootloader": "0.2",
|
"bootloader": "0.2",
|
||||||
"comms": "1.3.3",
|
"comms": "1.3.3",
|
||||||
"reactor-plc": "beta-v0.10.11",
|
"reactor-plc": "beta-v0.11.0",
|
||||||
"rtu": "beta-v0.11.1",
|
"rtu": "beta-v0.11.1",
|
||||||
"supervisor": "beta-v0.12.0",
|
"supervisor": "beta-v0.12.1",
|
||||||
"coordinator": "beta-v0.10.0",
|
"coordinator": "beta-v0.10.0",
|
||||||
"pocket": "alpha-v0.0.0"
|
"pocket": "alpha-v0.0.0"
|
||||||
},
|
},
|
||||||
@ -177,12 +177,12 @@
|
|||||||
},
|
},
|
||||||
"sizes": {
|
"sizes": {
|
||||||
"system": 1982,
|
"system": 1982,
|
||||||
"common": 88049,
|
"common": 88021,
|
||||||
"graphics": 99360,
|
"graphics": 99360,
|
||||||
"lockbox": 100797,
|
"lockbox": 100797,
|
||||||
"reactor-plc": 75915,
|
"reactor-plc": 75902,
|
||||||
"rtu": 81676,
|
"rtu": 81679,
|
||||||
"supervisor": 265030,
|
"supervisor": 267633,
|
||||||
"coordinator": 180849,
|
"coordinator": 180849,
|
||||||
"pocket": 335
|
"pocket": 335
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,7 +29,7 @@ local PCALL_START_MSG = "pcall: Reactor is already active."
|
|||||||
|
|
||||||
local MAX_DAMAGE_PERCENT = 90
|
local MAX_DAMAGE_PERCENT = 90
|
||||||
local MAX_DAMAGE_TEMPERATURE = 1200
|
local MAX_DAMAGE_TEMPERATURE = 1200
|
||||||
local MIN_COOLANT_FILL = 0.02
|
local MIN_COOLANT_FILL = 0.10
|
||||||
local MAX_WASTE_FILL = 0.8
|
local MAX_WASTE_FILL = 0.8
|
||||||
local MAX_HEATED_COLLANT_FILL = 0.95
|
local MAX_HEATED_COLLANT_FILL = 0.95
|
||||||
|
|
||||||
@ -206,7 +206,7 @@ function plc.rps_init(reactor, is_formed)
|
|||||||
self.state[state_keys.manual] = true
|
self.state[state_keys.manual] = true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- automatic SCRAM commanded by supervisor/coordinator
|
-- automatic SCRAM commanded by supervisor
|
||||||
function public.trip_auto()
|
function public.trip_auto()
|
||||||
self.state[state_keys.automatic] = true
|
self.state[state_keys.automatic] = true
|
||||||
end
|
end
|
||||||
|
|||||||
@ -14,7 +14,7 @@ local config = require("reactor-plc.config")
|
|||||||
local plc = require("reactor-plc.plc")
|
local plc = require("reactor-plc.plc")
|
||||||
local threads = require("reactor-plc.threads")
|
local threads = require("reactor-plc.threads")
|
||||||
|
|
||||||
local R_PLC_VERSION = "beta-v0.10.11"
|
local R_PLC_VERSION = "beta-v0.11.0"
|
||||||
|
|
||||||
local print = util.print
|
local print = util.print
|
||||||
local println = util.println
|
local println = util.println
|
||||||
|
|||||||
@ -299,7 +299,7 @@ end
|
|||||||
---@param level IO_LVL
|
---@param level IO_LVL
|
||||||
---@return boolean|nil
|
---@return boolean|nil
|
||||||
function rsio.digital_is_active(port, level)
|
function rsio.digital_is_active(port, level)
|
||||||
if (not util.is_int(port)) or (port > IO_PORT.U_ACK) then
|
if not util.is_int(port) then
|
||||||
return nil
|
return nil
|
||||||
elseif level == IO_LVL.FLOATING or level == IO_LVL.DISCONNECT then
|
elseif level == IO_LVL.FLOATING or level == IO_LVL.DISCONNECT then
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@ -14,7 +14,7 @@ local svsessions = require("supervisor.session.svsessions")
|
|||||||
local config = require("supervisor.config")
|
local config = require("supervisor.config")
|
||||||
local supervisor = require("supervisor.supervisor")
|
local supervisor = require("supervisor.supervisor")
|
||||||
|
|
||||||
local SUPERVISOR_VERSION = "beta-v0.12.0"
|
local SUPERVISOR_VERSION = "beta-v0.12.1"
|
||||||
|
|
||||||
local print = util.print
|
local print = util.print
|
||||||
local println = util.println
|
local println = util.println
|
||||||
|
|||||||
@ -82,7 +82,10 @@ function unit.new(for_reactor, num_boilers, num_turbines)
|
|||||||
-- redstone control
|
-- redstone control
|
||||||
io_ctl = nil, ---@type rs_controller
|
io_ctl = nil, ---@type rs_controller
|
||||||
valves = {}, ---@type unit_valves
|
valves = {}, ---@type unit_valves
|
||||||
|
emcool_opened = false,
|
||||||
-- auto control
|
-- auto control
|
||||||
|
auto_engaged = false,
|
||||||
|
auto_was_alarmed = false,
|
||||||
ramp_target_br100 = 0,
|
ramp_target_br100 = 0,
|
||||||
-- state tracking
|
-- state tracking
|
||||||
deltas = {},
|
deltas = {},
|
||||||
@ -141,25 +144,25 @@ function unit.new(for_reactor, num_boilers, num_turbines)
|
|||||||
-- radiation monitor alarm for this unit
|
-- radiation monitor alarm for this unit
|
||||||
ContainmentRadiation = { state = AISTATE.INACTIVE, trip_time = 0, hold_time = 0, id = ALARM.ContainmentRadiation, tier = PRIO.CRITICAL },
|
ContainmentRadiation = { state = AISTATE.INACTIVE, trip_time = 0, hold_time = 0, id = ALARM.ContainmentRadiation, tier = PRIO.CRITICAL },
|
||||||
-- reactor offline after being online
|
-- reactor offline after being online
|
||||||
ReactorLost = { state = AISTATE.INACTIVE, trip_time = 0, hold_time = 0, id = ALARM.ReactorLost, tier = PRIO.URGENT },
|
ReactorLost = { state = AISTATE.INACTIVE, trip_time = 0, hold_time = 0, id = ALARM.ReactorLost, tier = PRIO.TIMELY },
|
||||||
-- damage >100%
|
-- damage >100%
|
||||||
CriticalDamage = { state = AISTATE.INACTIVE, trip_time = 0, hold_time = 0, id = ALARM.CriticalDamage, tier = PRIO.CRITICAL },
|
CriticalDamage = { state = AISTATE.INACTIVE, trip_time = 0, hold_time = 0, id = ALARM.CriticalDamage, tier = PRIO.CRITICAL },
|
||||||
-- reactor damage increasing
|
-- reactor damage increasing
|
||||||
ReactorDamage = { state = AISTATE.INACTIVE, trip_time = 0, hold_time = 0, id = ALARM.ReactorDamage, tier = PRIO.EMERGENCY },
|
ReactorDamage = { state = AISTATE.INACTIVE, trip_time = 0, hold_time = 0, id = ALARM.ReactorDamage, tier = PRIO.EMERGENCY },
|
||||||
-- reactor >1200K
|
-- reactor >1200K
|
||||||
ReactorOverTemp = { state = AISTATE.INACTIVE, trip_time = 0, hold_time = 0, id = ALARM.ReactorOverTemp, tier = PRIO.URGENT },
|
ReactorOverTemp = { state = AISTATE.INACTIVE, trip_time = 0, hold_time = 0, id = ALARM.ReactorOverTemp, tier = PRIO.URGENT },
|
||||||
-- reactor >1100K
|
-- reactor >1150K
|
||||||
ReactorHighTemp = { state = AISTATE.INACTIVE, trip_time = 0, hold_time = 2, id = ALARM.ReactorHighTemp, tier = PRIO.TIMELY },
|
ReactorHighTemp = { state = AISTATE.INACTIVE, trip_time = 0, hold_time = 1, id = ALARM.ReactorHighTemp, tier = PRIO.TIMELY },
|
||||||
-- waste = 100%
|
-- waste = 100%
|
||||||
ReactorWasteLeak = { state = AISTATE.INACTIVE, trip_time = 0, hold_time = 0, id = ALARM.ReactorWasteLeak, tier = PRIO.EMERGENCY },
|
ReactorWasteLeak = { state = AISTATE.INACTIVE, trip_time = 0, hold_time = 0, id = ALARM.ReactorWasteLeak, tier = PRIO.EMERGENCY },
|
||||||
-- waste >85%
|
-- waste >85%
|
||||||
ReactorHighWaste = { state = AISTATE.INACTIVE, trip_time = 0, hold_time = 2, id = ALARM.ReactorHighWaste, tier = PRIO.TIMELY },
|
ReactorHighWaste = { state = AISTATE.INACTIVE, trip_time = 0, hold_time = 2, id = ALARM.ReactorHighWaste, tier = PRIO.URGENT },
|
||||||
-- RPS trip occured
|
-- RPS trip occured
|
||||||
RPSTransient = { state = AISTATE.INACTIVE, trip_time = 0, hold_time = 1, id = ALARM.RPSTransient, tier = PRIO.TIMELY },
|
RPSTransient = { state = AISTATE.INACTIVE, trip_time = 0, hold_time = 2, id = ALARM.RPSTransient, tier = PRIO.TIMELY },
|
||||||
-- BoilRateMismatch, CoolantFeedMismatch, SteamFeedMismatch, MaxWaterReturnFeed
|
-- BoilRateMismatch, CoolantFeedMismatch, SteamFeedMismatch, MaxWaterReturnFeed
|
||||||
RCSTransient = { state = AISTATE.INACTIVE, trip_time = 0, hold_time = 5, id = ALARM.RCSTransient, tier = PRIO.TIMELY },
|
RCSTransient = { state = AISTATE.INACTIVE, trip_time = 0, hold_time = 5, id = ALARM.RCSTransient, tier = PRIO.TIMELY },
|
||||||
-- "It's just a routine turbin' trip!" -Bill Gibson, "The China Syndrome"
|
-- "It's just a routine turbin' trip!" -Bill Gibson, "The China Syndrome"
|
||||||
TurbineTrip = { state = AISTATE.INACTIVE, trip_time = 0, hold_time = 1, id = ALARM.TurbineTrip, tier = PRIO.URGENT }
|
TurbineTrip = { state = AISTATE.INACTIVE, trip_time = 0, hold_time = 2, id = ALARM.TurbineTrip, tier = PRIO.URGENT }
|
||||||
},
|
},
|
||||||
---@class unit_db
|
---@class unit_db
|
||||||
db = {
|
db = {
|
||||||
@ -488,12 +491,17 @@ function unit.new(for_reactor, num_boilers, num_turbines)
|
|||||||
-- update alarm status
|
-- update alarm status
|
||||||
logic.update_alarms(self)
|
logic.update_alarms(self)
|
||||||
|
|
||||||
|
-- if in auto mode, SCRAM on certain alarms
|
||||||
|
logic.update_auto_safety(public, self)
|
||||||
|
|
||||||
-- update status text
|
-- update status text
|
||||||
logic.update_status_text(self)
|
logic.update_status_text(self)
|
||||||
|
|
||||||
-- handle redstone I/O
|
-- handle redstone I/O
|
||||||
if #self.redstone > 0 then
|
if #self.redstone > 0 then
|
||||||
logic.handle_redstone(self)
|
logic.handle_redstone(self)
|
||||||
|
elseif not self.plc_cache.rps_trip then
|
||||||
|
self.emcool_opened = false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -502,7 +510,7 @@ function unit.new(for_reactor, num_boilers, num_turbines)
|
|||||||
|
|
||||||
-- engage automatic control
|
-- engage automatic control
|
||||||
function public.a_engage()
|
function public.a_engage()
|
||||||
self.db.annunciator.AutoControl = true
|
self.auto_engaged = true
|
||||||
if self.plc_i ~= nil then
|
if self.plc_i ~= nil then
|
||||||
self.plc_i.auto_lock(true)
|
self.plc_i.auto_lock(true)
|
||||||
end
|
end
|
||||||
@ -510,7 +518,7 @@ function unit.new(for_reactor, num_boilers, num_turbines)
|
|||||||
|
|
||||||
-- disengage automatic control
|
-- disengage automatic control
|
||||||
function public.a_disengage()
|
function public.a_disengage()
|
||||||
self.db.annunciator.AutoControl = false
|
self.auto_engaged = false
|
||||||
if self.plc_i ~= nil then
|
if self.plc_i ~= nil then
|
||||||
self.plc_i.auto_lock(false)
|
self.plc_i.auto_lock(false)
|
||||||
self.db.control.br100 = 0
|
self.db.control.br100 = 0
|
||||||
@ -533,7 +541,7 @@ function unit.new(for_reactor, num_boilers, num_turbines)
|
|||||||
-- set the automatic burn rate based on the last set burn rate in 100ths
|
-- set the automatic burn rate based on the last set burn rate in 100ths
|
||||||
---@param ramp boolean true to ramp to rate, false to set right away
|
---@param ramp boolean true to ramp to rate, false to set right away
|
||||||
function public.a_commit_br100(ramp)
|
function public.a_commit_br100(ramp)
|
||||||
if self.db.annunciator.AutoControl then
|
if self.auto_engaged then
|
||||||
if self.plc_i ~= nil then
|
if self.plc_i ~= nil then
|
||||||
self.plc_i.auto_set_burn(self.db.control.br100 / 100, ramp)
|
self.plc_i.auto_set_burn(self.db.control.br100 / 100, ramp)
|
||||||
|
|
||||||
@ -562,7 +570,7 @@ function unit.new(for_reactor, num_boilers, num_turbines)
|
|||||||
|
|
||||||
-- queue a command to clear timeout/auto-scram if set
|
-- queue a command to clear timeout/auto-scram if set
|
||||||
function public.a_cond_rps_reset()
|
function public.a_cond_rps_reset()
|
||||||
if self.plc_s ~= nil and self.plc_i ~= nil then
|
if self.plc_s ~= nil and self.plc_i ~= nil and (not self.auto_was_alarmed) and (not self.emcool_opened) then
|
||||||
local rps = self.plc_i.get_rps()
|
local rps = self.plc_i.get_rps()
|
||||||
if rps.timeout or rps.automatic then
|
if rps.timeout or rps.automatic then
|
||||||
self.plc_i.auto_lock(true) -- if it timed out/restarted, auto lock was lost, so re-lock it
|
self.plc_i.auto_lock(true) -- if it timed out/restarted, auto lock was lost, so re-lock it
|
||||||
@ -668,8 +676,8 @@ function unit.new(for_reactor, num_boilers, num_turbines)
|
|||||||
|
|
||||||
-- check if a critical alarm is tripped
|
-- check if a critical alarm is tripped
|
||||||
function public.has_critical_alarm()
|
function public.has_critical_alarm()
|
||||||
for _, data in pairs(self.alarms) do
|
for _, alarm in pairs(self.alarms) do
|
||||||
if data.tier == PRIO.CRITICAL and (data.state == AISTATE.TRIPPED or data.state == AISTATE.ACKED) then
|
if alarm.tier == PRIO.CRITICAL and (alarm.state == AISTATE.TRIPPED or alarm.state == AISTATE.ACKED) then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -5,6 +5,7 @@ local util = require("scada-common.util")
|
|||||||
|
|
||||||
local plc = require("supervisor.session.plc")
|
local plc = require("supervisor.session.plc")
|
||||||
|
|
||||||
|
local PRIO = types.ALARM_PRIORITY
|
||||||
local ALARM_STATE = types.ALARM_STATE
|
local ALARM_STATE = types.ALARM_STATE
|
||||||
|
|
||||||
local TRI_FAIL = types.TRI_FAIL
|
local TRI_FAIL = types.TRI_FAIL
|
||||||
@ -50,6 +51,8 @@ function logic.update_annunciator(self)
|
|||||||
-- REACTOR --
|
-- REACTOR --
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
self.db.annunciator.AutoControl = self.auto_engaged
|
||||||
|
|
||||||
-- check PLC status
|
-- check PLC status
|
||||||
self.db.annunciator.PLCOnline = self.plc_i ~= nil
|
self.db.annunciator.PLCOnline = self.plc_i ~= nil
|
||||||
|
|
||||||
@ -109,7 +112,7 @@ function logic.update_annunciator(self)
|
|||||||
self.db.annunciator.AutoReactorSCRAM = plc_db.rps_trip_cause == types.rps_status_t.automatic
|
self.db.annunciator.AutoReactorSCRAM = plc_db.rps_trip_cause == types.rps_status_t.automatic
|
||||||
self.db.annunciator.RCPTrip = plc_db.rps_tripped and (plc_db.rps_status.ex_hcool or plc_db.rps_status.no_cool)
|
self.db.annunciator.RCPTrip = plc_db.rps_tripped and (plc_db.rps_status.ex_hcool or plc_db.rps_status.no_cool)
|
||||||
self.db.annunciator.RCSFlowLow = _get_dt(DT_KEYS.ReactorCCool) < -2.0
|
self.db.annunciator.RCSFlowLow = _get_dt(DT_KEYS.ReactorCCool) < -2.0
|
||||||
self.db.annunciator.CoolantLevelLow = plc_db.mek_status.ccool_fill < 0.5
|
self.db.annunciator.CoolantLevelLow = plc_db.mek_status.ccool_fill < 0.4
|
||||||
self.db.annunciator.ReactorTempHigh = plc_db.mek_status.temp > 1000
|
self.db.annunciator.ReactorTempHigh = plc_db.mek_status.temp > 1000
|
||||||
self.db.annunciator.ReactorHighDeltaT = _get_dt(DT_KEYS.ReactorTemp) > 100
|
self.db.annunciator.ReactorHighDeltaT = _get_dt(DT_KEYS.ReactorTemp) > 100
|
||||||
self.db.annunciator.FuelInputRateLow = _get_dt(DT_KEYS.ReactorFuel) < -1.0 or plc_db.mek_status.fuel_fill <= 0.01
|
self.db.annunciator.FuelInputRateLow = _get_dt(DT_KEYS.ReactorFuel) < -1.0 or plc_db.mek_status.fuel_fill <= 0.01
|
||||||
@ -515,6 +518,37 @@ function logic.update_alarms(self)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- update the internal automatic safety control performed while in auto control mode
|
||||||
|
---@param public reactor_unit reactor unit public functions
|
||||||
|
---@param self _unit_self unit instance
|
||||||
|
function logic.update_auto_safety(public, self)
|
||||||
|
local AISTATE = self.types.AISTATE
|
||||||
|
|
||||||
|
if self.auto_engaged then
|
||||||
|
local alarmed = false
|
||||||
|
|
||||||
|
for _, alarm in pairs(self.alarms) do
|
||||||
|
if alarm.tier <= PRIO.URGENT and (alarm.state == AISTATE.TRIPPED or alarm.state == AISTATE.ACKED) then
|
||||||
|
if not self.auto_was_alarmed then
|
||||||
|
log.info(util.c("UNIT ", self.r_id, " AUTO SCRAM due to ALARM ", alarm.id, " (", types.alarm_string[alarm.id], ") [PRIORITY ",
|
||||||
|
types.alarm_prio_string[alarm.tier + 1],"]"))
|
||||||
|
end
|
||||||
|
|
||||||
|
alarmed = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if alarmed and not self.plc_cache.rps_status.automatic then
|
||||||
|
public.a_scram()
|
||||||
|
end
|
||||||
|
|
||||||
|
self.auto_was_alarmed = alarmed
|
||||||
|
else
|
||||||
|
self.auto_was_alarmed = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- update the two unit status text messages
|
-- update the two unit status text messages
|
||||||
---@param self _unit_self unit instance
|
---@param self _unit_self unit instance
|
||||||
function logic.update_status_text(self)
|
function logic.update_status_text(self)
|
||||||
@ -570,6 +604,8 @@ function logic.update_status_text(self)
|
|||||||
self.status_text = { "WASTE LEVEL HIGH", "waste accumulating in reactor" }
|
self.status_text = { "WASTE LEVEL HIGH", "waste accumulating in reactor" }
|
||||||
elseif is_active(self.alarms.TurbineTrip) then
|
elseif is_active(self.alarms.TurbineTrip) then
|
||||||
self.status_text = { "TURBINE TRIP", "turbine stall occured" }
|
self.status_text = { "TURBINE TRIP", "turbine stall occured" }
|
||||||
|
elseif self.emcool_opened then
|
||||||
|
self.status_text = { "EMERGENCY COOLANT OPENED", "reset RPS to close valve" }
|
||||||
-- connection dependent states
|
-- connection dependent states
|
||||||
elseif self.plc_i ~= nil then
|
elseif self.plc_i ~= nil then
|
||||||
local plc_db = self.plc_i.get_db()
|
local plc_db = self.plc_i.get_db()
|
||||||
@ -641,6 +677,15 @@ end
|
|||||||
-- handle unit redstone I/O
|
-- handle unit redstone I/O
|
||||||
---@param self _unit_self unit instance
|
---@param self _unit_self unit instance
|
||||||
function logic.handle_redstone(self)
|
function logic.handle_redstone(self)
|
||||||
|
local AISTATE = self.types.AISTATE
|
||||||
|
|
||||||
|
-- check if an alarm is active (tripped or ack'd)
|
||||||
|
---@param alarm table alarm entry
|
||||||
|
---@return boolean active
|
||||||
|
local function is_active(alarm)
|
||||||
|
return alarm.state == AISTATE.TRIPPED or alarm.state == AISTATE.ACKED
|
||||||
|
end
|
||||||
|
|
||||||
-- reactor controls
|
-- reactor controls
|
||||||
if self.plc_s ~= nil then
|
if self.plc_s ~= nil then
|
||||||
if (not self.plc_cache.rps_status.manual) and self.io_ctl.digital_read(IO.R_SCRAM) then
|
if (not self.plc_cache.rps_status.manual) and self.io_ctl.digital_read(IO.R_SCRAM) then
|
||||||
@ -653,7 +698,7 @@ function logic.handle_redstone(self)
|
|||||||
self.plc_s.in_queue.push_command(PLC_S_CMDS.RPS_RESET)
|
self.plc_s.in_queue.push_command(PLC_S_CMDS.RPS_RESET)
|
||||||
end
|
end
|
||||||
|
|
||||||
if (not self.db.annunciator.AutoControl) and (not self.plc_cache.active) and
|
if (not self.auto_engaged) and (not self.plc_cache.active) and
|
||||||
(not self.plc_cache.rps_trip) and self.io_ctl.digital_read(IO.R_ACTIVE) then
|
(not self.plc_cache.rps_trip) and self.io_ctl.digital_read(IO.R_ACTIVE) then
|
||||||
-- reactor enable requested and allowable, but not yet done; perform it
|
-- reactor enable requested and allowable, but not yet done; perform it
|
||||||
self.plc_s.in_queue.push_command(PLC_S_CMDS.ENABLE)
|
self.plc_s.in_queue.push_command(PLC_S_CMDS.ENABLE)
|
||||||
@ -671,7 +716,7 @@ function logic.handle_redstone(self)
|
|||||||
|
|
||||||
-- write reactor status outputs
|
-- write reactor status outputs
|
||||||
self.io_ctl.digital_write(IO.R_ACTIVE, self.plc_cache.active)
|
self.io_ctl.digital_write(IO.R_ACTIVE, self.plc_cache.active)
|
||||||
self.io_ctl.digital_write(IO.R_AUTO_CTRL, self.db.annunciator.AutoControl)
|
self.io_ctl.digital_write(IO.R_AUTO_CTRL, self.auto_engaged)
|
||||||
self.io_ctl.digital_write(IO.R_SCRAMMED, self.plc_cache.rps_trip)
|
self.io_ctl.digital_write(IO.R_SCRAMMED, self.plc_cache.rps_trip)
|
||||||
self.io_ctl.digital_write(IO.R_AUTO_SCRAM, self.plc_cache.rps_status.automatic)
|
self.io_ctl.digital_write(IO.R_AUTO_SCRAM, self.plc_cache.rps_status.automatic)
|
||||||
self.io_ctl.digital_write(IO.R_DMG_CRIT, self.plc_cache.rps_status.dmg_crit)
|
self.io_ctl.digital_write(IO.R_DMG_CRIT, self.plc_cache.rps_status.dmg_crit)
|
||||||
@ -695,13 +740,32 @@ function logic.handle_redstone(self)
|
|||||||
|
|
||||||
self.io_ctl.digital_write(IO.U_ALARM, has_alarm)
|
self.io_ctl.digital_write(IO.U_ALARM, has_alarm)
|
||||||
|
|
||||||
-- check if emergency coolant is needed
|
-----------------------
|
||||||
if self.plc_cache.rps_status.no_cool then
|
-- Emergency Coolant --
|
||||||
self.valves.emer_cool.open()
|
-----------------------
|
||||||
elseif not self.plc_cache.rps_trip then
|
|
||||||
|
local enable_emer_cool = self.plc_cache.rps_status.no_cool or
|
||||||
|
(self.auto_engaged and self.db.annunciator.CoolantLevelLow and is_active(self.alarms.ReactorOverTemp))
|
||||||
|
|
||||||
|
if not self.plc_cache.rps_trip then
|
||||||
-- can't turn off on sufficient coolant level since it might drop again
|
-- can't turn off on sufficient coolant level since it might drop again
|
||||||
-- turn off once system is OK again
|
-- turn off once system is OK again
|
||||||
|
-- if auto control is engaged, alarm check will SCRAM on reactor over temp so that's covered
|
||||||
self.valves.emer_cool.close()
|
self.valves.emer_cool.close()
|
||||||
|
|
||||||
|
if self.db.annunciator.EmergencyCoolant > 1 and self.emcool_opened then
|
||||||
|
log.info(util.c("UNIT ", self.r_id, " emergency coolant valve closed"))
|
||||||
|
end
|
||||||
|
|
||||||
|
self.emcool_opened = false
|
||||||
|
elseif enable_emer_cool or self.emcool_opened then
|
||||||
|
self.valves.emer_cool.open()
|
||||||
|
|
||||||
|
if self.db.annunciator.EmergencyCoolant > 1 and not self.emcool_opened then
|
||||||
|
log.info(util.c("UNIT ", self.r_id, " emergency coolant valve opened"))
|
||||||
|
end
|
||||||
|
|
||||||
|
self.emcool_opened = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user