From 10aa34a8e801dc0949725ee0eae8f24e56c9cbc9 Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Fri, 29 Apr 2022 22:27:54 -0400 Subject: [PATCH] #17 PLC ramp burn rate to setpoint --- reactor-plc/plc.lua | 20 ++++----- reactor-plc/startup.lua | 11 ++++- reactor-plc/threads.lua | 99 ++++++++++++++++++++++++++++++++++++++--- 3 files changed, 111 insertions(+), 19 deletions(-) diff --git a/reactor-plc/plc.lua b/reactor-plc/plc.lua index c1ffbf0..a8c7c5e 100644 --- a/reactor-plc/plc.lua +++ b/reactor-plc/plc.lua @@ -357,12 +357,12 @@ function comms_init(id, modem, local_port, server_port, reactor, iss) end local sys_status = { - util.time(), - (not self.scrammed), - iss.is_tripped(), - degraded, - self.reactor.getHeatingRate(), - mek_data + util.time(), -- timestamp + (not self.scrammed), -- enabled + iss.is_tripped(), -- overridden + degraded, -- degraded + self.reactor.getHeatingRate(), -- heating rate + mek_data -- mekanism status data } _send(RPLC_TYPES.STATUS, sys_status) @@ -411,7 +411,7 @@ function comms_init(id, modem, local_port, server_port, reactor, iss) end -- handle an RPLC packet - local handle_packet = function (packet, plc_state, conn_watchdog) + local handle_packet = function (packet, plc_state, setpoints, conn_watchdog) if packet ~= nil then -- check sequence number if self.r_seq_num == nil then @@ -499,11 +499,11 @@ function comms_init(id, modem, local_port, server_port, reactor, iss) self.max_burn_rate = max_burn_rate end - -- if we know our max burn rate, update current burn rate if in range + -- if we know our max burn rate, update current burn rate setpoint if in range if max_burn_rate ~= ppm.ACCESS_FAULT then if burn_rate > 0 and burn_rate <= max_burn_rate then - self.reactor.setBurnRate(burn_rate) - success = self.reactor.__p_is_ok() + setpoints.burn_rate = burn_rate + success = true end end diff --git a/reactor-plc/startup.lua b/reactor-plc/startup.lua index 69038d3..2328a00 100644 --- a/reactor-plc/startup.lua +++ b/reactor-plc/startup.lua @@ -12,7 +12,7 @@ os.loadAPI("config.lua") os.loadAPI("plc.lua") os.loadAPI("threads.lua") -local R_PLC_VERSION = "alpha-v0.4.11" +local R_PLC_VERSION = "alpha-v0.4.12" local print = util.print local println = util.println @@ -43,6 +43,10 @@ local __shared_memory = { no_reactor = false, no_modem = false }, + + setpoints = { + burn_rate = 0.0 + }, -- core PLC devices plc_dev = { @@ -135,8 +139,11 @@ if __shared_memory.networked then local comms_thread_tx = threads.thread__comms_tx(__shared_memory) local comms_thread_rx = threads.thread__comms_rx(__shared_memory) + -- setpoint control only needed when networked + local sp_ctrl_thread = threads.thread__setpoint_control(__shared_memory) + -- run threads - parallel.waitForAll(main_thread.exec, iss_thread.exec, comms_thread_tx.exec, comms_thread_rx.exec) + parallel.waitForAll(main_thread.exec, iss_thread.exec, comms_thread_tx.exec, comms_thread_rx.exec, sp_ctrl_thread.exec) else -- run threads, excluding comms parallel.waitForAll(main_thread.exec, iss_thread.exec) diff --git a/reactor-plc/threads.lua b/reactor-plc/threads.lua index 93a243e..6a55e7f 100644 --- a/reactor-plc/threads.lua +++ b/reactor-plc/threads.lua @@ -10,9 +10,12 @@ local println_ts = util.println_ts local psleep = util.psleep -local MAIN_CLOCK = 1 -- (1Hz, 20 ticks) -local ISS_SLEEP = 500 -- (500ms, 10 ticks) -local COMMS_SLEEP = 150 -- (150ms, 3 ticks) +local MAIN_CLOCK = 1 -- (1Hz, 20 ticks) +local ISS_SLEEP = 500 -- (500ms, 10 ticks) +local COMMS_SLEEP = 150 -- (150ms, 3 ticks) +local SP_CTRL_SLEEP = 250 -- (250ms, 5 ticks) + +local BURN_RATE_RAMP_mB_s = 5.0 local MQ__ISS_CMD = { SCRAM = 1, @@ -196,7 +199,7 @@ function thread__iss(smem) -- thread loop while true do - local reactor = smem.plc_dev.reactor + local reactor = plc_dev.reactor -- ISS checks if plc_state.init_ok then @@ -292,7 +295,7 @@ function thread__iss(smem) return { exec = exec } end --- communications handler thread +-- communications sender thread function thread__comms_tx(smem) -- execute thread local exec = function () @@ -343,6 +346,7 @@ function thread__comms_tx(smem) return { exec = exec } end +-- communications handler thread function thread__comms_rx(smem) -- execute thread local exec = function () @@ -350,6 +354,7 @@ function thread__comms_rx(smem) -- load in from shared memory local plc_state = smem.plc_state + local setpoints = smem.setpoints local plc_comms = smem.plc_sys.plc_comms local conn_watchdog = smem.plc_sys.conn_watchdog @@ -369,8 +374,10 @@ function thread__comms_rx(smem) -- received data elseif msg.qtype == mqueue.TYPE.PACKET then -- received a packet - -- handle the packet (plc_state passed to allow clearing SCRAM flag) - plc_comms.handle_packet(msg.message, plc_state, conn_watchdog) + -- handle the packet (setpoints passed to update burn rate setpoint) + -- (plc_state passed to allow clearing SCRAM flag and check if degraded) + -- (conn_watchdog passed to allow feeding the watchdog) + plc_comms.handle_packet(msg.message, setpoints, plc_state, conn_watchdog) end -- quick yield @@ -390,3 +397,81 @@ function thread__comms_rx(smem) return { exec = exec } end + +-- apply setpoints +function thread__setpoint_control(smem) + -- execute thread + local exec = function () + log._debug("comms rx thread start") + + -- load in from shared memory + local plc_state = smem.plc_state + local setpoints = smem.setpoints + local plc_dev = smem.plc_dev + + local last_update = util.time() + local running = false + + local last_sp_burn = 0 + + -- thread loop + while true do + local reactor = plc_dev.reactor + + -- check if we should start ramping + if setpoints.burn_rate ~= last_sp_burn then + last_sp_burn = setpoints.burn_rate + running = true + end + + -- only check I/O if active to save on processing time + if running then + -- do not use the actual elapsed time, it could spike + -- we do not want to have big jumps as that is what we are trying to avoid in the first place + local min_elapsed_s = SETPOINT_CTRL_SLEEP / 1000.0 + + -- clear so we can later evaluate if we should keep running + running = false + + -- adjust burn rate (setpoints.burn_rate) + if not plc_state.scram then + local current_burn_rate = reactor.getBurnRate() + if (current_burn_rate ~= ppm.ACCESS_FAULT) and (current_burn_rate ~= setpoints.burn_rate) then + -- calculate new burn rate + local new_burn_rate = current_burn_rate + + if setpoints.burn_rate > current_burn_rate then + -- need to ramp up + local new_burn_rate = current_burn_rate + (BURN_RATE_RAMP_mB_s * min_elapsed_s) + if new_burn_rate > setpoints.burn_rate then + new_burn_rate = setpoints.burn_rate + end + else + -- need to ramp down + local new_burn_rate = current_burn_rate - (BURN_RATE_RAMP_mB_s * min_elapsed_s) + if new_burn_rate < setpoints.burn_rate then + new_burn_rate = setpoints.burn_rate + end + end + + -- set the burn rate + reactor.setBurnRate(new_burn_rate) + + running = running or (new_burn_rate ~= setpoints.burn_rate) + end + end + end + + -- check for termination request + if plc_state.shutdown then + log._info("setpoint control thread exiting") + break + end + + -- delay before next check + last_update = util.adaptive_delay(SETPOINT_CTRL_SLEEP, last_update) + end + end + + return { exec = exec } +end