feat: S12 — vcucmd 3-state command from VCU (replaces binary vcustop) #10
+49
-4
@@ -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)
|
||||
{
|
||||
DigIo::acpres_out.Clear();
|
||||
DigIo::evseact_out.Clear();
|
||||
state = STOP;
|
||||
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;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (vcucmd == VCUCMD_STOPPED)
|
||||
|
||||
// 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
|
||||
|
||||
Reference in New Issue
Block a user