From 1034765e319067a38dbe27641d7d43a38f5e4a03 Mon Sep 17 00:00:00 2001 From: Jens Ahrensfeld Date: Sun, 21 Jun 2026 16:38:59 +0200 Subject: [PATCH] Fix HOLD<->COOL chattering caused by too-tight HoldCool threshold HoldCool=0.1 was inherited from the pre-COOL-state era, where it meant "eagerly give up active holding and coast" - harmless, since coasting had no side effects. COOL is a real, actively-controlled state now (its own pid_cool, reset on every entry), so a threshold this tight relative to a real heater's discrete power steps (or even just sensor noise) caused the system to flip in and out of COOL nearly every tick once resting near a setpoint - resetting both pid_hold's and pid_cool's integrators each time and never letting either actually converge. Confirmed via a full multi-task simulation (real Pot/Sensor/Heater/ TempCtrl tasks, not a simplified loop) of sude/sud_0010.json: 44+ TempCtrl state changes and the run not settling within hours at HoldCool=0.1, dropping to 8 state changes and a clean 186.5 min finish at HoldCool=1.0 (matching the other thresholds). This was the dominant cause of real brews taking far longer than their nominal schedule duration - not just a forecasting inaccuracy, an actual control- quality bug. --- components/pid/temp_controller_base.py | 9 ++++++++- config.json.templ | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/components/pid/temp_controller_base.py b/components/pid/temp_controller_base.py index 0be2f7f..24daade 100644 --- a/components/pid/temp_controller_base.py +++ b/components/pid/temp_controller_base.py @@ -4,7 +4,14 @@ import enum DEFAULT_THRESHOLDS = { "HoldHeat": 1.0, - "HoldCool": 0.1, + # HoldCool used to be 0.1 ("eagerly give up and coast" made sense back + # when COOL meant nothing more than going idle - it's an active state + # with its own PID now, so a threshold this tight relative to a real + # heater's discrete power steps/sensor noise causes the system to + # chatter in and out of it every tick, resetting both pid_hold's and + # pid_cool's integrators each time and never letting either actually + # converge. Symmetric with the others instead. + "HoldCool": 1.0, "HeatHold": 1.0, "HeatCool": 1.0, "CoolHold": 1.0, diff --git a/config.json.templ b/config.json.templ index 15430d1..8167304 100644 --- a/config.json.templ +++ b/config.json.templ @@ -30,7 +30,7 @@ }, "Thresholds": { "HoldHeat": 1.0, - "HoldCool": 0.1, + "HoldCool": 1.0, "HeatHold": 1.0, "HeatCool": 1.0, "CoolHold": 1.0,