THRESH_HOLD_IDLE/HOLD_HEAT/IDLE_HEAT/IDLE_HOLD/HEAT_HOLD/HEAT_IDLE in tc_constants.py were hardcoded module-level constants shared by every controller instance, so tuning the IDLE/HOLD/HEAT hysteresis required a code change. Replace them with DEFAULT_THRESHOLDS plus an optional TempCtrl.Thresholds config section, merged at construction time in TempControllerBase.__init__ so configs that omit the section keep behaving exactly as before. Documented the new section in config.json.templ; left config.json.sim without it to exercise the default-fallback path. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2.4 KiB
components/pid design backlog
Findings from a design review, not yet acted on. See git history on
claude_refactor for items already fixed (Smith predictor's delay
correction enabled, the two TempController classes deduplicated into
temp_controller_base.py).
-
FSM thresholds aren't configurable. Moved into an optional
TempCtrl.Thresholdsconfig section (HoldIdle,HoldHeat,IdleHeat,IdleHold,HeatHold,HeatIdle), merged overDEFAULT_THRESHOLDSintc_constants.pyso existing configs without the section keep working unchanged. -
Pid.scale()is a gain-scheduling hack, not anti-windup.pid.py'sscale(k)multiplies every gain by1/heatrate_soll_set(called fromtemp_controller*.py'sprocess()), but it's framed as overshoot compensation, conflated with the real anti-windup logic a few lines below.self.kalso never resets inreset(), so a stale scale factor can survive a state-transition reset. Consider moving this scheduling logic out of the genericPidclass and into the temp controller, and resettingkinreset(). -
Three Kalman filters share one tuning. In
temp_controller_smith.py,kalman_model,kalman_model_delay, andkalman_plantare all constructed with the sameparams['Kalman']despite tracking signals with different noise characteristics. Allow independentvar_P/var_Q/var_Rper filter in config. -
matplotlib imported at module level in production code.
temp_controller.py,temp_controller_smith.py, andkalman.pyallfrom matplotlib.pyplot import ...just to support their__main__self-test plots, which couples the live server's import graph (and its dependency list) to a GUI plotting library it never uses at runtime. Move the plotting demos into separate scripts. -
No automated tests. The
__main__blocks (andkalman_eval.py) are manual, eyeballed-plot harnesses. Add regression tests for FSM transitions, anti-windup clamping, and Kalman convergence — this code drives a physical heater. -
Config access is unchecked
dict[key]everywhere.params['Kalman'],model_params['gain'], etc., throughout, with no schema validation at load time. We already hit this bug class once (config.json.sim'sgain/Modelnesting mismatch). A small schema/dataclass validation layer at config-load would surface errors immediately instead of mid-__init__.