33#include " sp140/globals.h"
44#include " sp140/lvgl/lvgl_core.h" // for spiBusMutex
55
6+ namespace {
7+
8+ void logBmsCellProbeConnectionTransitions (const float sanitizedCellTemps[BMS_CELL_PROBE_COUNT]) {
9+ static bool hasPreviousState = false ;
10+ static bool wasConnected[BMS_CELL_PROBE_COUNT] = {false , false , false , false };
11+
12+ for (uint8_t i = 0 ; i < BMS_CELL_PROBE_COUNT; i++) {
13+ const bool connected = !isnan (sanitizedCellTemps[i]);
14+
15+ if (!hasPreviousState) {
16+ wasConnected[i] = connected;
17+ continue ;
18+ }
19+
20+ if (connected != wasConnected[i]) {
21+ USBSerial.printf (" [BMS] T%u sensor %s (sanitized=%.1fC)\n " ,
22+ i + 1 ,
23+ connected ? " reconnected" : " disconnected" ,
24+ sanitizedCellTemps[i]);
25+ wasConnected[i] = connected;
26+ }
27+ }
28+
29+ hasPreviousState = true ;
30+ }
31+
32+ } // namespace
33+
634STR_BMS_TELEMETRY_140 bmsTelemetryData = {
735 .bmsState = TelemetryState::NOT_CONNECTED
836};
@@ -51,10 +79,6 @@ void updateBMSData() {
5179 // Calculated highest cell minus lowest cell voltage
5280 bmsTelemetryData.voltage_differential = bms_can->getHighestCellVoltage () - bms_can->getLowestCellVoltage ();
5381
54- // Temperature readings
55- bmsTelemetryData.highest_temperature = bms_can->getHighestTemperature ();
56- bmsTelemetryData.lowest_temperature = bms_can->getLowestTemperature ();
57-
5882 // Battery statistics
5983 bmsTelemetryData.battery_cycle = bms_can->getBatteryCycle ();
6084 bmsTelemetryData.energy_cycle = bms_can->getEnergyCycle ();
@@ -70,13 +94,31 @@ void updateBMSData() {
7094 bmsTelemetryData.cell_voltages [i] = bms_can->getCellVoltage (i);
7195 }
7296
73- // Populate individual temperature sensors
97+ // Populate temperature sensors (library returns NaN for disconnected probes)
7498 bmsTelemetryData.mos_temperature = bms_can->getTemperature (0 ); // BMS MOSFET
7599 bmsTelemetryData.balance_temperature = bms_can->getTemperature (1 ); // BMS Balance resistors
76- bmsTelemetryData.t1_temperature = bms_can->getTemperature (2 ); // Cell probe 1
77- bmsTelemetryData.t2_temperature = bms_can->getTemperature (3 ); // Cell probe 2
78- bmsTelemetryData.t3_temperature = bms_can->getTemperature (4 ); // Cell probe 3
79- bmsTelemetryData.t4_temperature = bms_can->getTemperature (5 ); // Cell probe 4
100+
101+ // Cell probes: library already returns NaN for disconnected. Apply app-level
102+ // policy (tolerate up to N disconnected before alerting).
103+ const float cellTemps[BMS_CELL_PROBE_COUNT] = {
104+ bms_can->getTemperature (2 ),
105+ bms_can->getTemperature (3 ),
106+ bms_can->getTemperature (4 ),
107+ bms_can->getTemperature (5 )
108+ };
109+ float sanitizedCellTemps[BMS_CELL_PROBE_COUNT];
110+ sanitizeCellProbeTemps (cellTemps, sanitizedCellTemps);
111+ bmsTelemetryData.t1_temperature = sanitizedCellTemps[0 ];
112+ bmsTelemetryData.t2_temperature = sanitizedCellTemps[1 ];
113+ bmsTelemetryData.t3_temperature = sanitizedCellTemps[2 ];
114+ bmsTelemetryData.t4_temperature = sanitizedCellTemps[3 ];
115+
116+ // Emit transition logs to help field-debug intermittent probe wiring issues.
117+ logBmsCellProbeConnectionTransitions (sanitizedCellTemps);
118+
119+ // Library already excludes disconnected probes from high/low temps
120+ bmsTelemetryData.highest_temperature = bms_can->getHighestTemperature ();
121+ bmsTelemetryData.lowest_temperature = bms_can->getLowestTemperature ();
80122
81123 bmsTelemetryData.lastUpdateMs = millis ();
82124 unsigned long dur = bmsTelemetryData.lastUpdateMs - tStart;
0 commit comments