mirror of
https://github.com/MikaylaFischler/cc-mek-scada.git
synced 2024-08-30 18:22:34 +00:00
#366 idling and charge level PD gain changes
This commit is contained in:
parent
4fcd375ee2
commit
65d43d55c7
@ -50,9 +50,9 @@ local START_STATUS = {
|
||||
BLADE_MISMATCH = 2
|
||||
}
|
||||
|
||||
local charge_Kp = 0.275
|
||||
local charge_Kp = 0.15
|
||||
local charge_Ki = 0.0
|
||||
local charge_Kd = 4.5
|
||||
local charge_Kd = 0.6
|
||||
|
||||
local rate_Kp = 2.45
|
||||
local rate_Ki = 0.4825
|
||||
@ -225,6 +225,14 @@ function facility.new(num_reactors, cooling_conf)
|
||||
return unallocated, false
|
||||
end
|
||||
|
||||
-- set idle state of all assigned reactors
|
||||
---@param idle boolean idle state
|
||||
local function _set_idling(idle)
|
||||
for i = 1, #self.prio_defs do
|
||||
for _, u in pairs(self.prio_defs[i]) do u.auto_set_idle(idle) end
|
||||
end
|
||||
end
|
||||
|
||||
-- PUBLIC FUNCTIONS --
|
||||
|
||||
---@class facility
|
||||
@ -325,8 +333,9 @@ function facility.new(num_reactors, cooling_conf)
|
||||
|
||||
--#region
|
||||
|
||||
local avg_charge = self.avg_charge.compute()
|
||||
local avg_inflow = self.avg_inflow.compute()
|
||||
local avg_charge = self.avg_charge.compute()
|
||||
local avg_inflow = self.avg_inflow.compute()
|
||||
local avg_outflow = self.avg_outflow.compute()
|
||||
|
||||
local now = util.time_s()
|
||||
|
||||
@ -390,6 +399,7 @@ function facility.new(num_reactors, cooling_conf)
|
||||
-- disable reactors and disengage auto control
|
||||
for _, u in pairs(self.prio_defs[i]) do
|
||||
u.disable()
|
||||
u.auto_set_idle(false)
|
||||
u.auto_disengage()
|
||||
end
|
||||
end
|
||||
@ -460,6 +470,9 @@ function facility.new(num_reactors, cooling_conf)
|
||||
self.last_error = 0
|
||||
self.accumulator = 0
|
||||
|
||||
-- enabling idling on all assigned units
|
||||
_set_idling(true)
|
||||
|
||||
self.status_text = { "CHARGE MODE", "running control loop" }
|
||||
log.info("FAC: CHARGE mode starting PID control")
|
||||
elseif self.last_update ~= charge_update then
|
||||
@ -475,9 +488,9 @@ function facility.new(num_reactors, cooling_conf)
|
||||
local integral = self.accumulator
|
||||
local derivative = (error - self.last_error) / (now - self.last_time)
|
||||
|
||||
local P = (charge_Kp * error)
|
||||
local I = (charge_Ki * integral)
|
||||
local D = (charge_Kd * derivative)
|
||||
local P = charge_Kp * error
|
||||
local I = charge_Ki * integral
|
||||
local D = charge_Kd * derivative
|
||||
|
||||
local output = P + I + D
|
||||
|
||||
@ -486,7 +499,10 @@ function facility.new(num_reactors, cooling_conf)
|
||||
|
||||
self.saturated = output ~= out_c
|
||||
|
||||
-- log.debug(util.sprintf("CHARGE[%f] { CHRG[%f] ERR[%f] INT[%f] => OUT[%f] OUT_C[%f] <= P[%f] I[%f] D[%d] }",
|
||||
-- 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 < avg_inflow)))
|
||||
|
||||
-- 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))
|
||||
|
||||
_allocate_burn_rate(out_c, true)
|
||||
@ -544,9 +560,9 @@ function facility.new(num_reactors, cooling_conf)
|
||||
local integral = self.accumulator
|
||||
local derivative = (error - self.last_error) / (now - self.last_time)
|
||||
|
||||
local P = (rate_Kp * error)
|
||||
local I = (rate_Ki * integral)
|
||||
local D = (rate_Kd * derivative)
|
||||
local P = rate_Kp * error
|
||||
local I = rate_Ki * integral
|
||||
local D = rate_Kd * derivative
|
||||
|
||||
-- velocity (rate) (derivative of charge level => rate) feed forward
|
||||
local FF = self.gen_rate_setpoint / self.charge_conversion
|
||||
|
@ -21,7 +21,7 @@ local supervisor = require("supervisor.supervisor")
|
||||
|
||||
local svsessions = require("supervisor.session.svsessions")
|
||||
|
||||
local SUPERVISOR_VERSION = "v1.3.5"
|
||||
local SUPERVISOR_VERSION = "v1.3.6"
|
||||
|
||||
local println = util.println
|
||||
local println_ts = util.println_ts
|
||||
|
@ -8,9 +8,6 @@ local logic = require("supervisor.unitlogic")
|
||||
local plc = require("supervisor.session.plc")
|
||||
local rsctl = require("supervisor.session.rsctl")
|
||||
|
||||
---@class reactor_control_unit
|
||||
local unit = {}
|
||||
|
||||
local WASTE_MODE = types.WASTE_MODE
|
||||
local WASTE = types.WASTE_PRODUCT
|
||||
local ALARM = types.ALARM
|
||||
@ -55,6 +52,14 @@ local AISTATE = {
|
||||
---@field id ALARM alarm ID
|
||||
---@field tier integer alarm urgency tier (0 = highest)
|
||||
|
||||
-- burn rate to idle at
|
||||
local IDLE_RATE = 0.01
|
||||
-- time (ms) to idle
|
||||
local IDLE_TIME = 15000
|
||||
|
||||
---@class reactor_control_unit
|
||||
local unit = {}
|
||||
|
||||
-- create a new reactor unit
|
||||
---@nodiscard
|
||||
---@param reactor_id integer reactor unit number
|
||||
@ -83,6 +88,9 @@ function unit.new(reactor_id, num_boilers, num_turbines)
|
||||
emcool_opened = false,
|
||||
-- auto control
|
||||
auto_engaged = false,
|
||||
auto_idle = false,
|
||||
auto_idling = false,
|
||||
auto_idle_start = 0,
|
||||
auto_was_alarmed = false,
|
||||
ramp_target_br100 = 0,
|
||||
-- state tracking
|
||||
@ -578,6 +586,23 @@ function unit.new(reactor_id, num_boilers, num_turbines)
|
||||
end
|
||||
end
|
||||
|
||||
-- set automatic control idling mode to change behavior when given a burn rate command of zero<br>
|
||||
-- - enabling will hold the reactor at 0.01 mB/t for a period before disabling when commanded zero
|
||||
-- - disabling will stop the reactor when commanded zero
|
||||
---@param idle boolean true to enable, false to disable and stop right away
|
||||
function public.auto_set_idle(idle)
|
||||
if not (idle and self.auto_idle) then
|
||||
self.auto_idling = false
|
||||
self.auto_idle_start = 0
|
||||
end
|
||||
|
||||
if idle ~= self.auto_idle then
|
||||
log.debug(util.c("UNIT ", self.r_id, ": idling mode changed to ", idle))
|
||||
end
|
||||
|
||||
self.auto_idle = idle
|
||||
end
|
||||
|
||||
-- get the actual limit of this unit<br>
|
||||
-- if it is degraded or not ready, the limit will be 0
|
||||
---@nodiscard
|
||||
@ -597,7 +622,35 @@ function unit.new(reactor_id, num_boilers, num_turbines)
|
||||
if self.auto_engaged then
|
||||
if self.plc_i ~= nil then
|
||||
log.debug(util.c("UNIT ", self.r_id, ": commit br100 of ", self.db.control.br100, " with ramp set to ", ramp))
|
||||
self.plc_i.auto_set_burn(self.db.control.br100 / 100, ramp)
|
||||
|
||||
local rate = self.db.control.br100 / 100
|
||||
|
||||
if self.auto_idle then
|
||||
if rate <= IDLE_RATE then
|
||||
if self.auto_idle_start == 0 then
|
||||
self.auto_idling = true
|
||||
self.auto_idle_start = util.time_ms()
|
||||
log.info(util.c("UNIT ", self.r_id, ": started idling at ", IDLE_RATE, " mB/t"))
|
||||
|
||||
rate = IDLE_RATE
|
||||
elseif (util.time_ms() - self.auto_idle_start) > IDLE_TIME then
|
||||
if self.auto_idling then
|
||||
self.auto_idling = false
|
||||
log.info(util.c("UNIT ", self.r_id, ": completed idling period"))
|
||||
end
|
||||
else
|
||||
log.debug(util.c("UNIT ", self.r_id, ": continuing idle at ", IDLE_RATE, " mB/t"))
|
||||
|
||||
rate = IDLE_RATE
|
||||
end
|
||||
else
|
||||
self.auto_idling = false
|
||||
self.auto_idle_start = 0
|
||||
end
|
||||
end
|
||||
|
||||
self.plc_i.auto_set_burn(rate, ramp)
|
||||
|
||||
if ramp then self.ramp_target_br100 = self.db.control.br100 end
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user