feat: S12 — vcucmd 3-state command from VCU (replaces binary vcustop) #10

Open
bastian wants to merge 3 commits from feat/s12-vcucmd-3state into fix/canmap-revert-clear-add-reentrancy-guard
Showing only changes of commit 0514940877 - Show all commits
+46 -1
View File
@@ -383,13 +383,58 @@ void ChargerStateMachine()
// VCU command is the primary exit. CheckUnplugged + CheckChargerFaults
// remain for hardware safety; the self-decided CheckVoltage/CheckTimeout
// exits are gone (S12 — VCU is authoritative).
//
// SKUDAK: ramp the DC-current reference toward zero across 3 ticks
// (300 ms) before transitioning to STOP. Without this, the VCU
// opening its HV contactor at the moment we go STOP triggers a hard
// 23 A → 0 disconnect transient that floods the Tesla BMS state-
// change CAN path and starves the VCU's task scheduler past its
// IWDG window (bench-confirmed 2026-05-21 limit-lower 0x002A loop).
// The VCU also defers its contactor open by ~1500 ms; together
// they make the disconnect graceful even on a hard limit-lower
// mid-RUN. completeRampTicks counts DOWN from 3 → 0; the original
// reference is stashed so if vcucmd reverts to Charging mid-ramp
// we restore cleanly.
static uint8_t completeRampTicks = 0;
static s32fp completeRampOriginalRef = 0;
if (vcucmd == VCUCMD_COMPLETE)
{
if (completeRampTicks == 0)
{
completeRampOriginalRef = MIN(Param::Get(Param::idcspnt), Param::Get(Param::idclim));
completeRampTicks = 3;
}
if (completeRampTicks > 1)
{
// Scale 2/3 → 1/3 → 0 across remaining ticks.
s32fp scaled = (completeRampOriginalRef * (completeRampTicks - 1)) / 3;
dcCurController.SetRef(scaled);
completeRampTicks--;
// Stay in EVSEACTIVATE this tick; current is decaying.
}
else
{
dcCurController.SetRef(0);
DigIo::acpres_out.Clear();
DigIo::evseact_out.Clear();
completeRampTicks = 0;
completeRampOriginalRef = 0;
state = STOP;
}
else if (vcucmd == VCUCMD_STOPPED)
break;
}
// vcucmd not Complete — if we were mid-ramp the user reversed
// (raised limit again); restore reference before the existing
// branches take over.
if (completeRampTicks != 0)
{
dcCurController.SetRef(completeRampOriginalRef);
completeRampTicks = 0;
completeRampOriginalRef = 0;
}
if (vcucmd == VCUCMD_STOPPED)
{
// VCU revoked the charge command (e.g. user lowered limit below
// current SOC but BMS isn't full yet). Park HV-armed in ENABLE