[Sensor] - replace TempSensorSim's hardcoded k_noise with configurable
temp_offset/variance, accept **kwargs on Max31865 too so both sensors
share a constructor signature usable from TempSensorFactory.create()
[Temp Controller] - low-pass filter the backward-difference heat-rate
estimate (alpha=0.1) in both temp_controller.py and
temp_controller_smith.py instead of using the raw, noisy derivative
[Pot] - drop kn from demo_pot.py's params, matching the unused-field
removal already made to pot.py itself
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
[brewpi] - drop trace vars for the dtheta_ist_* attributes removed
when temp_controller_smith.py dropped Kalman filtering
[Pot] - drop unused kn field (never read since the noise-injection
code that used it was dropped)
[GUI] - default WS connection to ws://localhost:8765
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
temp_controller_smith.py still relied on Kalman filtering and Pot's old
get_temperature_intermediate(), both removed by the recent Pot/Kalman
simplification. Rebuild it using two Pot model copies (zero-delay and
delayed) and the same backward-difference heat rate as temp_controller.py,
combined into the classic Smith correction:
theta_ist = theta_model_fast + (theta_plant - theta_model_delay).
Also fix set_model_power() never being called, so the internal model
actually receives the controller's power output, and fill in
demo_temp_controller_smith.py to exercise it end-to-end with an extra
plot of plant vs. fast-model vs. delayed-model temperature.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
temp_controller.py, temp_controller_smith.py, and kalman.py imported
matplotlib at module level just to support eyeballed-plot __main__
blocks, coupling the live server's import graph to a GUI plotting lib
it never uses at runtime. Relocate those demos (and kalman_eval.py) to
scripts/demos/pid/ and strip the now-unused imports/__main__ blocks
from the production files.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Review of pot.py found a likely root cause for sim-vs-real control
mismatches: the heat-loss term carries the wrong units, masking
ambient cooling in simulation. Also notes the dropped sensor-noise
term, hardcoded ambient temp, and lag-vs-dead-time modeling gap.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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>
Tracks open issues from a review that weren't fixed as part of this
branch's Smith-predictor and dedup work: non-configurable FSM
thresholds, Pid.scale()'s gain-scheduling hack, shared Kalman tuning
across the Smith controller's 3 filters, matplotlib imported at
module level in production code, no automated tests, and unchecked
config access.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
TempControllerBase no longer threads model_params through (only the
Smith subclass needs it, for its own Pot model and Kalman filters).
Enable the Smith predictor's actual delay-compensated error term
(theta_err now uses theta_ist_plant - theta_ist_model_delay +
theta_ist_model instead of the plain plant reading), which is the
correction this controller is named for.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Both controllers had nearly identical process_fsm(), process_pid(),
and all getters/setters; only Kalman/model setup and process()
genuinely differed, and the duplication had already drifted (the
Smith variant resets model state on entering HEAT, the plain one
didn't).
Add TempControllerBase with the shared logic and three small hooks
(init_kalman, on_state_entered, post_pid) subclasses use to plug in
their own Kalman/model behavior. Each subclass now contains only what
makes it different.
Also fixes a latent crash: TempController's constructor only accepted
(dt, params), but PidFactory/brewpi.py always call it with a third
model_params arg, so pid_type "Normal" would have raised TypeError.
The shared base's model_params=None default fixes this. Also
initializes the Smith controller's trace attributes in __init__
instead of leaving them undefined until the first process() call.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>