Keep the plant/controller model in sync as the Sud advances
SudTask.on_step_changed() set the controller's target temp/rate on every step, but never touched the real Pot's or the Smith predictor's internal model's thermal mass (M/C) - those stayed frozen at brewpi.py's startup DEFAULT_PLANT_PARAMS for the whole brew, even though grain_mass/water_mass change per step (malt going in, water boiling off) and demo_sud.py already recomputes them every step via derive_plant_params(). Production SudTask just never got the same treatment. Adds SudTask.apply_plant_params(), called alongside the existing theta_soll/heatrate_soll push, mirroring the demo. Needs the real Pot now, so SudTask takes a `pot` constructor arg; set_model_params() is only called if the configured controller actually defines one (the "Normal" pid_type doesn't).
This commit is contained in:
+1
-1
@@ -74,7 +74,7 @@ if __name__ == '__main__':
|
|||||||
sud_path = config.get('sud')
|
sud_path = config.get('sud')
|
||||||
if sud_path:
|
if sud_path:
|
||||||
sud = Sud(sud_path)
|
sud = Sud(sud_path)
|
||||||
taskmgr.add(SudTask(sud, tc, stirrer, DT_TASK, dispatcher.msgio_get("Sud")))
|
taskmgr.add(SudTask(sud, tc, stirrer, pot, DT_TASK, dispatcher.msgio_get("Sud")))
|
||||||
|
|
||||||
# Tracer
|
# Tracer
|
||||||
taskmgr.add(TracerTask(sensor, heater, tc, trace_tc, DT_TASK_TRACER, dispatcher.msgio_get("Tracer")))
|
taskmgr.add(TracerTask(sensor, heater, tc, trace_tc, DT_TASK_TRACER, dispatcher.msgio_get("Tracer")))
|
||||||
|
|||||||
+14
-1
@@ -3,6 +3,7 @@ from tasks import ATask
|
|||||||
from ws.message import MsgIo
|
from ws.message import MsgIo
|
||||||
from utils.value import ChangedFloat
|
from utils.value import ChangedFloat
|
||||||
from components import APid, AStirrer
|
from components import APid, AStirrer
|
||||||
|
from components.plant import APlant
|
||||||
from components.sud import Sud, SudState
|
from components.sud import Sud, SudState
|
||||||
|
|
||||||
# How close theta_ist needs to be to theta_soll_set to count as "reached".
|
# How close theta_ist needs to be to theta_soll_set to count as "reached".
|
||||||
@@ -10,14 +11,25 @@ TEMP_REACHED_TOLERANCE = 0.2
|
|||||||
|
|
||||||
|
|
||||||
class SudTask(ATask):
|
class SudTask(ATask):
|
||||||
def __init__(self, sud: Sud, tc: APid, stirrer: AStirrer, interval, msg_handler: MsgIo):
|
def __init__(self, sud: Sud, tc: APid, stirrer: AStirrer, pot: APlant, interval, msg_handler: MsgIo):
|
||||||
ATask.__init__(self, interval)
|
ATask.__init__(self, interval)
|
||||||
self.sud = sud
|
self.sud = sud
|
||||||
self.tc = tc
|
self.tc = tc
|
||||||
self.stirrer = stirrer
|
self.stirrer = stirrer
|
||||||
|
self.pot = pot
|
||||||
self.msg_handler = msg_handler
|
self.msg_handler = msg_handler
|
||||||
msg_handler.set_recv_handler(self.recv)
|
msg_handler.set_recv_handler(self.recv)
|
||||||
|
|
||||||
|
def apply_plant_params(self, step):
|
||||||
|
"""Keeps the real plant's and the controller's internal model's
|
||||||
|
lumped (M, C) in sync with the step's grain_mass/water_mass, since
|
||||||
|
those vary over the course of a brew (malt going in, water boiling
|
||||||
|
off) - mirrors demo_sud.py's apply_plant_params()."""
|
||||||
|
params = self.sud.derive_plant_params(step.get('grain_mass', 0), step.get('water_mass', 0))
|
||||||
|
self.pot.set_thermal_params(params['M'], params['C'])
|
||||||
|
if hasattr(self.tc, 'set_model_params'):
|
||||||
|
self.tc.set_model_params(params['M'], params['C'])
|
||||||
|
|
||||||
def apply_stirrer(self, step):
|
def apply_stirrer(self, step):
|
||||||
stirrer_cfg = step.get('ramp', step.get('hold', {})).get('stirrer', {})
|
stirrer_cfg = step.get('ramp', step.get('hold', {})).get('stirrer', {})
|
||||||
speed = stirrer_cfg.get('speed', 0)
|
speed = stirrer_cfg.get('speed', 0)
|
||||||
@@ -35,6 +47,7 @@ class SudTask(ATask):
|
|||||||
ramp = step.get('ramp') if step else None
|
ramp = step.get('ramp') if step else None
|
||||||
hold = step.get('hold') if step else None
|
hold = step.get('hold') if step else None
|
||||||
if step is not None:
|
if step is not None:
|
||||||
|
self.apply_plant_params(step)
|
||||||
if ramp is not None:
|
if ramp is not None:
|
||||||
self.tc.set_theta_soll(ramp['temp'])
|
self.tc.set_theta_soll(ramp['temp'])
|
||||||
self.tc.set_heatrate_soll(ramp['rate'])
|
self.tc.set_heatrate_soll(ramp['rate'])
|
||||||
|
|||||||
Reference in New Issue
Block a user