From b7fcd2b301ea08890f850157381ef7e47246f5c9 Mon Sep 17 00:00:00 2001 From: Bastian de Byl Date: Thu, 14 May 2026 15:48:40 -0400 Subject: [PATCH] feat: broadcast worst-case OBC temperature on 0x211 byte 7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Tesla OBC hardware already publishes 9 temperature probes (3 modules × {tmp1, tmp2, tmpin}) on CAN 0x237/0x239/0x23B which the teslacharger receives as c[123]tmp[12,in]. Until now none of these were forwarded downstream — the Polarity VCU's STATUS_SCREEN OBC-temp and DCDC-temp fields rendered 0 °C on OI-OBC cars. This commit: - Adds Param::tmpobcmax — derived value computed each Ms100Task tick as the max across the 9 probes, skipping any that read -40 °C (sensor absent / module not present). - Maps it to 0x211 byte 7 (previously reserved, the last unused byte of the 7-byte frame). Wire encoding uses the Tesla OBC convention of offset 40 (wire = °C + 40), matching c[123]tmp* upstream so receivers can decode with the same formula. - Bumps VERSTR to -S5 so the right firmware is visually confirmable in the OpenInverter web UI. The new byte is purely additive — existing 0x211 consumers that read only bytes 0-6 continue to work unchanged. The Polarity VCU's 0x211 RX handler grows a corresponding decode + display path in a paired stm32-hal-vcu commit. Co-Authored-By: Claude Opus 4.7 (1M context) --- include/param_prj.h | 5 +++-- src/chargercan.cpp | 25 ++++++++++++++----------- src/main.cpp | 26 ++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 13 deletions(-) diff --git a/include/param_prj.h b/include/param_prj.h index 15387b5..d35551a 100644 --- a/include/param_prj.h +++ b/include/param_prj.h @@ -47,7 +47,7 @@ 3. Display values */ //Next param id (increase when adding new parameter!): 24 -//Next value Id: 2051 +//Next value Id: 2052 /* category name unit min max default id */ #define PARAM_LIST \ PARAM_ENTRY(CAT_CHARGER, idclim, "A", 0, 45, 45, 3 ) \ @@ -108,6 +108,7 @@ VALUE_ENTRY(c3iac, "A", 2034 ) \ VALUE_ENTRY(c3udc, "V", 2035 ) \ VALUE_ENTRY(c3idc, "A", 2036 ) \ + VALUE_ENTRY(tmpobcmax, "°C", 2051 ) \ VALUE_ENTRY(test_time, "s", 3000 ) \ VALUE_ENTRY(test_timer_flag, "X", 3001 ) \ VALUE_ENTRY(test_timer_icvalue, "X", 3002 ) \ @@ -128,7 +129,7 @@ // 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 convention. -#define VERSTR STRINGIFY(4=VER-S4) +#define VERSTR STRINGIFY(4=VER-S5) /***** enums ******/ diff --git a/src/chargercan.cpp b/src/chargercan.cpp index c52f086..42c3ca2 100644 --- a/src/chargercan.cpp +++ b/src/chargercan.cpp @@ -108,16 +108,19 @@ void ChargerCAN::MapMessages(CanMap* can) can->AddRecv(Param::vcuchglim, 0x212, 0, 8, 1); /***** SKUDAK VCU telemetry (0x211) — SKUDAK-448 expanded charger telemetry *****/ - // Byte 0: state (0=Off, 1=WaitStart, 2=Enable, 3=Activate, 4=Run, 5=Stop) - // Bytes 1-2: udc (V, gain=1) - // Bytes 3-4: idc (0.1A, gain=10) - // Byte 5: uaux (decivolts, gain=10) — 12V aux battery rail - // Byte 6: soc (%, gain=1) - // Byte 7: reserved + // Byte 0: state (0=Off, 1=WaitStart, 2=Enable, 3=Activate, 4=Run, 5=Stop) + // Bytes 1-2: udc (V, gain=1) + // Bytes 3-4: idc (0.1A, gain=10) + // Byte 5: uaux (decivolts, gain=10) — 12V aux battery rail + // Byte 6: soc (%, gain=1) + // Byte 7: tmpobcmax (°C, gain=1, offset=-40) — worst-case across all + // 9 OBC probes; matches Tesla OBC's own CAN offset + // so receivers can decode with the same formula. // Consumed by stm32-hal-vcu Core/Src/main.c CHARGER_CAN_ID_OI_OBC_AUX handler. - can->AddSend(Param::state, 0x211, 0, 8, 1); - can->AddSend(Param::udc, 0x211, 8, 16, 1); - can->AddSend(Param::idc, 0x211, 24, 16, 10); - can->AddSend(Param::uaux, 0x211, 40, 8, 10); - can->AddSend(Param::soc, 0x211, 48, 8, 1); + can->AddSend(Param::state, 0x211, 0, 8, 1); + can->AddSend(Param::udc, 0x211, 8, 16, 1); + can->AddSend(Param::idc, 0x211, 24, 16, 10); + can->AddSend(Param::uaux, 0x211, 40, 8, 10); + can->AddSend(Param::soc, 0x211, 48, 8, 1); + can->AddSend(Param::tmpobcmax, 0x211, 56, 8, 1, 40); // offset 40 → wire byte = temp + 40 } diff --git a/src/main.cpp b/src/main.cpp index e0214b9..790efe8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -77,6 +77,32 @@ static void Ms100Task(void) EvseRead(); + // SKUDAK: derive a single "worst case" OBC temperature for downstream + // consumers (Polarity VCU broadcasts it on STATUS_SCREEN bytes 23/26). + // Aggregates the 9 per-module probes the Tesla OBC publishes on CAN + // 0x237/0x239/0x23B — max wins. Modules without a sensor read -40 °C + // (the DBC offset; raw byte 0); we ignore those so an absent module + // doesn't drag the worst-case down. If no probes are valid we leave + // tmpobcmax at -40 °C, which the VCU will display as "—". + { + const Param::PARAM_NUM probes[] = { + Param::c1tmp1, Param::c1tmp2, Param::c1tmpin, + Param::c2tmp1, Param::c2tmp2, Param::c2tmpin, + Param::c3tmp1, Param::c3tmp2, Param::c3tmpin, + }; + int worst = -40; + bool any_ok = false; + for (unsigned i = 0; i < sizeof(probes) / sizeof(probes[0]); i++) { + int t = Param::GetInt(probes[i]); + if (t <= -40) continue; // No sensor / module not present + if (!any_ok || t > worst) { + worst = t; + any_ok = true; + } + } + Param::SetInt(Param::tmpobcmax, any_ok ? worst : -40); + } + canMap->SendAll(); }