aae23f53a6
Promote 0x212 byte 3 from S11's binary vcustop to the full Dilong-style
OBC_ControlCMD vocabulary:
0 = Charging — walk to / hold at EVSEACTIVATE, produce current
1 = Stopped — sit idle in OFF/WAITSTART/ENABLE, no current
2 = Complete — drop to STOP (cycle terminated by VCU)
VCU is now authoritative for the charge-cycle lifecycle. The charger
keeps hardware-level wisdom (EVSE pilot via CheckStartCondition,
plug-out safety via CheckUnplugged, module-fault detection via
CheckChargerFaults) but obeys vcucmd for "should I be charging?".
FSM changes:
- ENABLE→ACTIVATE now gated on vcucmd==Charging (was unconditional).
ENABLE on vcucmd==Complete drops to STOP; vcucmd==Stopped holds
HV-armed waiting for next Charging command.
- EVSEACTIVATE self-decided exits (CheckVoltage, CheckTimeout) are
gone. Those were band-aids for the absence of an authoritative VCU
stop signal. vcucmd==Stopped now parks back in ENABLE (HV held);
vcucmd==Complete drops to STOP. CheckUnplugged + CheckChargerFaults
still own hardware-safety exits.
- STOP→OFF now also triggers on vcucmd != Complete (was unplug-only).
This is the fix for the "raise ChargeLimit mid-COMPLETE doesn't
restart charging" wedge — the VCU's vcucmd flip from Complete to
Stopped on a limit-raise lets the natural OFF→WAITSTART→ENABLE→
ACTIVATE→EVSEACTIVATE flow resume charging without an unplug cycle.
Param rename vcustop→vcucmd. External tooling that reads/writes the
S11 vcustop param via the openinverter web UI will see the new vcucmd
param with 3-state semantics — single-user bench, acceptable.
VERSTR bumped to S12.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
232 lines
10 KiB
C
232 lines
10 KiB
C
/*
|
|
* This file is part of the stm32-template project.
|
|
*
|
|
* Copyright (C) 2020 Johannes Huebner <dev@johanneshuebner.com>
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/* This file contains all parameters used in your project
|
|
* See main.cpp on how to access them.
|
|
* If a parameters unit is of format "0=Choice, 1=AnotherChoice" etc.
|
|
* It will be displayed as a dropdown in the web interface
|
|
* If it is a spot value, the decimal is translated to the name, i.e. 0 becomes "Choice"
|
|
* If the enum values are powers of two, they will be displayed as flags, example
|
|
* "0=None, 1=Flag1, 2=Flag2, 4=Flag3, 8=Flag4" and the value is 5.
|
|
* It means that Flag1 and Flag3 are active -> Display "Flag1 | Flag3"
|
|
*
|
|
* Every parameter/value has a unique ID that must never change. This is used when loading parameters
|
|
* from flash, so even across firmware versions saved parameters in flash can always be mapped
|
|
* back to our list here. If a new value is added, it will receive its default value
|
|
* because it will not be found in flash.
|
|
* The unique ID is also used in the CAN module, to be able to recover the CAN map
|
|
* no matter which firmware version saved it to flash.
|
|
* Make sure to keep track of your ids and avoid duplicates. Also don't re-assign
|
|
* IDs from deleted parameters because you will end up loading some random value
|
|
* into your new parameter!
|
|
* IDs are 16 bit, so 65535 is the maximum
|
|
*/
|
|
|
|
//Define a version string of your firmware here
|
|
#define VER 1.20.R
|
|
|
|
/* Entries must be ordered as follows:
|
|
1. Saveable parameters (id != 0)
|
|
2. Temporary parameters (id = 0)
|
|
3. Display values
|
|
*/
|
|
//Next param id (increase when adding new parameter!): 24
|
|
//Next value Id: 2053
|
|
/* category name unit min max default id */
|
|
#define PARAM_LIST \
|
|
PARAM_ENTRY(CAT_CHARGER, idclim, "A", 0, 45, 45, 3 ) \
|
|
PARAM_ENTRY(CAT_CHARGER, iaclim, "A", 0, 72, 16, 10 ) \
|
|
PARAM_ENTRY(CAT_CHARGER, idcspnt, "A", 0, 45, 45, 9 ) \
|
|
PARAM_ENTRY(CAT_CHARGER, chargerena, CHARGERS, 1, 7, 7, 4 ) \
|
|
PARAM_ENTRY(CAT_CHARGER, udcspnt, "V", 50, 420, 403, 5 ) \
|
|
PARAM_ENTRY(CAT_CHARGER, udclim, "V", 50, 420, 398, 6 ) \
|
|
PARAM_ENTRY(CAT_CHARGER, timelim, "minutes", -1, 10000, -1, 16 ) \
|
|
PARAM_ENTRY(CAT_CHARGER, timedly, "minutes", -1, 10000, -1, 22 ) \
|
|
PARAM_ENTRY(CAT_CHARGER, inputype, INPUTS, 0, 5, 1, 17 ) \
|
|
PARAM_ENTRY(CAT_CHARGER, cancontrol, OFFON, 0, 1, 0, 14 ) \
|
|
PARAM_ENTRY(CAT_CHARGER, enablepol, POLARITIES,0, 1, 0, 18 ) \
|
|
PARAM_ENTRY(CAT_CHARGER, idckp, "", 0, 10000, 1, 20 ) \
|
|
PARAM_ENTRY(CAT_CHARGER, idcki, "", 0, 10000, 10, 21 ) \
|
|
PARAM_ENTRY(CAT_CHARGER, vcuchglim, "%", 20, 100, 80, 23 ) \
|
|
VALUE_ENTRY(state, STATES, 2043 ) \
|
|
VALUE_ENTRY(uptime, "s", 2048 ) \
|
|
VALUE_ENTRY(lasterr, errorListString, 2002 ) \
|
|
VALUE_ENTRY(uaux, "V", 2049 ) \
|
|
VALUE_ENTRY(aclim, "A", 2042 ) \
|
|
VALUE_ENTRY(cablelim, "A", 2038 ) \
|
|
VALUE_ENTRY(evselim, "A", 2039 ) \
|
|
VALUE_ENTRY(idc, "A", 2041 ) \
|
|
VALUE_ENTRY(udc, "V", 2047 ) \
|
|
VALUE_ENTRY(soc, "%", 2046 ) \
|
|
VALUE_ENTRY(proximity, OFFON, 2040 ) \
|
|
VALUE_ENTRY(enable, OFFON, 2005 ) \
|
|
VALUE_ENTRY(canenable, OFFON, 2045 ) \
|
|
VALUE_ENTRY(cpuload, "%", 2004 ) \
|
|
VALUE_ENTRY(version, VERSTR, 2001 ) \
|
|
VALUE_ENTRY(opmode, OPMODES, 2000 ) \
|
|
VALUE_ENTRY(hwaclim, "A", 2050 ) \
|
|
VALUE_ENTRY(c1stt, "", 2007 ) \
|
|
VALUE_ENTRY(c1flag, CHFLAGS, 2008 ) \
|
|
VALUE_ENTRY(c1tmp1, "°C", 2010 ) \
|
|
VALUE_ENTRY(c1tmp2, "°C", 2011 ) \
|
|
VALUE_ENTRY(c1tmpin, "°C", 2012 ) \
|
|
VALUE_ENTRY(c1uac, "V", 2013 ) \
|
|
VALUE_ENTRY(c1iac, "A", 2014 ) \
|
|
VALUE_ENTRY(c1udc, "V", 2015 ) \
|
|
VALUE_ENTRY(c1idc, "A", 2016 ) \
|
|
VALUE_ENTRY(c2stt, "", 2017 ) \
|
|
VALUE_ENTRY(c2flag, CHFLAGS, 2018 ) \
|
|
VALUE_ENTRY(c2tmp1, "°C", 2020 ) \
|
|
VALUE_ENTRY(c2tmp2, "°C", 2021 ) \
|
|
VALUE_ENTRY(c2tmpin, "°C", 2022 ) \
|
|
VALUE_ENTRY(c2uac, "V", 2023 ) \
|
|
VALUE_ENTRY(c2iac, "A", 2024 ) \
|
|
VALUE_ENTRY(c2udc, "V", 2025 ) \
|
|
VALUE_ENTRY(c2idc, "A", 2026 ) \
|
|
VALUE_ENTRY(c3stt, "", 2027 ) \
|
|
VALUE_ENTRY(c3flag, CHFLAGS, 2028 ) \
|
|
VALUE_ENTRY(c3tmp1, "°C", 2030 ) \
|
|
VALUE_ENTRY(c3tmp2, "°C", 2031 ) \
|
|
VALUE_ENTRY(c3tmpin, "°C", 2032 ) \
|
|
VALUE_ENTRY(c3uac, "V", 2033 ) \
|
|
VALUE_ENTRY(c3iac, "A", 2034 ) \
|
|
VALUE_ENTRY(c3udc, "V", 2035 ) \
|
|
VALUE_ENTRY(c3idc, "A", 2036 ) \
|
|
VALUE_ENTRY(tmpobcmax, "°C", 2051 ) \
|
|
VALUE_ENTRY(vcucmd, VCUCMDS, 2052 ) \
|
|
VALUE_ENTRY(test_time, "s", 3000 ) \
|
|
VALUE_ENTRY(test_timer_flag, "X", 3001 ) \
|
|
VALUE_ENTRY(test_timer_icvalue, "X", 3002 ) \
|
|
|
|
|
|
/***** Enum String definitions *****/
|
|
#define OPMODES "0=Off, 1=Run"
|
|
#define CHARGERS "1=Charger1, 2=Charger2, 4=Charger3"
|
|
#define OFFON "0=Off, 1=On"
|
|
// SKUDAK-S12: VCU→charger control command on 0x212 byte 3. Mirrors the Dilong
|
|
// path's OBC_ControlCMD vocabulary exactly so VCU code paths can be reused.
|
|
// 0 = Charging — VCU wants current to flow; walk to / hold at EVSEACTIVATE
|
|
// 1 = Stopped — VCU is not driving a cycle; sit in OFF/WAITSTART/ENABLE
|
|
// 2 = Complete — VCU has terminated the cycle; drop to STOP
|
|
#define VCUCMDS "0=Charging, 1=Stopped, 2=Complete"
|
|
#define CHFLAGS "0=None, 1=Enabled, 2=Fault, 4=CheckAlive"
|
|
#define STATES "0=Off, 1=WaitStart, 2=Enable, 3=Activate, 4=Run, 5=Stop"
|
|
#define INPUTS "0=Type2, 1=Type2-3P, 2=Type1, 3=Manual, 4=Manual-3P, 5=Type2-Auto"
|
|
#define POLARITIES "0=ActiveHigh, 1=ActiveLow"
|
|
#define CAT_TEST "Testing"
|
|
#define CAT_CHARGER "Charger"
|
|
#define CAT_COMM "Communication"
|
|
|
|
// SKUDAK customization suffix: bump on every Skudak-side change so the OpenInverter
|
|
// web UI shows a distinct version (e.g. "4=1.20.R-S4") and we can visually confirm
|
|
// the right firmware is flashed. Match the stm32-sine -S<N> convention.
|
|
// -S6 was withdrawn (PR #8 closed): the canary-rebuild attempt called
|
|
// canMap->Clear() inside MapChargerMessages, which recursed through the
|
|
// HandleClear callback and stack-overflowed at boot before the terminal
|
|
// came up. Jumping straight to -S7 so any bench that still reports -S6
|
|
// in the openinverter UI is visibly the broken build and gets re-flashed.
|
|
// -S8 trims chargercan.cpp from 73 → 37 entries so the libopeninv 50-slot
|
|
// pool doesn't silently drop the SKUDAK 0x211 broadcast on rebuild.
|
|
// -S9 restores 8 c2/c3 RX entries (uac/flag/idc/udc per module). -S8 over-
|
|
// trimmed multi-module Tesla OBC support: CalcTotals was summing only
|
|
// module 1's contribution, so reported pack power was 1/3 of actual delivery.
|
|
// -S10 added udclim RX on 0x212 bytes 1-2. The VCU sent udclim=200V to force
|
|
// CheckVoltage() to fire (udc > udclim → STOP). DEPRECATED in -S11: the
|
|
// per-module DC voltage readings (c1udc/c2udc/c3udc) collapse below 200V
|
|
// once VCU opens HV contactors, so the trigger never accumulates 10 ticks.
|
|
// udclim RX is kept mapped but the VCU now always sends 398V (no-op).
|
|
//
|
|
// -S11 adds vcustop RX on 0x212 byte 3 — an explicit VCU command lever that
|
|
// mirrors the Dilong path's OBC_ControlCMD. When VCU enters CHARGE_COMPLETE
|
|
// it sets vcustop=1; ChargerStateMachine's EVSEACTIVATE case transitions to
|
|
// STOP immediately, the J1772 CP signal drops, EVSE stops delivering AC,
|
|
// VCU_IsCharging() returns 0, water pumps power down naturally.
|
|
// -S12 promotes byte 3 from a binary vcustop flag to the full 3-state
|
|
// VCUCMDS vocabulary (0=Charging, 1=Stopped, 2=Complete), matching the
|
|
// Dilong OBC_ControlCMD exactly. The internal FSM now obeys vcucmd for
|
|
// lifecycle transitions: ENABLE only advances to ACTIVATE on Charging, STOP
|
|
// returns to OFF when vcucmd flips back to Charging/Stopped (fixes the
|
|
// "raise ChargeLimit mid-COMPLETE doesn't resume" wedge — teslacharger was
|
|
// stuck in STOP because STOP only exited on CheckUnplugged). The self-
|
|
// decided EVSEACTIVATE exits (CheckVoltage, CheckTimeout) are stripped; the
|
|
// VCU is now authoritative for when charging starts and stops. The charger
|
|
// retains hardware-level wisdom: CheckUnplugged() still forces OFF from any
|
|
// state, and CheckStartCondition() still gates OFF→WAITSTART on EVSE pilot.
|
|
#define VERSTR STRINGIFY(4=VER-S12)
|
|
|
|
/***** enums ******/
|
|
|
|
enum inputs
|
|
{
|
|
INP_TYPE2,
|
|
INP_TYPE2_3P,
|
|
INP_TYPE1,
|
|
INP_MANUAL,
|
|
INP_MANUAL_3P,
|
|
INP_TYPE2_AUTO
|
|
};
|
|
|
|
enum states
|
|
{
|
|
OFF,
|
|
WAITSTART,
|
|
ENABLE,
|
|
ACTIVATE,
|
|
EVSEACTIVATE,
|
|
STOP
|
|
};
|
|
|
|
// SKUDAK-S12: VCU→charger command vocabulary on 0x212 byte 3. Must match
|
|
// the values exposed via VCUCMDS enum string AND the VCU's
|
|
// VCU_OIOBCCommand_t enum (stm32-hal-vcu Core/Inc/applications/charger/
|
|
// charger_types.h). Updating one without the others silently breaks the
|
|
// charge state machine, so keep them in lock-step.
|
|
enum vcucmds
|
|
{
|
|
VCUCMD_CHARGING = 0,
|
|
VCUCMD_STOPPED = 1,
|
|
VCUCMD_COMPLETE = 2
|
|
};
|
|
|
|
enum _canspeeds
|
|
{
|
|
CAN_PERIOD_100MS = 0,
|
|
CAN_PERIOD_10MS,
|
|
CAN_PERIOD_LAST
|
|
};
|
|
|
|
enum _modes
|
|
{
|
|
MOD_OFF = 0,
|
|
MOD_RUN,
|
|
MOD_LAST
|
|
};
|
|
|
|
enum _chflags
|
|
{
|
|
FLAG_NONE = 0,
|
|
FLAG_ENABLED = 1,
|
|
FLAG_FAULT = 2,
|
|
FLAG_CHECK = 4
|
|
};
|
|
|
|
//Generated enum-string for possible errors
|
|
extern const char* errorListString;
|
|
|