Skip to content

fix(pb_heater): approach cap stalled the chamber below setpoint since v1.1.16 - #103

Merged
plastikman merged 3 commits into
mainfrom
fix/pid-approach-cap-hold
Sep 20, 2026
Merged

plastikman merged 3 commits into
mainfrom
fix/pid-approach-cap-hold

Conversation

@plastikman

Copy link
Copy Markdown
Owner

Problem

Since v1.1.16 the chamber controller can't hold setpoint — it stalls ~2 °C low ("gets to 64, can't reach 65"). v1.1.15 held.

Root cause: the approach cap in pb_heater_pid.h limited SSR duty by chamber distance-to-target (40% within 2 °C, 70% within 5 °C). That clamped the steady-state hold, creating a stable attractor at target − 2 °C for any enclosure whose hold duty exceeds the cap, and integral_max = output_max − proportional stopped the integrator from compensating. It also throttled the element below its safe capability, adding SSR duty-modulation (wear) the prior bang-bang firmware never had — the concern Justin raised about frequent SSR trips.

The element (PTC) foldback already in pb_heater.c is the correct near-target limiter (a real thermal/safety limit). The chamber-error cap ceilinged the wrong variable.

Fix

  • Rate-gated soft anti-overshoot (pb_heater_pid_approach_soft_cap): full authority unless within 3 °C of target and genuinely climbing (>0.06 °C/s), so a settled/oscillating hold is never clamped, while a fast approach on a low-loss enclosure still gets overshoot damping. integral_max frees up at hold.
  • EMA-filtered gate rate (α 0.20): the NTC reports in ~0.1 °C steps, so a single tick spikes the one-sample rate to ~0.2 °C/s and would flicker the cap through the whole hold. Filtering rejects isolated ticks while a sustained climb still registers (bench: 27% → 8% of hold samples capped).
  • SSR wear: widen the time-proportioning window 10 s → 30 s + a 2 s minimum on/off dwell (steady-state switching 12/min → ~4/min).
  • Applied soft cap reported via state->last_approach_cap telemetry (DragonSniff//diag still see when damping is active).

Fixed safety cutoffs (105 °C PTC / 85 °C chamber / 70 °C target) untouched. All DragonBreath-side — no dc_pid change.

Bench validation (enclosed U1, 65 °C target, bed 100 °C)

chamber hold vs 65 SSR/min chamber cap
v1.1.18 (bug) 62.9 °C −2.1 12 pinned 0.40–0.70
v1.1.15 (good) 64.3 °C −0.7 2.3 n/a
this fix 64.3 °C −0.7 4.4 released (1.0)

The fix recovers v1.1.15's reach exactly and cuts SSR switching ~63% vs the bug. Raising the already-exposed fb_cut advanced setting 102 → 103 °C then reached and held a full 65.0 °C on the same rig, with the element still ~90 °C at steady state (huge margin to the 105 °C cutoff) — so fb_cut is the per-enclosure element-headroom knob for lossy setups.

Tests

Host suite (tests/pb_heater_pid_host_test.c) rewritten to cover the soft cap, EMA quantization-spike rejection, the 30 s window + dwell, a settled hold reaching full authority, and fast-approach damping. All four heater/policy host suites pass; firmware builds (esp32c3).

Follow-ups (not in this PR)

  • Optional: expose SSR window / soft-cap params as advanced settings (foldback-chain mirror) — deferred since fb_cut already covers the highest-impact knob.
  • The residual ~8% plateau flicker could go to ~0 by latching the anti-overshoot off after target is first reached this session — a small state-machine change worth discussing separately.

🤖 Generated with Claude Code

https://claude.ai/code/session_012B9YKQ5yUenkyDUqdbn6HP

plastikman and others added 2 commits September 15, 2026 20:08
…old below setpoint

Since v1.1.16 the chamber controller could not hold setpoint -- it stalled
~2 C low ("gets to 64, can't reach 65"). Root cause is the approach cap in
pb_heater_pid.h, which limited SSR duty by chamber distance-to-target (40%
within 2 C, 70% within 5 C). That clamped the STEADY-STATE hold, creating a
stable attractor at target-2 C for any enclosure whose hold duty exceeds the
cap, and integral_max = output_max - proportional prevented the integrator
from compensating. It also throttled the element below its safe capability,
adding SSR duty-modulation (wear) the prior bang-bang firmware did not have.

Bench-validated on an enclosed U1 (65 C target, bed 100 C):
  v1.1.18 (bug):  chamber 62.9 C, SSR 12/min, duty capped 0.40-0.70
  v1.1.15 (good): chamber 64.3 C, SSR 2.3/min (element-foldback limited)
  this fix:       chamber 64.3 C, SSR 4.4/min, approach cap released at hold
The element (PTC) foldback in pb_heater.c is the correct near-target limiter
(a real thermal/safety limit); the chamber-error cap ceilinged the wrong
variable.

Changes:
- Replace the chamber-error cap with a rate-gated SOFT anti-overshoot
  (pb_heater_pid_approach_soft_cap): full authority unless within 3 C of
  target AND genuinely climbing (>0.06 C/s), so a settled/oscillating hold is
  never clamped while a fast approach on a low-loss enclosure still gets
  overshoot damping. The gate rate is EMA-filtered (alpha 0.20) to reject the
  ~0.1 C NTC quantization ticks that otherwise spike the one-sample rate to
  ~0.2 C/s and flicker the cap through the hold (bench: 27% -> 8% of samples).
- Widen the SSR time-proportioning window 10 s -> 30 s and add a 2 s minimum
  on/off dwell, cutting steady-state SSR switching (12/min -> ~4/min).
- Report the applied soft cap via state->last_approach_cap telemetry.

Fixed safety cutoffs (105 C PTC / 85 C chamber / 70 C target) are untouched.
The already-exposed fb_cut advanced setting (default 102 C) remains the
per-enclosure element-headroom knob: raising it to 103 C let the same rig
reach a full 65 C hold with the element still ~90 C at steady state.

Host tests updated for the soft cap, EMA quantization rejection, the 30 s
window + dwell, and a settled hold reaching full authority.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012B9YKQ5yUenkyDUqdbn6HP
Release notes for the v1.1.19-rc1 prerelease; the release workflow pulls this
section into the GitHub Release. Content only — no code change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012B9YKQ5yUenkyDUqdbn6HP
@plastikman
plastikman merged commit 3563026 into main Sep 20, 2026
1 check passed
plastikman added a commit that referenced this pull request Sep 23, 2026
Consolidates rc1/rc2 into the 1.1.19 release: selectable Bang-Bang/PID
chamber control (#95), configurable hostname, the approach-cap hold fix
(#103), and follow-the-filament material detection (#65). Both follow-the-
filament and heater-method tested good on hardware.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant