From a30cded074cab10eda9390015315370b553761d9 Mon Sep 17 00:00:00 2001 From: Bastian de Byl Date: Thu, 21 May 2026 16:23:47 -0400 Subject: [PATCH] fix: restore PI reference on final ramp tick (iteration O regression) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The iteration O 3-tick ramp ended with dcCurController.SetRef(0) before transitioning to STOP. Param::Change only fires when idcspnt or idclim parameter values change — a normal STOP → OFF → WAITSTART → ENABLE → ACTIVATE → RUN → EVSEACTIVATE restart cycle never touches those, so nothing restored the PI reference. On the next entry to EVSEACTIVATE the controller targeted 0 A and the charger sipped ~0.1 kW. Bench-confirmed 2026-05-21 on iteration O firmware: after lowering the ChargeLimit_pct to drop into COMPLETE and then raising it back, charging restarted at 0.1 kW instead of ramping to 9 kW. Fix: on the final ramp tick, restore SetRef to MIN(idcspnt, idclim) instead of zeroing it. The GPIO clears (acpres_out, evseact_out) still cut AC enable so the output current decays through the filter caps; the reference value is irrelevant during STOP but matters for the next EVSEACTIVATE entry. The ramp-restore block in the vcucmd != Complete branch (charger.cpp:431 in iteration O) only handles the mid-ramp reversal case (counter ≠ 0); it didn't help when the ramp completed cleanly. This commit closes that gap. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/charger.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/charger.cpp b/src/charger.cpp index 9a3ee3d..1ef60b0 100644 --- a/src/charger.cpp +++ b/src/charger.cpp @@ -414,9 +414,17 @@ void ChargerStateMachine() } else { - dcCurController.SetRef(0); + // Final ramp tick: clear GPIOs (cuts AC enable; output decays + // through filter caps) and restore the PI reference to the + // current idcspnt/idclim so the NEXT EVSEACTIVATE entry + // doesn't sip at 0 A. Param::Change only fires on parameter + // changes; a normal restart cycle never touches idcspnt or + // idclim, so without this restore the PI controller stays + // pinned at 0 across the cycle. Iteration O bug — bench- + // confirmed 0.1 kW sip on limit-raise from COMPLETE. DigIo::acpres_out.Clear(); DigIo::evseact_out.Clear(); + dcCurController.SetRef(MIN(Param::Get(Param::idcspnt), Param::Get(Param::idclim))); completeRampTicks = 0; completeRampOriginalRef = 0; state = STOP;