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
|
// VCU command is the primary exit. CheckUnplugged + CheckChargerFaults
|
||||||
// remain for hardware safety; the self-decided CheckVoltage/CheckTimeout
|
// remain for hardware safety; the self-decided CheckVoltage/CheckTimeout
|
||||||
// exits are gone (S12 — VCU is authoritative).
|
// 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 (vcucmd == VCUCMD_COMPLETE)
|
||||||
{
|
{
|
||||||
DigIo::acpres_out.Clear();
|
if (completeRampTicks == 0)
|
||||||
DigIo::evseact_out.Clear();
|
{
|
||||||
state = STOP;
|
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
|
// VCU revoked the charge command (e.g. user lowered limit below
|
||||||
// current SOC but BMS isn't full yet). Park HV-armed in ENABLE
|
// current SOC but BMS isn't full yet). Park HV-armed in ENABLE
|
||||||
|
|||||||
Reference in New Issue
Block a user