mirror of
https://github.com/MikaylaFischler/cc-mek-scada.git
synced 2024-08-30 18:22:34 +00:00
#159 linked up redstone I/O
This commit is contained in:
parent
caa6cc81b1
commit
cc5ea0dbb0
@ -25,7 +25,7 @@ local sna_rtu = require("rtu.dev.sna_rtu")
|
|||||||
local sps_rtu = require("rtu.dev.sps_rtu")
|
local sps_rtu = require("rtu.dev.sps_rtu")
|
||||||
local turbinev_rtu = require("rtu.dev.turbinev_rtu")
|
local turbinev_rtu = require("rtu.dev.turbinev_rtu")
|
||||||
|
|
||||||
local RTU_VERSION = "beta-v0.10.6"
|
local RTU_VERSION = "beta-v0.11.0"
|
||||||
|
|
||||||
local rtu_t = types.rtu_t
|
local rtu_t = types.rtu_t
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ local rsio = {}
|
|||||||
-- RS I/O CONSTANTS --
|
-- RS I/O CONSTANTS --
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
---@alias IO_LVL integer
|
---@enum IO_LVL I/O logic level
|
||||||
local IO_LVL = {
|
local IO_LVL = {
|
||||||
DISCONNECT = -1, -- use for RTU session to indicate this RTU is not connected to this port
|
DISCONNECT = -1, -- use for RTU session to indicate this RTU is not connected to this port
|
||||||
LOW = 0,
|
LOW = 0,
|
||||||
@ -19,13 +19,13 @@ local IO_LVL = {
|
|||||||
FLOATING = 2 -- use for RTU session to indicate this RTU is connected but not yet read
|
FLOATING = 2 -- use for RTU session to indicate this RTU is connected but not yet read
|
||||||
}
|
}
|
||||||
|
|
||||||
---@alias IO_DIR integer
|
---@enum IO_DIR I/O direction
|
||||||
local IO_DIR = {
|
local IO_DIR = {
|
||||||
IN = 0,
|
IN = 0,
|
||||||
OUT = 1
|
OUT = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
---@alias IO_MODE integer
|
---@enum IO_MODE I/O mode (digital/analog input/output)
|
||||||
local IO_MODE = {
|
local IO_MODE = {
|
||||||
DIGITAL_IN = 0,
|
DIGITAL_IN = 0,
|
||||||
DIGITAL_OUT = 1,
|
DIGITAL_OUT = 1,
|
||||||
@ -33,45 +33,50 @@ local IO_MODE = {
|
|||||||
ANALOG_OUT = 3
|
ANALOG_OUT = 3
|
||||||
}
|
}
|
||||||
|
|
||||||
---@alias IO_PORT integer
|
---@enum IO_PORT redstone I/O logic port
|
||||||
local IO_PORT = {
|
local IO_PORT = {
|
||||||
-- digital inputs --
|
-- digital inputs --
|
||||||
|
|
||||||
-- facility
|
-- facility
|
||||||
F_SCRAM = 1, -- active low, facility-wide scram
|
F_SCRAM = 1, -- active low, facility-wide scram
|
||||||
|
F_ACK = 2, -- active high, facility alarm acknowledge
|
||||||
|
|
||||||
-- reactor
|
-- reactor
|
||||||
R_SCRAM = 2, -- active low, reactor scram
|
R_SCRAM = 3, -- active low, reactor scram
|
||||||
R_ENABLE = 3, -- active high, reactor enable
|
R_RESET = 4, -- active high, reactor RPS reset
|
||||||
|
R_ENABLE = 5, -- active high, reactor enable
|
||||||
|
|
||||||
|
-- unit
|
||||||
|
U_ACK = 6, -- active high, unit alarm acknowledge
|
||||||
|
|
||||||
-- digital outputs --
|
-- digital outputs --
|
||||||
|
|
||||||
-- facility
|
-- facility
|
||||||
F_ALARM = 4, -- active high, facility safety alarm
|
F_ALARM = 7, -- active high, facility alarm (any high priority unit alarm)
|
||||||
|
|
||||||
-- waste
|
-- waste
|
||||||
WASTE_PU = 5, -- active low, waste -> plutonium -> pellets route
|
WASTE_PU = 8, -- active low, waste -> plutonium -> pellets route
|
||||||
WASTE_PO = 6, -- active low, waste -> polonium route
|
WASTE_PO = 9, -- active low, waste -> polonium route
|
||||||
WASTE_POPL = 7, -- active low, polonium -> pellets route
|
WASTE_POPL = 10, -- active low, polonium -> pellets route
|
||||||
WASTE_AM = 8, -- active low, polonium -> anti-matter route
|
WASTE_AM = 11, -- active low, polonium -> anti-matter route
|
||||||
|
|
||||||
-- reactor
|
-- reactor
|
||||||
R_ALARM = 9, -- active high, reactor safety alarm
|
|
||||||
R_SCRAMMED = 10, -- active high, if the reactor is scrammed
|
|
||||||
R_AUTO_SCRAM = 11, -- active high, if the reactor was automatically scrammed
|
|
||||||
R_ACTIVE = 12, -- active high, if the reactor is active
|
R_ACTIVE = 12, -- active high, if the reactor is active
|
||||||
R_AUTO_CTRL = 13, -- active high, if the reactor burn rate is automatic
|
R_AUTO_CTRL = 13, -- active high, if the reactor burn rate is automatic
|
||||||
R_DMG_CRIT = 14, -- active high, if the reactor damage is critical
|
R_SCRAMMED = 14, -- active high, if the reactor is scrammed
|
||||||
R_HIGH_TEMP = 15, -- active high, if the reactor is at a high temperature
|
R_AUTO_SCRAM = 15, -- active high, if the reactor was automatically scrammed
|
||||||
R_NO_COOLANT = 16, -- active high, if the reactor has no coolant
|
R_DMG_CRIT = 16, -- active high, if the reactor damage is critical
|
||||||
R_EXCESS_HC = 17, -- active high, if the reactor has excess heated coolant
|
R_HIGH_TEMP = 17, -- active high, if the reactor is at a high temperature
|
||||||
R_EXCESS_WS = 18, -- active high, if the reactor has excess waste
|
R_NO_COOLANT = 18, -- active high, if the reactor has no coolant
|
||||||
R_INSUFF_FUEL = 19, -- active high, if the reactor has insufficent fuel
|
R_EXCESS_HC = 19, -- active high, if the reactor has excess heated coolant
|
||||||
R_PLC_FAULT = 20, -- active high, if the reactor PLC reports a device access fault
|
R_EXCESS_WS = 20, -- active high, if the reactor has excess waste
|
||||||
R_PLC_TIMEOUT = 21, -- active high, if the reactor PLC has not been heard from
|
R_INSUFF_FUEL = 21, -- active high, if the reactor has insufficent fuel
|
||||||
|
R_PLC_FAULT = 22, -- active high, if the reactor PLC reports a device access fault
|
||||||
|
R_PLC_TIMEOUT = 23, -- active high, if the reactor PLC has not been heard from
|
||||||
|
|
||||||
-- unit outputs
|
-- unit outputs
|
||||||
U_EMER_COOL = 22 -- active low, emergency coolant control
|
U_ALARM = 24, -- active high, unit alarm
|
||||||
|
U_EMER_COOL = 25 -- active low, emergency coolant control
|
||||||
}
|
}
|
||||||
|
|
||||||
rsio.IO_LVL = IO_LVL
|
rsio.IO_LVL = IO_LVL
|
||||||
@ -88,18 +93,20 @@ rsio.IO = IO_PORT
|
|||||||
function rsio.to_string(port)
|
function rsio.to_string(port)
|
||||||
local names = {
|
local names = {
|
||||||
"F_SCRAM",
|
"F_SCRAM",
|
||||||
|
"F_ACK",
|
||||||
"R_SCRAM",
|
"R_SCRAM",
|
||||||
|
"R_RESET",
|
||||||
"R_ENABLE",
|
"R_ENABLE",
|
||||||
|
"U_ACK",
|
||||||
"F_ALARM",
|
"F_ALARM",
|
||||||
"WASTE_PU",
|
"WASTE_PU",
|
||||||
"WASTE_PO",
|
"WASTE_PO",
|
||||||
"WASTE_POPL",
|
"WASTE_POPL",
|
||||||
"WASTE_AM",
|
"WASTE_AM",
|
||||||
"R_ALARM",
|
|
||||||
"R_SCRAMMED",
|
|
||||||
"R_AUTO_SCRAM",
|
|
||||||
"R_ACTIVE",
|
"R_ACTIVE",
|
||||||
"R_AUTO_CTRL",
|
"R_AUTO_CTRL",
|
||||||
|
"R_SCRAMMED",
|
||||||
|
"R_AUTO_SCRAM",
|
||||||
"R_DMG_CRIT",
|
"R_DMG_CRIT",
|
||||||
"R_HIGH_TEMP",
|
"R_HIGH_TEMP",
|
||||||
"R_NO_COOLANT",
|
"R_NO_COOLANT",
|
||||||
@ -108,6 +115,7 @@ function rsio.to_string(port)
|
|||||||
"R_INSUFF_FUEL",
|
"R_INSUFF_FUEL",
|
||||||
"R_PLC_FAULT",
|
"R_PLC_FAULT",
|
||||||
"R_PLC_TIMEOUT",
|
"R_PLC_TIMEOUT",
|
||||||
|
"U_ALARM",
|
||||||
"U_EMER_COOL"
|
"U_EMER_COOL"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,12 +137,22 @@ local function _O_ACTIVE_LOW(active) if active then return IO_LVL.LOW else retur
|
|||||||
local RS_DIO_MAP = {
|
local RS_DIO_MAP = {
|
||||||
-- F_SCRAM
|
-- F_SCRAM
|
||||||
{ _in = _I_ACTIVE_LOW, _out = _O_ACTIVE_LOW, mode = IO_DIR.IN },
|
{ _in = _I_ACTIVE_LOW, _out = _O_ACTIVE_LOW, mode = IO_DIR.IN },
|
||||||
|
-- F_ACK
|
||||||
|
{ _in = _I_ACTIVE_HIGH, _out = _O_ACTIVE_HIGH, mode = IO_DIR.IN },
|
||||||
|
|
||||||
-- R_SCRAM
|
-- R_SCRAM
|
||||||
{ _in = _I_ACTIVE_LOW, _out = _O_ACTIVE_LOW, mode = IO_DIR.IN },
|
{ _in = _I_ACTIVE_LOW, _out = _O_ACTIVE_LOW, mode = IO_DIR.IN },
|
||||||
|
-- R_RESET
|
||||||
|
{ _in = _I_ACTIVE_HIGH, _out = _O_ACTIVE_HIGH, mode = IO_DIR.IN },
|
||||||
-- R_ENABLE
|
-- R_ENABLE
|
||||||
{ _in = _I_ACTIVE_HIGH, _out = _O_ACTIVE_HIGH, mode = IO_DIR.IN },
|
{ _in = _I_ACTIVE_HIGH, _out = _O_ACTIVE_HIGH, mode = IO_DIR.IN },
|
||||||
|
|
||||||
|
-- U_ACK
|
||||||
|
{ _in = _I_ACTIVE_HIGH, _out = _O_ACTIVE_HIGH, mode = IO_DIR.IN },
|
||||||
|
|
||||||
-- F_ALARM
|
-- F_ALARM
|
||||||
{ _in = _I_ACTIVE_HIGH, _out = _O_ACTIVE_HIGH, mode = IO_DIR.OUT },
|
{ _in = _I_ACTIVE_HIGH, _out = _O_ACTIVE_HIGH, mode = IO_DIR.OUT },
|
||||||
|
|
||||||
-- WASTE_PU
|
-- WASTE_PU
|
||||||
{ _in = _I_ACTIVE_LOW, _out = _O_ACTIVE_LOW, mode = IO_DIR.OUT },
|
{ _in = _I_ACTIVE_LOW, _out = _O_ACTIVE_LOW, mode = IO_DIR.OUT },
|
||||||
-- WASTE_PO
|
-- WASTE_PO
|
||||||
@ -143,16 +161,15 @@ local RS_DIO_MAP = {
|
|||||||
{ _in = _I_ACTIVE_LOW, _out = _O_ACTIVE_LOW, mode = IO_DIR.OUT },
|
{ _in = _I_ACTIVE_LOW, _out = _O_ACTIVE_LOW, mode = IO_DIR.OUT },
|
||||||
-- WASTE_AM
|
-- WASTE_AM
|
||||||
{ _in = _I_ACTIVE_LOW, _out = _O_ACTIVE_LOW, mode = IO_DIR.OUT },
|
{ _in = _I_ACTIVE_LOW, _out = _O_ACTIVE_LOW, mode = IO_DIR.OUT },
|
||||||
-- R_ALARM
|
|
||||||
|
-- R_ACTIVE
|
||||||
|
{ _in = _I_ACTIVE_HIGH, _out = _O_ACTIVE_HIGH, mode = IO_DIR.OUT },
|
||||||
|
-- R_AUTO_CTRL
|
||||||
{ _in = _I_ACTIVE_HIGH, _out = _O_ACTIVE_HIGH, mode = IO_DIR.OUT },
|
{ _in = _I_ACTIVE_HIGH, _out = _O_ACTIVE_HIGH, mode = IO_DIR.OUT },
|
||||||
-- R_SCRAMMED
|
-- R_SCRAMMED
|
||||||
{ _in = _I_ACTIVE_HIGH, _out = _O_ACTIVE_HIGH, mode = IO_DIR.OUT },
|
{ _in = _I_ACTIVE_HIGH, _out = _O_ACTIVE_HIGH, mode = IO_DIR.OUT },
|
||||||
-- R_AUTO_SCRAM
|
-- R_AUTO_SCRAM
|
||||||
{ _in = _I_ACTIVE_HIGH, _out = _O_ACTIVE_HIGH, mode = IO_DIR.OUT },
|
{ _in = _I_ACTIVE_HIGH, _out = _O_ACTIVE_HIGH, mode = IO_DIR.OUT },
|
||||||
-- R_ACTIVE
|
|
||||||
{ _in = _I_ACTIVE_HIGH, _out = _O_ACTIVE_HIGH, mode = IO_DIR.OUT },
|
|
||||||
-- R_AUTO_CTRL
|
|
||||||
{ _in = _I_ACTIVE_HIGH, _out = _O_ACTIVE_HIGH, mode = IO_DIR.OUT },
|
|
||||||
-- R_DMG_CRIT
|
-- R_DMG_CRIT
|
||||||
{ _in = _I_ACTIVE_HIGH, _out = _O_ACTIVE_HIGH, mode = IO_DIR.OUT },
|
{ _in = _I_ACTIVE_HIGH, _out = _O_ACTIVE_HIGH, mode = IO_DIR.OUT },
|
||||||
-- R_HIGH_TEMP
|
-- R_HIGH_TEMP
|
||||||
@ -169,6 +186,9 @@ local RS_DIO_MAP = {
|
|||||||
{ _in = _I_ACTIVE_HIGH, _out = _O_ACTIVE_HIGH, mode = IO_DIR.OUT },
|
{ _in = _I_ACTIVE_HIGH, _out = _O_ACTIVE_HIGH, mode = IO_DIR.OUT },
|
||||||
-- R_PLC_TIMEOUT
|
-- R_PLC_TIMEOUT
|
||||||
{ _in = _I_ACTIVE_HIGH, _out = _O_ACTIVE_HIGH, mode = IO_DIR.OUT },
|
{ _in = _I_ACTIVE_HIGH, _out = _O_ACTIVE_HIGH, mode = IO_DIR.OUT },
|
||||||
|
|
||||||
|
-- U_ALARM
|
||||||
|
{ _in = _I_ACTIVE_HIGH, _out = _O_ACTIVE_HIGH, mode = IO_DIR.OUT },
|
||||||
-- U_EMER_COOL
|
-- U_EMER_COOL
|
||||||
{ _in = _I_ACTIVE_LOW, _out = _O_ACTIVE_LOW, mode = IO_DIR.OUT }
|
{ _in = _I_ACTIVE_LOW, _out = _O_ACTIVE_LOW, mode = IO_DIR.OUT }
|
||||||
}
|
}
|
||||||
@ -179,18 +199,20 @@ local RS_DIO_MAP = {
|
|||||||
function rsio.get_io_mode(port)
|
function rsio.get_io_mode(port)
|
||||||
local modes = {
|
local modes = {
|
||||||
IO_MODE.DIGITAL_IN, -- F_SCRAM
|
IO_MODE.DIGITAL_IN, -- F_SCRAM
|
||||||
|
IO_MODE.DIGITAL_IN, -- F_ACK
|
||||||
IO_MODE.DIGITAL_IN, -- R_SCRAM
|
IO_MODE.DIGITAL_IN, -- R_SCRAM
|
||||||
|
IO_MODE.DIGITAL_IN, -- R_RESET
|
||||||
IO_MODE.DIGITAL_IN, -- R_ENABLE
|
IO_MODE.DIGITAL_IN, -- R_ENABLE
|
||||||
|
IO_MODE.DIGITAL_IN, -- U_ACK
|
||||||
IO_MODE.DIGITAL_OUT, -- F_ALARM
|
IO_MODE.DIGITAL_OUT, -- F_ALARM
|
||||||
IO_MODE.DIGITAL_OUT, -- WASTE_PU
|
IO_MODE.DIGITAL_OUT, -- WASTE_PU
|
||||||
IO_MODE.DIGITAL_OUT, -- WASTE_PO
|
IO_MODE.DIGITAL_OUT, -- WASTE_PO
|
||||||
IO_MODE.DIGITAL_OUT, -- WASTE_POPL
|
IO_MODE.DIGITAL_OUT, -- WASTE_POPL
|
||||||
IO_MODE.DIGITAL_OUT, -- WASTE_AM
|
IO_MODE.DIGITAL_OUT, -- WASTE_AM
|
||||||
IO_MODE.DIGITAL_OUT, -- R_ALARM
|
|
||||||
IO_MODE.DIGITAL_OUT, -- R_SCRAMMED
|
|
||||||
IO_MODE.DIGITAL_OUT, -- R_AUTO_SCRAM
|
|
||||||
IO_MODE.DIGITAL_OUT, -- R_ACTIVE
|
IO_MODE.DIGITAL_OUT, -- R_ACTIVE
|
||||||
IO_MODE.DIGITAL_OUT, -- R_AUTO_CTRL
|
IO_MODE.DIGITAL_OUT, -- R_AUTO_CTRL
|
||||||
|
IO_MODE.DIGITAL_OUT, -- R_SCRAMMED
|
||||||
|
IO_MODE.DIGITAL_OUT, -- R_AUTO_SCRAM
|
||||||
IO_MODE.DIGITAL_OUT, -- R_DMG_CRIT
|
IO_MODE.DIGITAL_OUT, -- R_DMG_CRIT
|
||||||
IO_MODE.DIGITAL_OUT, -- R_HIGH_TEMP
|
IO_MODE.DIGITAL_OUT, -- R_HIGH_TEMP
|
||||||
IO_MODE.DIGITAL_OUT, -- R_NO_COOLANT
|
IO_MODE.DIGITAL_OUT, -- R_NO_COOLANT
|
||||||
@ -199,6 +221,7 @@ function rsio.get_io_mode(port)
|
|||||||
IO_MODE.DIGITAL_OUT, -- R_INSUFF_FUEL
|
IO_MODE.DIGITAL_OUT, -- R_INSUFF_FUEL
|
||||||
IO_MODE.DIGITAL_OUT, -- R_PLC_FAULT
|
IO_MODE.DIGITAL_OUT, -- R_PLC_FAULT
|
||||||
IO_MODE.DIGITAL_OUT, -- R_PLC_TIMEOUT
|
IO_MODE.DIGITAL_OUT, -- R_PLC_TIMEOUT
|
||||||
|
IO_MODE.DIGITAL_OUT, -- U_ALARM
|
||||||
IO_MODE.DIGITAL_OUT -- U_EMER_COOL
|
IO_MODE.DIGITAL_OUT -- U_EMER_COOL
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,11 +272,7 @@ end
|
|||||||
---@param rs_value boolean
|
---@param rs_value boolean
|
||||||
---@return IO_LVL
|
---@return IO_LVL
|
||||||
function rsio.digital_read(rs_value)
|
function rsio.digital_read(rs_value)
|
||||||
if rs_value then
|
if rs_value then return IO_LVL.HIGH else return IO_LVL.LOW end
|
||||||
return IO_LVL.HIGH
|
|
||||||
else
|
|
||||||
return IO_LVL.LOW
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- get redstone boolean output value corresponding to a digital I/O level
|
-- get redstone boolean output value corresponding to a digital I/O level
|
||||||
@ -280,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.R_ENABLE) then
|
if (not util.is_int(port)) or (port > IO_PORT.U_ACK) 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
|
||||||
@ -310,7 +329,7 @@ end
|
|||||||
---@return number rs_value scaled redstone reading (0 to 15)
|
---@return number rs_value scaled redstone reading (0 to 15)
|
||||||
function rsio.analog_write(value, min, max)
|
function rsio.analog_write(value, min, max)
|
||||||
local scaled_value = (value - min) / (max - min)
|
local scaled_value = (value - min) / (max - min)
|
||||||
return scaled_value * 15
|
return math.floor(scaled_value * 15)
|
||||||
end
|
end
|
||||||
|
|
||||||
return rsio
|
return rsio
|
||||||
|
@ -6,11 +6,12 @@ local util = require("scada-common.util")
|
|||||||
local unit = require("supervisor.unit")
|
local unit = require("supervisor.unit")
|
||||||
|
|
||||||
local rsctl = require("supervisor.session.rsctl")
|
local rsctl = require("supervisor.session.rsctl")
|
||||||
local unit = require("supervisor.session.unit")
|
|
||||||
|
|
||||||
local PROCESS = types.PROCESS
|
local PROCESS = types.PROCESS
|
||||||
local PROCESS_NAMES = types.PROCESS_NAMES
|
local PROCESS_NAMES = types.PROCESS_NAMES
|
||||||
|
|
||||||
|
local IO = rsio.IO
|
||||||
|
|
||||||
-- 7.14 kJ per blade for 1 mB of fissile fuel<br/>
|
-- 7.14 kJ per blade for 1 mB of fissile fuel<br/>
|
||||||
-- 2856 FE per blade per 1 mB, 285.6 FE per blade per 0.1 mB (minimum)
|
-- 2856 FE per blade per 1 mB, 285.6 FE per blade per 0.1 mB (minimum)
|
||||||
local POWER_PER_BLADE = util.joules_to_fe(7140)
|
local POWER_PER_BLADE = util.joules_to_fe(7140)
|
||||||
@ -57,12 +58,15 @@ local facility = {}
|
|||||||
function facility.new(num_reactors, cooling_conf)
|
function facility.new(num_reactors, cooling_conf)
|
||||||
local self = {
|
local self = {
|
||||||
units = {},
|
units = {},
|
||||||
|
status_text = { "START UP", "initializing..." },
|
||||||
|
all_sys_ok = false,
|
||||||
|
-- rtus
|
||||||
|
rtu_conn_count = 0,
|
||||||
redstone = {},
|
redstone = {},
|
||||||
induction = {},
|
induction = {},
|
||||||
envd = {},
|
envd = {},
|
||||||
status_text = { "START UP", "initializing..." },
|
-- redstone I/O control
|
||||||
all_sys_ok = false,
|
io_ctl = nil, ---@type rs_controller
|
||||||
rtu_conn_count = 0,
|
|
||||||
-- process control
|
-- process control
|
||||||
units_ready = false,
|
units_ready = false,
|
||||||
mode = PROCESS.INACTIVE,
|
mode = PROCESS.INACTIVE,
|
||||||
@ -111,7 +115,7 @@ function facility.new(num_reactors, cooling_conf)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- init redstone RTU I/O controller
|
-- init redstone RTU I/O controller
|
||||||
local rs_rtu_io_ctl = rsctl.new(self.redstone)
|
self.io_ctl = rsctl.new(self.redstone)
|
||||||
|
|
||||||
-- unlink disconnected units
|
-- unlink disconnected units
|
||||||
---@param sessions table
|
---@param sessions table
|
||||||
@ -655,6 +659,36 @@ function facility.new(num_reactors, cooling_conf)
|
|||||||
-- update last mode and set next mode
|
-- update last mode and set next mode
|
||||||
self.last_mode = self.mode
|
self.last_mode = self.mode
|
||||||
self.mode = next_mode
|
self.mode = next_mode
|
||||||
|
|
||||||
|
-------------------------
|
||||||
|
-- Handle Redstone I/O --
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
if #self.redstone > 0 then
|
||||||
|
-- handle facility SCRAM
|
||||||
|
if self.io_ctl.digital_read(IO.F_SCRAM) then
|
||||||
|
for i = 1, #self.units do
|
||||||
|
local u = self.units[i] ---@type reactor_unit
|
||||||
|
u.cond_scram()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- handle facility ack
|
||||||
|
if self.io_ctl.digital_read(IO.F_ACK) then public.ack_all() end
|
||||||
|
|
||||||
|
-- update facility alarm output
|
||||||
|
local has_alarm = false
|
||||||
|
for i = 1, #self.units do
|
||||||
|
local u = self.units[i] ---@type reactor_unit
|
||||||
|
|
||||||
|
if u.has_critical_alarm() then
|
||||||
|
has_alarm = true
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
self.io_ctl.digital_write(IO.F_ALARM, has_alarm)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- call the update function of all units in the facility
|
-- call the update function of all units in the facility
|
||||||
|
@ -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.11.10"
|
local SUPERVISOR_VERSION = "beta-v0.11.11"
|
||||||
|
|
||||||
local print = util.print
|
local print = util.print
|
||||||
local println = util.println
|
local println = util.println
|
||||||
|
@ -74,10 +74,14 @@ function unit.new(for_reactor, num_boilers, num_turbines)
|
|||||||
num_turbines = num_turbines,
|
num_turbines = num_turbines,
|
||||||
types = { DT_KEYS = DT_KEYS, AISTATE = AISTATE },
|
types = { DT_KEYS = DT_KEYS, AISTATE = AISTATE },
|
||||||
defs = { FLOW_STABILITY_DELAY_MS = FLOW_STABILITY_DELAY_MS },
|
defs = { FLOW_STABILITY_DELAY_MS = FLOW_STABILITY_DELAY_MS },
|
||||||
|
-- rtus
|
||||||
redstone = {},
|
redstone = {},
|
||||||
boilers = {},
|
boilers = {},
|
||||||
turbines = {},
|
turbines = {},
|
||||||
envd = {},
|
envd = {},
|
||||||
|
-- redstone control
|
||||||
|
io_ctl = nil, ---@type rs_controller
|
||||||
|
valves = {}, ---@type unit_valves
|
||||||
-- auto control
|
-- auto control
|
||||||
ramp_target_br100 = 0,
|
ramp_target_br100 = 0,
|
||||||
-- state tracking
|
-- state tracking
|
||||||
@ -151,7 +155,7 @@ function unit.new(for_reactor, num_boilers, num_turbines)
|
|||||||
-- 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.TIMELY },
|
||||||
-- RPS trip occured
|
-- RPS trip occured
|
||||||
RPSTransient = { state = AISTATE.INACTIVE, trip_time = 0, hold_time = 1, id = ALARM.RPSTransient, tier = PRIO.URGENT },
|
RPSTransient = { state = AISTATE.INACTIVE, trip_time = 0, hold_time = 1, 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"
|
||||||
@ -223,7 +227,7 @@ function unit.new(for_reactor, num_boilers, num_turbines)
|
|||||||
}
|
}
|
||||||
|
|
||||||
-- init redstone RTU I/O controller
|
-- init redstone RTU I/O controller
|
||||||
local rs_rtu_io_ctl = rsctl.new(self.redstone)
|
self.io_ctl = rsctl.new(self.redstone)
|
||||||
|
|
||||||
-- init boiler table fields
|
-- init boiler table fields
|
||||||
for _ = 1, num_boilers do
|
for _ = 1, num_boilers do
|
||||||
@ -272,10 +276,8 @@ function unit.new(for_reactor, num_boilers, num_turbines)
|
|||||||
|
|
||||||
-- get the delta t of a value
|
-- get the delta t of a value
|
||||||
---@param key string value key
|
---@param key string value key
|
||||||
---@return number
|
---@return number value value or 0 if not known
|
||||||
function self._get_dt(key)
|
function self._get_dt(key) if self.deltas[key] then return self.deltas[key].dt else return 0.0 end end
|
||||||
if self.deltas[key] then return self.deltas[key].dt else return 0.0 end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- update all delta computations
|
-- update all delta computations
|
||||||
local function _dt__compute_all()
|
local function _dt__compute_all()
|
||||||
@ -320,8 +322,8 @@ function unit.new(for_reactor, num_boilers, num_turbines)
|
|||||||
|
|
||||||
--#region redstone I/O
|
--#region redstone I/O
|
||||||
|
|
||||||
local __rs_w = rs_rtu_io_ctl.digital_write
|
local __rs_w = self.io_ctl.digital_write
|
||||||
local __rs_r = rs_rtu_io_ctl.digital_read
|
local __rs_r = self.io_ctl.digital_read
|
||||||
|
|
||||||
-- valves
|
-- valves
|
||||||
local waste_pu = { open = function () __rs_w(IO.WASTE_PU, true) end, close = function () __rs_w(IO.WASTE_PU, false) end }
|
local waste_pu = { open = function () __rs_w(IO.WASTE_PU, true) end, close = function () __rs_w(IO.WASTE_PU, false) end }
|
||||||
@ -330,6 +332,15 @@ function unit.new(for_reactor, num_boilers, num_turbines)
|
|||||||
local waste_sps = { open = function () __rs_w(IO.WASTE_AM, true) end, close = function () __rs_w(IO.WASTE_AM, false) end }
|
local waste_sps = { open = function () __rs_w(IO.WASTE_AM, true) end, close = function () __rs_w(IO.WASTE_AM, false) end }
|
||||||
local emer_cool = { open = function () __rs_w(IO.U_EMER_COOL, true) end, close = function () __rs_w(IO.U_EMER_COOL, false) end }
|
local emer_cool = { open = function () __rs_w(IO.U_EMER_COOL, true) end, close = function () __rs_w(IO.U_EMER_COOL, false) end }
|
||||||
|
|
||||||
|
---@class unit_valves
|
||||||
|
self.valves = {
|
||||||
|
waste_pu = waste_pu,
|
||||||
|
waste_sna = waste_sna,
|
||||||
|
waste_po = waste_po,
|
||||||
|
waste_sps = waste_sps,
|
||||||
|
emer_cool = emer_cool
|
||||||
|
}
|
||||||
|
|
||||||
--#endregion
|
--#endregion
|
||||||
|
|
||||||
-- unlink disconnected units
|
-- unlink disconnected units
|
||||||
@ -480,13 +491,9 @@ function unit.new(for_reactor, num_boilers, num_turbines)
|
|||||||
-- update status text
|
-- update status text
|
||||||
logic.update_status_text(self)
|
logic.update_status_text(self)
|
||||||
|
|
||||||
-- check if emergency coolant is needed
|
-- handle redstone I/O
|
||||||
if self.plc_cache.rps_status.no_cool then
|
if #self.redstone > 0 then
|
||||||
emer_cool.open()
|
logic.handle_redstone(self)
|
||||||
elseif not self.plc_cache.rps_trip then
|
|
||||||
-- can't turn off on sufficient coolant level since it might drop again
|
|
||||||
-- turn off once system is OK again
|
|
||||||
emer_cool.close()
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -576,6 +583,13 @@ function unit.new(for_reactor, num_boilers, num_turbines)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- queue a SCRAM command only if a manual SCRAM has not already occured
|
||||||
|
function public.cond_scram()
|
||||||
|
if self.plc_s ~= nil and not self.plc_cache.rps_status.manual then
|
||||||
|
self.plc_s.in_queue.push_command(PLC_S_CMDS.SCRAM)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- acknowledge all alarms (if possible)
|
-- acknowledge all alarms (if possible)
|
||||||
function public.ack_all()
|
function public.ack_all()
|
||||||
for i = 1, #self.db.alarm_states do
|
for i = 1, #self.db.alarm_states do
|
||||||
|
@ -3,6 +3,8 @@ local rsio = require("scada-common.rsio")
|
|||||||
local types = require("scada-common.types")
|
local types = require("scada-common.types")
|
||||||
local util = require("scada-common.util")
|
local util = require("scada-common.util")
|
||||||
|
|
||||||
|
local plc = require("supervisor.session.plc")
|
||||||
|
|
||||||
local ALARM_STATE = types.ALARM_STATE
|
local ALARM_STATE = types.ALARM_STATE
|
||||||
|
|
||||||
local TRI_FAIL = types.TRI_FAIL
|
local TRI_FAIL = types.TRI_FAIL
|
||||||
@ -10,6 +12,8 @@ local DUMPING_MODE = types.DUMPING_MODE
|
|||||||
|
|
||||||
local IO = rsio.IO
|
local IO = rsio.IO
|
||||||
|
|
||||||
|
local PLC_S_CMDS = plc.PLC_S_CMDS
|
||||||
|
|
||||||
local aistate_string = {
|
local aistate_string = {
|
||||||
"INACTIVE",
|
"INACTIVE",
|
||||||
"TRIPPING",
|
"TRIPPING",
|
||||||
@ -620,4 +624,71 @@ function logic.update_status_text(self)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- handle unit redstone I/O
|
||||||
|
---@param self _unit_self unit instance
|
||||||
|
function logic.handle_redstone(self)
|
||||||
|
-- reactor controls
|
||||||
|
if self.plc_s ~= nil then
|
||||||
|
if (not self.plc_cache.rps_status.manual) and self.io_ctl.digital_read(IO.R_SCRAM) then
|
||||||
|
-- reactor SCRAM requested but not yet done; perform it
|
||||||
|
self.plc_s.in_queue.push_command(PLC_S_CMDS.SCRAM)
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.plc_cache.rps_trip and self.io_ctl.digital_read(IO.R_RESET) then
|
||||||
|
-- reactor RPS reset requested but not yet done; perform it
|
||||||
|
self.plc_s.in_queue.push_command(PLC_S_CMDS.RPS_RESET)
|
||||||
|
end
|
||||||
|
|
||||||
|
if (not self.db.annunciator.AutoControl) and (not self.plc_cache.active) and
|
||||||
|
(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
|
||||||
|
self.plc_s.in_queue.push_command(PLC_S_CMDS.ENABLE)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- check for request to ack all alarms
|
||||||
|
if self.io_ctl.digital_read(IO.U_ACK) then
|
||||||
|
for i = 1, #self.db.alarm_states do
|
||||||
|
if self.db.alarm_states[i] == ALARM_STATE.TRIPPED then
|
||||||
|
self.db.alarm_states[i] = ALARM_STATE.ACKED
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- write reactor status outputs
|
||||||
|
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_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_DMG_CRIT, self.plc_cache.rps_status.dmg_crit)
|
||||||
|
self.io_ctl.digital_write(IO.R_HIGH_TEMP, self.plc_cache.rps_status.high_temp)
|
||||||
|
self.io_ctl.digital_write(IO.R_NO_COOLANT, self.plc_cache.rps_status.no_cool)
|
||||||
|
self.io_ctl.digital_write(IO.R_EXCESS_HC, self.plc_cache.rps_status.ex_hcool)
|
||||||
|
self.io_ctl.digital_write(IO.R_EXCESS_WS, self.plc_cache.rps_status.ex_waste)
|
||||||
|
self.io_ctl.digital_write(IO.R_INSUFF_FUEL, self.plc_cache.rps_status.no_fuel)
|
||||||
|
self.io_ctl.digital_write(IO.R_PLC_FAULT, self.plc_cache.rps_status.fault)
|
||||||
|
self.io_ctl.digital_write(IO.R_PLC_TIMEOUT, self.plc_cache.rps_status.timeout)
|
||||||
|
|
||||||
|
-- write unit outputs
|
||||||
|
|
||||||
|
local has_alarm = false
|
||||||
|
for i = 1, #self.db.alarm_states do
|
||||||
|
if self.db.alarm_states[i] == ALARM_STATE.TRIPPED then
|
||||||
|
has_alarm = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
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
|
||||||
|
self.valves.emer_cool.open()
|
||||||
|
elseif not self.plc_cache.rps_trip then
|
||||||
|
-- can't turn off on sufficient coolant level since it might drop again
|
||||||
|
-- turn off once system is OK again
|
||||||
|
self.valves.emer_cool.close()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return logic
|
return logic
|
||||||
|
Loading…
Reference in New Issue
Block a user