Merge branch 'main' into feature/mqtt_library_replacement

This commit is contained in:
Matt Holmes 2025-01-19 20:13:55 +00:00
commit fc3f5b4e31
12 changed files with 1613 additions and 238 deletions

View file

@ -51,6 +51,7 @@ jobs:
battery:
- BMW_I3_BATTERY
- BMW_IX_BATTERY
- BMW_PHEV_BATTERY
- BYD_ATTO_3_BATTERY
- CELLPOWER_BMS
- CHADEMO_BATTERY

View file

@ -56,6 +56,7 @@ jobs:
battery:
- BMW_I3_BATTERY
- BMW_IX_BATTERY
- BMW_PHEV_BATTERY
- BYD_ATTO_3_BATTERY
- CELLPOWER_BMS
- CHADEMO_BATTERY

View file

@ -54,7 +54,7 @@
#endif // WIFI
// The current software version, shown on webserver
const char* version_number = "8.2.dev";
const char* version_number = "8.3.dev";
// Interval settings
uint16_t intervalUpdateValues = INTERVAL_1_S; // Interval at which to update inverter values / Modbus registers

View file

@ -11,6 +11,7 @@
/* Select battery used */
//#define BMW_I3_BATTERY
//#define BMW_IX_BATTERY
//#define BMW_PHEV_BATTERY
//#define BOLT_AMPERA_BATTERY
//#define BYD_ATTO_3_BATTERY
//#define CELLPOWER_BMS

View file

@ -17,6 +17,10 @@ void setup_can_shunt();
#include "BMW-IX-BATTERY.h"
#endif
#ifdef BMW_PHEV_BATTERY
#include "BMW-PHEV-BATTERY.h"
#endif
#ifdef BOLT_AMPERA_BATTERY
#include "BOLT-AMPERA-BATTERY.h"
#endif

View file

@ -272,6 +272,12 @@ CAN_frame BMWiX_6F4_REQUEST_BALANCING_START = {
.DLC = 6,
.ID = 0x6F4,
.data = {0xF4, 0x04, 0x71, 0x01, 0xAE, 0x77}}; // Request Balancing command?
CAN_frame BMWiX_6F4_REQUEST_BALANCING_START2 = {
.FD = true,
.ext_ID = false,
.DLC = 6,
.ID = 0x6F4,
.data = {0xF4, 0x04, 0x31, 0x01, 0xAE, 0x77}}; // Request Balancing command?
CAN_frame BMWiX_6F4_REQUEST_PACK_VOLTAGE_LIMITS = {
.FD = true,
.ext_ID = false,
@ -330,15 +336,15 @@ int numUDSreqs = sizeof(UDS_REQUESTS100MS) / sizeof(UDS_REQUESTS100MS[0]); // N
static bool battery_info_available = false;
static uint32_t battery_serial_number = 0;
static int32_t battery_current = 0;
static int16_t battery_voltage = 370;
static int16_t battery_voltage = 370; //Startup with valid values - needs fixing in future
static int16_t terminal30_12v_voltage = 0;
static int16_t battery_voltage_after_contactor = 0;
static int16_t min_soc_state = 50;
static int16_t avg_soc_state = 50;
static int16_t max_soc_state = 50;
static int16_t min_soh_state = 99; // Uses E5 45, also available in 78 73
static int16_t avg_soh_state = 99; // Uses E5 45, also available in 78 73
static int16_t max_soh_state = 99; // Uses E5 45, also available in 78 73
static int16_t min_soc_state = 5000;
static int16_t avg_soc_state = 5000;
static int16_t max_soc_state = 5000;
static int16_t min_soh_state = 9900; // Uses E5 45, also available in 78 73
static int16_t avg_soh_state = 9900; // Uses E5 45, also available in 78 73
static int16_t max_soh_state = 9900; // Uses E5 45, also available in 78 73
static uint16_t max_design_voltage = 0;
static uint16_t min_design_voltage = 0;
static int32_t remaining_capacity = 0;
@ -347,8 +353,8 @@ static int16_t min_battery_temperature = 0;
static int16_t avg_battery_temperature = 0;
static int16_t max_battery_temperature = 0;
static int16_t main_contactor_temperature = 0;
static int16_t min_cell_voltage = 0;
static int16_t max_cell_voltage = 0;
static int16_t min_cell_voltage = 3700; //Startup with valid values - needs fixing in future
static int16_t max_cell_voltage = 3700; //Startup with valid values - needs fixing in future
static unsigned long min_cell_voltage_lastchanged = 0;
static unsigned long max_cell_voltage_lastchanged = 0;
static unsigned min_cell_voltage_lastreceived = 0;
@ -763,6 +769,8 @@ void transmit_can_battery() {
// Send 10000ms CAN Message
if (currentMillis - previousMillis10000 >= INTERVAL_10_S) {
previousMillis10000 = currentMillis;
transmit_can_frame(&BMWiX_6F4_REQUEST_BALANCING_START2, can_config.battery);
transmit_can_frame(&BMWiX_6F4_REQUEST_BALANCING_START, can_config.battery);
}
}
//We can always send CAN as the iX BMS will wake up on vehicle comms

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,22 @@
#ifndef BMW_PHEV_BATTERY_H
#define BMW_PHEV_BATTERY_H
#include <Arduino.h>
#include "../include.h"
#define BATTERY_SELECTED
#define MAX_PACK_VOLTAGE_DV 4650 //4650 = 465.0V
#define MIN_PACK_VOLTAGE_DV 3000
#define MAX_CELL_DEVIATION_MV 250
#define MAX_CELL_VOLTAGE_MV 4300 //Battery is put into emergency stop if one cell goes over this value
#define MIN_CELL_VOLTAGE_MV 2800 //Battery is put into emergency stop if one cell goes below this value
#define MAX_DISCHARGE_POWER_ALLOWED_W 10000
#define MAX_CHARGE_POWER_ALLOWED_W 10000
#define MAX_CHARGE_POWER_WHEN_TOPBALANCING_W 500
#define RAMPDOWN_SOC 9000 // (90.00) SOC% to start ramping down from max charge power towards 0 at 100.00%
#define STALE_PERIOD_CONFIG \
3600000; //Number of milliseconds before critical values are classed as stale/stuck 1800000 = 3600 seconds / 60mins
void setup_battery(void);
void transmit_can_frame(CAN_frame* tx_frame, int interface);
#endif

View file

@ -38,6 +38,7 @@ static bool cellvoltagesRead = false;
static uint32_t battery_total_discharge = 0;
static uint32_t battery_total_charge = 0;
//0x352: 850 BMS_energyStatus
static bool BMS352_mux = false; // variable to store when 0x352 mux is present
static uint16_t battery_energy_buffer = 0; // kWh
static uint16_t battery_energy_buffer_m1 = 0; // kWh
static uint16_t battery_energy_to_charge_complete = 0; // kWh
@ -123,6 +124,8 @@ static bool battery_fcCtrsOpenRequested = false; // Change to bool
static uint8_t battery_fcCtrsRequestStatus = 0;
static bool battery_fcCtrsResetRequestRequired = false; // Change to bool
static bool battery_fcLinkAllowedToEnergize = false; // Change to bool
//0x72A: BMS_serialNumber
static uint8_t BMS_SerialNumber[14] = {0}; // Stores raw HEX values for ASCII chars
//0x212: 530 BMS_status
static bool battery_BMS_hvacPowerRequest = false; //Change to bool
static bool battery_BMS_notEnoughPowerForDrive = false; //Change to bool
@ -507,6 +510,8 @@ static bool battery2_fcCtrsOpenRequested = false;
static uint8_t battery2_fcCtrsRequestStatus = 0;
static bool battery2_fcCtrsResetRequestRequired = false;
static bool battery2_fcLinkAllowedToEnergize = false;
//0x72A: BMS_serialNumber
static uint8_t BMS2_SerialNumber[14] = {0}; // Stores raw HEX values for ASCII chars
//0x212: 530 BMS_status
static bool battery2_BMS_hvacPowerRequest = false;
static bool battery2_BMS_notEnoughPowerForDrive = false;
@ -592,7 +597,7 @@ static bool HVP2_gpioPyroIsoEn = false;
static bool HVP2_gpioCpFaultIn = false;
static bool HVP2_gpioPackContPowerEn = false;
static bool HVP2_gpioHvCablesOk = false;
static bool HVP2_gpioHVPSelfEnable = false;
static bool HVP2_gpioHvpSelfEnable = false;
static bool HVP2_gpioLed = false;
static bool HVP2_gpioCrashSignal = false;
static bool HVP2_gpioShuntDataReady = false;
@ -602,7 +607,7 @@ static bool HVP2_gpioBmsEout = false;
static bool HVP2_gpioCpFaultOut = false;
static bool HVP2_gpioPyroPor = false;
static bool HVP2_gpioShuntEn = false;
static bool HVP2_gpioHVPVerEn = false;
static bool HVP2_gpioHvpVerEn = false;
static bool HVP2_gpioPackCoontPosFlywheel = false;
static bool HVP2_gpioCpLatchEnable = false;
static bool HVP2_gpioPcsEnable = false;
@ -784,7 +789,7 @@ static bool battery2_BMS_a151_SW_external_isolation = false;
static bool battery2_BMS_a156_SW_BMB_Vref_bad = false;
static bool battery2_BMS_a157_SW_HVP_HVS_Comms = false;
static bool battery2_BMS_a159_SW_HVP_ECU_Error = false;
static bool battery2_BMS_a16false_SW_DI_Open_Request = false;
static bool battery2_BMS_a161_SW_DI_Open_Request = false;
static bool battery2_BMS_a162_SW_No_Power_For_Support = false;
static bool battery2_BMS_a163_SW_Contactor_Mismatch = false;
static bool battery2_BMS_a164_SW_Uncontrolled_Regen = false;
@ -943,11 +948,14 @@ void update_values_battery() { //This function maps all the values fetched via
datalayer_extended.tesla.battery_packCtrsRequestStatus = battery_packCtrsRequestStatus;
datalayer_extended.tesla.battery_packCtrsResetRequestRequired = battery_packCtrsResetRequestRequired;
datalayer_extended.tesla.battery_dcLinkAllowedToEnergize = battery_dcLinkAllowedToEnergize;
//0x72A
memcpy(datalayer_extended.tesla.BMS_SerialNumber, BMS_SerialNumber, sizeof(BMS_SerialNumber));
//0x2B4
datalayer_extended.tesla.battery_dcdcLvBusVolt = battery_dcdcLvBusVolt;
datalayer_extended.tesla.battery_dcdcHvBusVolt = battery_dcdcHvBusVolt;
datalayer_extended.tesla.battery_dcdcLvOutputCurrent = battery_dcdcLvOutputCurrent;
//0x352
datalayer_extended.tesla.BMS352_mux = BMS352_mux;
datalayer_extended.tesla.battery_nominal_full_pack_energy = battery_nominal_full_pack_energy;
datalayer_extended.tesla.battery_nominal_full_pack_energy_m0 = battery_nominal_full_pack_energy_m0;
datalayer_extended.tesla.battery_nominal_energy_remaining = battery_nominal_energy_remaining;
@ -1033,6 +1041,9 @@ void update_values_battery() { //This function maps all the values fetched via
//0x2A4
datalayer_extended.tesla.PCS_dcdcTemp = PCS_dcdcTemp;
datalayer_extended.tesla.PCS_ambientTemp = PCS_ambientTemp;
datalayer_extended.tesla.PCS_chgPhATemp = PCS_chgPhATemp;
datalayer_extended.tesla.PCS_chgPhBTemp = PCS_chgPhBTemp;
datalayer_extended.tesla.PCS_chgPhCTemp = PCS_chgPhCTemp;
//0x2C4
datalayer_extended.tesla.PCS_dcdcMaxLvOutputCurrent = PCS_dcdcMaxLvOutputCurrent;
datalayer_extended.tesla.PCS_dcdcCurrentLimit = PCS_dcdcCurrentLimit;
@ -1180,30 +1191,40 @@ void update_values_battery() { //This function maps all the values fetched via
void handle_incoming_can_frame_battery(CAN_frame rx_frame) {
static uint8_t mux = 0;
static uint16_t temp = 0;
static bool mux0_read = false;
static bool mux1_read = false;
switch (rx_frame.ID) {
case 0x352: // 850 BMS_energyStatus newer BMS
mux = (rx_frame.data.u8[0] & 0x02); //BMS_energyStatusIndex M : 0|2@1+ (1,0) [0|0] "" X
case 0x352: // 850 BMS_energyStatus newer BMS
mux = ((rx_frame.data.u8[0]) & 0x03); //BMS_energyStatusIndex M : 0|2@1+ (1,0) [0|0] "" X
if (mux == 0) {
battery_nominal_full_pack_energy_m0 =
((rx_frame.data.u8[3] << 8) | rx_frame.data.u8[2]); //16|16@1+ (0.02,0) [0|0] "kWh"//to datalayer_extended
(((rx_frame.data.u8[3]) << 8) |
rx_frame.data.u8[2]); //16|16@1+ (0.02,0) [0|0] "kWh"//to datalayer_extended
battery_nominal_energy_remaining_m0 =
((rx_frame.data.u8[5] << 8) | rx_frame.data.u8[4]); //32|16@1+ (0.02,0) [0|0] "kWh"//to datalayer_extended
(((rx_frame.data.u8[5]) << 8) |
rx_frame.data.u8[4]); //32|16@1+ (0.02,0) [0|0] "kWh"//to datalayer_extended
battery_ideal_energy_remaining_m0 =
((rx_frame.data.u8[7] << 8) | rx_frame.data.u8[6]); //48|16@1+ (0.02,0) [0|0] "kWh"//to datalayer_extended
(((rx_frame.data.u8[7]) << 8) |
rx_frame.data.u8[6]); //48|16@1+ (0.02,0) [0|0] "kWh"//to datalayer_extended
mux0_read = true; //Set flag to true
}
if (mux == 1) {
battery_fully_charged = (rx_frame.data.u8[1] & 0x01); //15|1@1+ (1,0) [0|1]//to datalayer_extended
battery_energy_buffer_m1 =
(rx_frame.data.u8[3] | rx_frame.data.u8[2]); //16|16@1+ (0.01,0) [0|0] "kWh"//to datalayer_extended
((rx_frame.data.u8[3] << 8) | rx_frame.data.u8[2]); //16|16@1+ (0.01,0) [0|0] "kWh"//to datalayer_extended
battery_expected_energy_remaining_m1 =
(rx_frame.data.u8[5] | rx_frame.data.u8[4]); //32|16@1+ (0.02,0) [0|0] "kWh"//to datalayer_extended
((rx_frame.data.u8[5] << 8) | rx_frame.data.u8[4]); //32|16@1+ (0.02,0) [0|0] "kWh"//to datalayer_extended
battery_energy_to_charge_complete_m1 =
(rx_frame.data.u8[7] | rx_frame.data.u8[6]); //48|16@1+ (0.02,0) [0|0] "kWh"//to datalayer_extended
((rx_frame.data.u8[7] << 8) | rx_frame.data.u8[6]); //48|16@1+ (0.02,0) [0|0] "kWh"//to datalayer_extended
mux1_read = true; //Set flag to true
}
if (mux == 2) {
} // Additional information needed on this mux 2, example frame: 02 26 02 20 02 80 00 00 doesn't change
if (mux0_read && mux1_read) {
mux0_read = false;
mux1_read = false;
}
if (mux == 2) {}
// Additional information needed on this mux, example frame: 02 26 02 20 02 80 00 00 doesn't change
// older BMS <2021 without mux
battery_nominal_full_pack_energy = //BMS_nominalFullPackEnergy : 0|11@1+ (0.1,0) [0|204.6] "KWh" //((_d[1] & (0x07U)) << 8) | (_d[0] & (0xFFU));
(((rx_frame.data.u8[1] & 0x07) << 8) | (rx_frame.data.u8[0])); //Example 752 (75.2kWh)
@ -1217,9 +1238,9 @@ void handle_incoming_can_frame_battery(CAN_frame rx_frame) {
battery_energy_to_charge_complete = // BMS_energyToChargeComplete : 44|11@1+ (0.1,0) [0|204.6] "KWh"// ((_d[6] & (0x7FU)) << 4) | ((_d[5] >> 4) & (0x0FU));
(((rx_frame.data.u8[6] & 0x7F) << 4) | ((rx_frame.data.u8[5] & 0x0F) << 4)); //Example 147 * 0.1 = 14.7kWh
battery_energy_buffer = //BMS_energyBuffer : 55|8@1+ (0.1,0) [0|25.4] "KWh"// ((_d[7] & (0x7FU)) << 1) | ((_d[6] >> 7) & (0x01U));
(((rx_frame.data.u8[7] & 0x7F) << 1) | ((rx_frame.data.u8[6] & 0x01) >> 7)); //Example 1 * 0.1 = 0
(((rx_frame.data.u8[7] & 0xFE) >> 1) | ((rx_frame.data.u8[6] & 0x80) >> 7)); //Example 1 * 0.1 = 0
battery_full_charge_complete = //BMS_fullChargeComplete : 63|1@1+ (1,0) [0|1] ""//((_d[7] >> 7) & (0x01U));
((rx_frame.data.u8[7] & 0x01) >> 7);
((rx_frame.data.u8[7] >> 7) & 0x01);
break;
case 0x20A: //522 HVP_contactorState:
battery_packContNegativeState =
@ -1424,15 +1445,15 @@ void handle_incoming_can_frame_battery(CAN_frame rx_frame) {
break;
case 0x2A4: //676 PCS_thermalStatus
PCS_chgPhATemp =
((rx_frame.data.u8[1] & (0x07U)) << 8) | (rx_frame.data.u8[0] & (0xFFU)); //0|11@1- (0.1,40) [0|0] "C
(((rx_frame.data.u8[1] & 0x07) << 8) | (rx_frame.data.u8[0] & 0xFF)); //0|11@1- (0.1,40) [0|0] "C"
PCS_chgPhBTemp =
((rx_frame.data.u8[2] & (0x3FU)) << 5) | ((rx_frame.data.u8[1] >> 3) & (0x1FU)); //11|11@1- (0.1,40) [0|0] "C
PCS_chgPhCTemp =
((rx_frame.data.u8[4] & (0x07U)) << 8) | (rx_frame.data.u8[3] & (0xFFU)); //24|11@1- (0.1,40) [0|0] "C"
PCS_dcdcTemp = ((rx_frame.data.u8[5] & (0x3FU)) << 5) |
((rx_frame.data.u8[4] >> 3) & (0x1FU)); //35|11@1- (0.1,40) [0|0] "C"
(((rx_frame.data.u8[2] & 0x3F) << 5) | ((rx_frame.data.u8[1] >> 3) & 0x1F)); //11|11@1- (0.1,40) [0|0] "C"
PCS_chgPhCTemp = (((rx_frame.data.u8[2] & 0xC0) >> 6) | ((rx_frame.data.u8[3] & 0xFF) << 2) |
((rx_frame.data.u8[4] & 0x03) << 10)); //22|11@1- (0.1,40) [0|0] "C"
PCS_dcdcTemp =
(((rx_frame.data.u8[4] >> 1) & 0x1F) | ((rx_frame.data.u8[5] & 0x3F) << 5)); //33|11@1- (0.1,40) [0|0] "C"
PCS_ambientTemp =
((rx_frame.data.u8[7] & (0x07U)) << 8) | (rx_frame.data.u8[6] & (0xFFU)); //48|11@1- (0.1,40) [0|0] "C"
(((rx_frame.data.u8[7] & 0x07) << 8) | (rx_frame.data.u8[6] & 0xFF)); //44|11@1- (0.1,40) [0|0] "C"
break;
case 0x2C4: // 708 PCS_logging: not all frames are listed, just ones relating to dcdc
mux = (rx_frame.data.u8[0] & (0x1FU));
@ -1728,9 +1749,7 @@ void handle_incoming_can_frame_battery(CAN_frame rx_frame) {
break;
case 0x320: //800 BMS_alertMatrix //BMS_alertMatrix 800 BMS_alertMatrix: 8 VEH
mux = (rx_frame.data.u8[0] & (0x0F));
if (mux == 0)
;
{ //mux0
if (mux == 0) { //mux0
battery_BMS_matrixIndex = (rx_frame.data.u8[0] & (0x0F)); // 0|4@1+ (1,0) [0|0] "" X
battery_BMS_a017_SW_Brick_OV = ((rx_frame.data.u8[2] >> 4) & (0x01)); //20|1@1+ (1,0) [0|0] "" X
battery_BMS_a018_SW_Brick_UV = ((rx_frame.data.u8[2] >> 5) & (0x01)); //21|1@1+ (1,0) [0|0] "" X
@ -1830,6 +1849,27 @@ void handle_incoming_can_frame_battery(CAN_frame rx_frame) {
battery_BMS_a180_SW_ECU_reset_blocked = ((rx_frame.data.u8[7] >> 7) & (0x01U)); //63|1@1+ (1,0) [0|0] "" X
}
break;
case 0x72A: //1834 ID72ABMS_serialNumber
//Work in progress to display BMS Serial Number in ASCII: 00 54 47 33 32 31 32 30 (mux 0) .TG32120 + 01 32 30 30 33 41 48 58 (mux 1) .2003AHX = TG321202003AHX
if (rx_frame.data.u8[0] == 0x00) {
BMS_SerialNumber[0] = rx_frame.data.u8[1];
BMS_SerialNumber[1] = rx_frame.data.u8[2];
BMS_SerialNumber[2] = rx_frame.data.u8[3];
BMS_SerialNumber[3] = rx_frame.data.u8[4];
BMS_SerialNumber[4] = rx_frame.data.u8[5];
BMS_SerialNumber[5] = rx_frame.data.u8[6];
BMS_SerialNumber[6] = rx_frame.data.u8[7];
}
if (rx_frame.data.u8[0] == 0x01) {
BMS_SerialNumber[7] = rx_frame.data.u8[1];
BMS_SerialNumber[8] = rx_frame.data.u8[2];
BMS_SerialNumber[9] = rx_frame.data.u8[3];
BMS_SerialNumber[10] = rx_frame.data.u8[4];
BMS_SerialNumber[11] = rx_frame.data.u8[5];
BMS_SerialNumber[12] = rx_frame.data.u8[6];
BMS_SerialNumber[13] = rx_frame.data.u8[7];
}
break;
default:
break;
}
@ -1979,16 +2019,24 @@ void handle_incoming_can_frame_battery2(CAN_frame rx_frame) {
((rx_frame.data.u8[7] >> 3) &
(0x1FU)); //0 "PWR_UP_INIT" 1 "STANDBY" 2 "12V_SUPPORT_ACTIVE" 3 "DIS_HVBUS" 4 "PCHG_FAST_DIS_HVBUS" 5 "PCHG_SLOW_DIS_HVBUS" 6 "PCHG_DWELL_CHARGE" 7 "PCHG_DWELL_WAIT" 8 "PCHG_DI_RECOVERY_WAIT" 9 "PCHG_ACTIVE" 10 "PCHG_FLT_FAST_DIS_HVBUS" 11 "SHUTDOWN" 12 "12V_SUPPORT_FAULTED" 13 "DIS_HVBUS_FAULTED" 14 "PCHG_FAULTED" 15 "CLEAR_FAULTS" 16 "FAULTED" 17 "NUM" ;
break;
case 0x252:
//Limits
battery2_regenerative_limit =
((rx_frame.data.u8[1] << 8) | rx_frame.data.u8[0]) * 0.01; //Example 4715 * 0.01 = 47.15kW
battery2_discharge_limit =
((rx_frame.data.u8[3] << 8) | rx_frame.data.u8[2]) * 0.013; //Example 2009 * 0.013 = 26.117???
battery2_max_heat_park =
(((rx_frame.data.u8[5] & 0x03) << 8) | rx_frame.data.u8[4]) * 0.01; //Example 500 * 0.01 = 5kW
battery2_hvac_max_power =
(((rx_frame.data.u8[7] << 6) | ((rx_frame.data.u8[6] & 0xFC) >> 2))) * 0.02; //Example 1000 * 0.02 = 20kW?
case 0x252: //Limit //594 BMS_powerAvailable:
BMS2_maxRegenPower = ((rx_frame.data.u8[1] << 8) |
rx_frame.data.u8[0]); //0|16@1+ (0.01,0) [0|655.35] "kW" //Example 4715 * 0.01 = 47.15kW
BMS2_maxDischargePower =
((rx_frame.data.u8[3] << 8) |
rx_frame.data.u8[2]); //16|16@1+ (0.013,0) [0|655.35] "kW" //Example 2009 * 0.013 = 26.117???
BMS2_maxStationaryHeatPower =
(((rx_frame.data.u8[5] & 0x03) << 8) |
rx_frame.data.u8[4]); //32|10@1+ (0.01,0) [0|10.23] "kW" //Example 500 * 0.01 = 5kW
BMS2_hvacPowerBudget =
(((rx_frame.data.u8[7] << 6) |
((rx_frame.data.u8[6] & 0xFC) >> 2))); //50|10@1+ (0.02,0) [0|20.46] "kW" //Example 1000 * 0.02 = 20kW?
BMS2_notEnoughPowerForHeatPump =
((rx_frame.data.u8[5] >> 2) & (0x01U)); //BMS_notEnoughPowerForHeatPump : 42|1@1+ (1,0) [0|1] "" Receiver
BMS2_powerLimitState =
(rx_frame.data.u8[6] &
(0x01U)); //BMS_powerLimitsState : 48|1@1+ (1,0) [0|1] 0 "NOT_CALCULATED_FOR_DRIVE" 1 "CALCULATED_FOR_DRIVE"
BMS2_inverterTQF = ((rx_frame.data.u8[7] >> 4) & (0x03U));
break;
case 0x132:
//battery amps/volts
@ -2457,6 +2505,27 @@ void handle_incoming_can_frame_battery2(CAN_frame rx_frame) {
battery2_BMS_a180_SW_ECU_reset_blocked = ((rx_frame.data.u8[7] >> 7) & (0x01U)); //63|1@1+ (1,0) [0|0] "" X
}
break;
case 0x72A: //1834 ID72ABMS_serialNumber
//Work in progress to display BMS Serial Number in ASCII: 00 54 47 33 32 31 32 30 (mux 0) .TG32120 + 01 32 30 30 33 41 48 58 (mux 1) .2003AHX = TG321202003AHX
if (rx_frame.data.u8[0] == 0x00) {
BMS2_SerialNumber[0] = rx_frame.data.u8[1];
BMS2_SerialNumber[1] = rx_frame.data.u8[2];
BMS2_SerialNumber[2] = rx_frame.data.u8[3];
BMS2_SerialNumber[3] = rx_frame.data.u8[4];
BMS2_SerialNumber[4] = rx_frame.data.u8[5];
BMS2_SerialNumber[5] = rx_frame.data.u8[6];
BMS2_SerialNumber[6] = rx_frame.data.u8[7];
}
if (rx_frame.data.u8[0] == 0x01) {
BMS2_SerialNumber[7] = rx_frame.data.u8[1];
BMS2_SerialNumber[8] = rx_frame.data.u8[2];
BMS2_SerialNumber[9] = rx_frame.data.u8[3];
BMS2_SerialNumber[10] = rx_frame.data.u8[4];
BMS2_SerialNumber[11] = rx_frame.data.u8[5];
BMS2_SerialNumber[12] = rx_frame.data.u8[6];
BMS2_SerialNumber[13] = rx_frame.data.u8[7];
}
break;
default:
break;
}
@ -2869,7 +2938,7 @@ void printFaultCodesIfActive() {
printDebugIfActive(battery_BMS_a018_SW_Brick_UV, "ERROR: BMS_a018_SW_Brick_UV");
printDebugIfActive(battery_BMS_a019_SW_Module_OT, "ERROR: BMS_a019_SW_Module_OT");
printDebugIfActive(battery_BMS_a021_SW_Dr_Limits_Regulation, "ERROR: BMS_a021_SW_Dr_Limits_Regulation");
printDebugIfActive(battery_BMS_a022_SW_Over_Current, "ERROR: BMS_a022_SW_Over_Current");
//printDebugIfActive(battery_BMS_a022_SW_Over_Current, "ERROR: BMS_a022_SW_Over_Current");
printDebugIfActive(battery_BMS_a023_SW_Stack_OV, "ERROR: BMS_a023_SW_Stack_OV");
printDebugIfActive(battery_BMS_a024_SW_Islanded_Brick, "ERROR: BMS_a024_SW_Islanded_Brick");
printDebugIfActive(battery_BMS_a025_SW_PwrBalance_Anomaly, "ERROR: BMS_a025_SW_PwrBalance_Anomaly");
@ -2887,7 +2956,7 @@ void printFaultCodesIfActive() {
printDebugIfActive(battery_BMS_a046_SW_Task_Stack_Usage, "ERROR: BMS_a046_SW_Task_Stack_Usage");
printDebugIfActive(battery_BMS_a047_SW_Task_Stack_Overflow, "ERROR: BMS_a047_SW_Task_Stack_Overflow");
printDebugIfActive(battery_BMS_a048_SW_Log_Upload_Request, "ERROR: BMS_a048_SW_Log_Upload_Request");
printDebugIfActive(battery_BMS_a050_SW_Brick_Voltage_MIA, "ERROR: BMS_a050_SW_Brick_Voltage_MIA");
//printDebugIfActive(battery_BMS_a050_SW_Brick_Voltage_MIA, "ERROR: BMS_a050_SW_Brick_Voltage_MIA");
printDebugIfActive(battery_BMS_a051_SW_HVC_Vref_Bad, "ERROR: BMS_a051_SW_HVC_Vref_Bad");
printDebugIfActive(battery_BMS_a052_SW_PCS_MIA, "ERROR: BMS_a052_SW_PCS_MIA");
printDebugIfActive(battery_BMS_a053_SW_ThermalModel_Sanity, "ERROR: BMS_a053_SW_ThermalModel_Sanity");
@ -2910,10 +2979,10 @@ void printFaultCodesIfActive() {
printDebugIfActive(battery_BMS_a087_SW_Feim_Test_Blocked, "ERROR: BMS_a087_SW_Feim_Test_Blocked");
printDebugIfActive(battery_BMS_a088_SW_VcFront_MIA_InDrive, "ERROR: BMS_a088_SW_VcFront_MIA_InDrive");
printDebugIfActive(battery_BMS_a089_SW_VcFront_MIA, "ERROR: BMS_a089_SW_VcFront_MIA");
printDebugIfActive(battery_BMS_a090_SW_Gateway_MIA, "ERROR: BMS_a090_SW_Gateway_MIA");
printDebugIfActive(battery_BMS_a091_SW_ChargePort_MIA, "ERROR: BMS_a091_SW_ChargePort_MIA");
printDebugIfActive(battery_BMS_a092_SW_ChargePort_Mia_On_Hv, "ERROR: BMS_a092_SW_ChargePort_Mia_On_Hv");
printDebugIfActive(battery_BMS_a094_SW_Drive_Inverter_MIA, "ERROR: BMS_a094_SW_Drive_Inverter_MIA");
//printDebugIfActive(battery_BMS_a090_SW_Gateway_MIA, "ERROR: BMS_a090_SW_Gateway_MIA");
//printDebugIfActive(battery_BMS_a091_SW_ChargePort_MIA, "ERROR: BMS_a091_SW_ChargePort_MIA");
//printDebugIfActive(battery_BMS_a092_SW_ChargePort_Mia_On_Hv, "ERROR: BMS_a092_SW_ChargePort_Mia_On_Hv");
//printDebugIfActive(battery_BMS_a094_SW_Drive_Inverter_MIA, "ERROR: BMS_a094_SW_Drive_Inverter_MIA");
printDebugIfActive(battery_BMS_a099_SW_BMB_Communication, "ERROR: BMS_a099_SW_BMB_Communication");
printDebugIfActive(battery_BMS_a105_SW_One_Module_Tsense, "ERROR: BMS_a105_SW_One_Module_Tsense");
printDebugIfActive(battery_BMS_a106_SW_All_Module_Tsense, "ERROR: BMS_a106_SW_All_Module_Tsense");
@ -2950,7 +3019,7 @@ void printFaultCodesIfActive() {
printDebugIfActive(battery_BMS_a167_SW_FC_Partial_Weld, "ERROR: BMS_a167_SW_FC_Partial_Weld");
printDebugIfActive(battery_BMS_a168_SW_FC_Full_Weld, "ERROR: BMS_a168_SW_FC_Full_Weld");
printDebugIfActive(battery_BMS_a169_SW_FC_Pack_Weld, "ERROR: BMS_a169_SW_FC_Pack_Weld");
printDebugIfActive(battery_BMS_a170_SW_Limp_Mode, "ERROR: BMS_a170_SW_Limp_Mode");
//printDebugIfActive(battery_BMS_a170_SW_Limp_Mode, "ERROR: BMS_a170_SW_Limp_Mode");
printDebugIfActive(battery_BMS_a171_SW_Stack_Voltage_Sense, "ERROR: BMS_a171_SW_Stack_Voltage_Sense");
printDebugIfActive(battery_BMS_a174_SW_Charge_Failure, "ERROR: BMS_a174_SW_Charge_Failure");
printDebugIfActive(battery_BMS_a176_SW_GracefulPowerOff, "ERROR: BMS_a176_SW_GracefulPowerOff");
@ -3039,7 +3108,7 @@ void printFaultCodesIfActive_battery2() {
printDebugIfActive(battery2_BMS_a018_SW_Brick_UV, "ERROR: BMS_a018_SW_Brick_UV");
printDebugIfActive(battery2_BMS_a019_SW_Module_OT, "ERROR: BMS_a019_SW_Module_OT");
printDebugIfActive(battery2_BMS_a021_SW_Dr_Limits_Regulation, "ERROR: BMS_a021_SW_Dr_Limits_Regulation");
printDebugIfActive(battery2_BMS_a022_SW_Over_Current, "ERROR: BMS_a022_SW_Over_Current");
//printDebugIfActive(battery2_BMS_a022_SW_Over_Current, "ERROR: BMS_a022_SW_Over_Current");
printDebugIfActive(battery2_BMS_a023_SW_Stack_OV, "ERROR: BMS_a023_SW_Stack_OV");
printDebugIfActive(battery2_BMS_a024_SW_Islanded_Brick, "ERROR: BMS_a024_SW_Islanded_Brick");
printDebugIfActive(battery2_BMS_a025_SW_PwrBalance_Anomaly, "ERROR: BMS_a025_SW_PwrBalance_Anomaly");
@ -3057,7 +3126,7 @@ void printFaultCodesIfActive_battery2() {
printDebugIfActive(battery2_BMS_a046_SW_Task_Stack_Usage, "ERROR: BMS_a046_SW_Task_Stack_Usage");
printDebugIfActive(battery2_BMS_a047_SW_Task_Stack_Overflow, "ERROR: BMS_a047_SW_Task_Stack_Overflow");
printDebugIfActive(battery2_BMS_a048_SW_Log_Upload_Request, "ERROR: BMS_a048_SW_Log_Upload_Request");
printDebugIfActive(battery2_BMS_a050_SW_Brick_Voltage_MIA, "ERROR: BMS_a050_SW_Brick_Voltage_MIA");
//printDebugIfActive(battery2_BMS_a050_SW_Brick_Voltage_MIA, "ERROR: BMS_a050_SW_Brick_Voltage_MIA");
printDebugIfActive(battery2_BMS_a051_SW_HVC_Vref_Bad, "ERROR: BMS_a051_SW_HVC_Vref_Bad");
printDebugIfActive(battery2_BMS_a052_SW_PCS_MIA, "ERROR: BMS_a052_SW_PCS_MIA");
printDebugIfActive(battery2_BMS_a053_SW_ThermalModel_Sanity, "ERROR: BMS_a053_SW_ThermalModel_Sanity");
@ -3080,10 +3149,10 @@ void printFaultCodesIfActive_battery2() {
printDebugIfActive(battery2_BMS_a087_SW_Feim_Test_Blocked, "ERROR: BMS_a087_SW_Feim_Test_Blocked");
printDebugIfActive(battery2_BMS_a088_SW_VcFront_MIA_InDrive, "ERROR: BMS_a088_SW_VcFront_MIA_InDrive");
printDebugIfActive(battery2_BMS_a089_SW_VcFront_MIA, "ERROR: BMS_a089_SW_VcFront_MIA");
printDebugIfActive(battery2_BMS_a090_SW_Gateway_MIA, "ERROR: BMS_a090_SW_Gateway_MIA");
printDebugIfActive(battery2_BMS_a091_SW_ChargePort_MIA, "ERROR: BMS_a091_SW_ChargePort_MIA");
printDebugIfActive(battery2_BMS_a092_SW_ChargePort_Mia_On_Hv, "ERROR: BMS_a092_SW_ChargePort_Mia_On_Hv");
printDebugIfActive(battery2_BMS_a094_SW_Drive_Inverter_MIA, "ERROR: BMS_a094_SW_Drive_Inverter_MIA");
//printDebugIfActive(battery2_BMS_a090_SW_Gateway_MIA, "ERROR: BMS_a090_SW_Gateway_MIA");
//printDebugIfActive(battery2_BMS_a091_SW_ChargePort_MIA, "ERROR: BMS_a091_SW_ChargePort_MIA");
//printDebugIfActive(battery2_BMS_a092_SW_ChargePort_Mia_On_Hv, "ERROR: BMS_a092_SW_ChargePort_Mia_On_Hv");
//printDebugIfActive(battery2_BMS_a094_SW_Drive_Inverter_MIA, "ERROR: BMS_a094_SW_Drive_Inverter_MIA");
printDebugIfActive(battery2_BMS_a099_SW_BMB_Communication, "ERROR: BMS_a099_SW_BMB_Communication");
printDebugIfActive(battery2_BMS_a105_SW_One_Module_Tsense, "ERROR: BMS_a105_SW_One_Module_Tsense");
printDebugIfActive(battery2_BMS_a106_SW_All_Module_Tsense, "ERROR: BMS_a106_SW_All_Module_Tsense");
@ -3120,7 +3189,7 @@ void printFaultCodesIfActive_battery2() {
printDebugIfActive(battery2_BMS_a167_SW_FC_Partial_Weld, "ERROR: BMS_a167_SW_FC_Partial_Weld");
printDebugIfActive(battery2_BMS_a168_SW_FC_Full_Weld, "ERROR: BMS_a168_SW_FC_Full_Weld");
printDebugIfActive(battery2_BMS_a169_SW_FC_Pack_Weld, "ERROR: BMS_a169_SW_FC_Pack_Weld");
printDebugIfActive(battery2_BMS_a170_SW_Limp_Mode, "ERROR: BMS_a170_SW_Limp_Mode");
//printDebugIfActive(battery2_BMS_a170_SW_Limp_Mode, "ERROR: BMS_a170_SW_Limp_Mode");
printDebugIfActive(battery2_BMS_a171_SW_Stack_Voltage_Sense, "ERROR: BMS_a171_SW_Stack_Voltage_Sense");
printDebugIfActive(battery2_BMS_a174_SW_Charge_Failure, "ERROR: BMS_a174_SW_Charge_Failure");
printDebugIfActive(battery2_BMS_a176_SW_GracefulPowerOff, "ERROR: BMS_a176_SW_GracefulPowerOff");

View file

@ -64,6 +64,62 @@ typedef struct {
} DATALAYER_INFO_BMWIX;
typedef struct {
/** uint8_t */
/** Status isolation external, 0 not evaluated, 1 OK, 2 error active, 3 Invalid signal*/
uint8_t ST_iso_ext = 0;
/** uint8_t */
/** Status isolation external, 0 not evaluated, 1 OK, 2 error active, 3 Invalid signal*/
uint8_t ST_iso_int = 0;
/** uint8_t */
/** Status cooling valve error, 0 not evaluated, 1 OK valve closed, 2 error active valve open, 3 Invalid signal*/
uint8_t ST_valve_cooling = 0;
/** uint8_t */
/** Status interlock error, 0 not evaluated, 1 OK, 2 error active, 3 Invalid signal*/
uint8_t ST_interlock = 0;
/** uint8_t */
/** Status precharge, 0 no statement, 1 Not active closing not blocked, 2 error precharge blocked, 3 Invalid signal*/
uint8_t ST_precharge = 0;
/** uint8_t */
/** Status DC switch, 0 contactors open, 1 precharge ongoing, 2 contactors engaged, 3 Invalid signal*/
uint8_t ST_DCSW = 0;
/** uint8_t */
/** Status emergency, 0 not evaluated, 1 OK, 2 error active, 3 Invalid signal*/
uint8_t ST_EMG = 0;
/** uint8_t */
/** Status welding detection, 0 Contactors OK, 1 One contactor welded, 2 Two contactors welded, 3 Invalid signal*/
uint8_t ST_WELD = 0;
/** uint8_t */
/** Status isolation, 0 not evaluated, 1 OK, 2 error active, 3 Invalid signal*/
uint8_t ST_isolation = 0;
/** uint8_t */
/** Status cold shutoff valve, 0 OK, 1 Short circuit to GND, 2 Short circuit to 12V, 3 Line break, 6 Driver error, 12 Stuck, 13 Stuck, 15 Invalid Signal*/
uint8_t ST_cold_shutoff_valve = 0;
/** uint16_t */
/** Terminal 30 - 12V SME Supply Voltage */
uint16_t T30_Voltage = 0;
/** Status HVIL, 1 HVIL OK, 0 HVIL disconnected*/
uint8_t hvil_status = 0;
/** Min/Max Cell SOH*/
uint16_t min_soh_state = 0;
uint16_t max_soh_state = 0;
int32_t allowable_charge_amps = 0;
int32_t allowable_discharge_amps = 0;
int16_t balancing_status = 0;
int16_t battery_voltage_after_contactor = 0;
unsigned long min_cell_voltage_data_age = 0;
unsigned long max_cell_voltage_data_age = 0;
int32_t iso_safety_int_kohm = 0; //STAT_ISOWIDERSTAND_INT_WERT
int32_t iso_safety_ext_kohm = 0; //STAT_ISOWIDERSTAND_EXT_STD_WERT
int32_t iso_safety_trg_kohm = 0;
int32_t iso_safety_ext_plausible = 0; //STAT_ISOWIDERSTAND_EXT_TRG_PLAUS
int32_t iso_safety_int_plausible = 0;
int32_t iso_safety_trg_plausible = 0;
int32_t iso_safety_kohm = 0; //STAT_R_ISO_ROH_01_WERT
int32_t iso_safety_kohm_quality = 0; //STAT_R_ISO_ROH_QAL_01_INFO Quality of measurement 0-21 (higher better)
} DATALAYER_INFO_BMWPHEV;
typedef struct {
/** uint16_t */
/** SOC% raw battery value. Might not always reach 100% */
@ -232,11 +288,13 @@ typedef struct {
uint8_t battery_packCtrsRequestStatus = 0;
bool battery_packCtrsResetRequestRequired = false;
bool battery_dcLinkAllowedToEnergize = false;
uint8_t BMS_SerialNumber[15] = {0}; //stores raw HEX values for ASCII chars
uint8_t battery_beginning_of_life = 0;
uint8_t battery_battTempPct = 0;
uint16_t battery_dcdcLvBusVolt = 0;
uint16_t battery_dcdcHvBusVolt = 0;
uint16_t battery_dcdcLvOutputCurrent = 0;
bool BMS352_mux = false; // variable to store when 0x352 mux is present
uint16_t battery_nominal_full_pack_energy = 0;
uint16_t battery_nominal_full_pack_energy_m0 = 0;
uint16_t battery_nominal_energy_remaining = 0;
@ -315,6 +373,9 @@ typedef struct {
bool BMS_noFlowRequest = false;
uint16_t PCS_dcdcTemp = 0;
uint16_t PCS_ambientTemp = 0;
uint16_t PCS_chgPhATemp = 0;
uint16_t PCS_chgPhBTemp = 0;
uint16_t PCS_chgPhCTemp = 0;
uint16_t PCS_dcdcMaxLvOutputCurrent = 0;
uint16_t PCS_dcdcCurrentLimit = 0;
uint16_t PCS_dcdcLvOutputCurrentTempLimit = 0;
@ -614,6 +675,7 @@ class DataLayerExtended {
public:
DATALAYER_INFO_BOLTAMPERA boltampera;
DATALAYER_INFO_BMWIX bmwix;
DATALAYER_INFO_BMWPHEV bmwphev;
DATALAYER_INFO_BMWI3 bmwi3;
DATALAYER_INFO_BYDATTO3 bydAtto3;
DATALAYER_INFO_CELLPOWER cellpower;

View file

@ -61,6 +61,7 @@ SensorConfig sensorConfigTemplate[] = {
{"battery_current", "Battery Current", "", "A", "current"},
{"cell_max_voltage", "Cell Max Voltage", "", "V", "voltage"},
{"cell_min_voltage", "Cell Min Voltage", "", "V", "voltage"},
{"cell_voltage_delta", "Cell Voltage Delta", "", "mV", "voltage"},
{"battery_voltage", "Battery Voltage", "", "V", "voltage"},
{"total_capacity", "Battery Total Capacity", "", "Wh", "energy"},
{"remaining_capacity", "Battery Remaining Capacity (scaled)", "", "Wh", "energy"},
@ -144,6 +145,8 @@ void set_battery_attributes(JsonDocument& doc, const DATALAYER_BATTERY_TYPE& bat
if (battery.info.number_of_cells != 0u && battery.status.cell_voltages_mV[battery.info.number_of_cells - 1] != 0u) {
doc["cell_max_voltage" + suffix] = ((float)battery.status.cell_max_voltage_mV) / 1000.0;
doc["cell_min_voltage" + suffix] = ((float)battery.status.cell_min_voltage_mV) / 1000.0;
doc["cell_voltage_delta" + suffix] =
((float)battery.status.cell_max_voltage_mV) - ((float)battery.status.cell_min_voltage_mV);
}
doc["total_capacity" + suffix] = ((float)battery.info.total_capacity_Wh);
doc["remaining_capacity_real" + suffix] = ((float)battery.status.remaining_capacity_Wh);

View file

@ -14,7 +14,6 @@ String advanced_battery_processor(const String& var) {
"cursor: pointer; border-radius: 10px; }";
content += "button:hover { background-color: #3A4A52; }";
content += "</style>";
content += "<button onclick='goToMainPage()'>Back to main page</button>";
// Start a new block with a specific background color
@ -97,6 +96,123 @@ String advanced_battery_processor(const String& var) {
content += "<h4>Pyro Status PSS6: " + String((pyroText[datalayer_extended.bmwix.pyro_status_pss6])) + "</h4>";
#endif //BMW_IX_BATTERY
#ifdef BMW_PHEV_BATTERY
content +=
"<h4>Battery Voltage after Contactor: " + String(datalayer_extended.bmwphev.battery_voltage_after_contactor) +
" dV</h4>";
content += "<h4>Allowed Discharge Power: " + String(datalayer.battery.status.max_discharge_power_W) + " W</h4>";
content += "<h4>Allowed Charge Power: " + String(datalayer.battery.status.max_charge_power_W) + " W</h4>";
static const char* balanceText[5] = {"0 Balancing Inactive - Balancing not needed", "1 Balancing Active",
"2 Balancing Inactive - Cells not in rest break wait 10mins",
"3 Balancing Inactive", "4 Unknown"};
content += "<h4>Balancing: " + String((balanceText[datalayer_extended.bmwphev.balancing_status])) + "</h4>";
static const char* pyroText[5] = {"0 Value Invalid", "1 Successfully Blown", "2 Disconnected",
"3 Not Activated - Pyro Intact", "4 Unknown"};
static const char* statusText[16] = {
"Not evaluated", "OK", "Error!", "Invalid signal", "", "", "", "", "", "", "", "", "", "", "", ""};
content += "<h4>Interlock: " + String(statusText[datalayer_extended.bmwphev.ST_interlock]) + "</h4>";
content += "<h4>Isolation external: " + String(statusText[datalayer_extended.bmwphev.ST_iso_ext]) + "</h4>";
content += "<h4>Isolation internal: " + String(statusText[datalayer_extended.bmwphev.ST_iso_int]) + "</h4>";
content += "<h4>Isolation: " + String(statusText[datalayer_extended.bmwphev.ST_isolation]) + "</h4>";
content += "<h4>Cooling valve: " + String(statusText[datalayer_extended.bmwphev.ST_valve_cooling]) + "</h4>";
content += "<h4>Emergency: " + String(statusText[datalayer_extended.bmwphev.ST_EMG]) + "</h4>";
static const char* prechargeText[16] = {"Not evaluated",
"Not active, closing not blocked",
"Error precharge blocked",
"Invalid signal",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
""};
content += "<h4>Precharge: " + String(prechargeText[datalayer_extended.bmwphev.ST_precharge]) +
"</h4>"; //Still unclear of enum
static const char* DCSWText[16] = {"Contactors open",
"Precharge ongoing",
"Contactors engaged",
"Invalid signal",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
""};
content += "<h4>Contactor status: " + String(DCSWText[datalayer_extended.bmwphev.ST_DCSW]) + "</h4>";
static const char* contText[16] = {"Contactors OK",
"One contactor welded!",
"Two contactors welded!",
"Invalid signal",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
""};
content += "<h4>Contactor weld: " + String(contText[datalayer_extended.bmwphev.ST_WELD]) + "</h4>";
static const char* valveText[16] = {"OK",
"Short circuit to GND",
"Short circuit to 12V",
"Line break",
"",
"",
"Driver error",
"",
"",
"",
"",
"",
"Stuck",
"Stuck",
"",
"Invalid Signal"};
content +=
"<h4>Cold shutoff valve: " + String(valveText[datalayer_extended.bmwphev.ST_cold_shutoff_valve]) + "</h4>";
content +=
"<h4>Min Cell Voltage Data Age: " + String(datalayer_extended.bmwphev.min_cell_voltage_data_age) + " ms</h4>";
content +=
"<h4>Max Cell Voltage Data Age: " + String(datalayer_extended.bmwphev.max_cell_voltage_data_age) + " ms</h4>";
content += "<h4>Max Design Voltage: " + String(datalayer.battery.info.max_design_voltage_dV) + " dV</h4>";
content += "<h4>Min Design Voltage: " + String(datalayer.battery.info.min_design_voltage_dV) + " dV</h4>";
content += "<h4>BMS Allowed Charge Amps: " + String(datalayer_extended.bmwphev.allowable_charge_amps) + " A</h4>";
content +=
"<h4>BMS Allowed Disharge Amps: " + String(datalayer_extended.bmwphev.allowable_discharge_amps) + " A</h4>";
content += "<h4>Detected Cell Count: " + String(datalayer.battery.info.number_of_cells) + "</h4>";
content += "<h4>iso_safety_int_kohm: " + String(datalayer_extended.bmwphev.iso_safety_int_kohm) + "</h4>";
content += "<h4>iso_safety_ext_kohm: " + String(datalayer_extended.bmwphev.iso_safety_ext_kohm) + "</h4>";
content += "<h4>iso_safety_trg_kohm: " + String(datalayer_extended.bmwphev.iso_safety_trg_kohm) + "</h4>";
content += "<h4>iso_safety_ext_plausible: " + String(datalayer_extended.bmwphev.iso_safety_ext_plausible) + "</h4>";
content += "<h4>iso_safety_int_plausible: " + String(datalayer_extended.bmwphev.iso_safety_int_plausible) + "</h4>";
content += "<h4>iso_safety_trg_plausible: " + String(datalayer_extended.bmwphev.iso_safety_trg_plausible) + "</h4>";
content += "<h4>iso_safety_kohm: " + String(datalayer_extended.bmwphev.iso_safety_kohm) + "</h4>";
content += "<h4>iso_safety_kohm_quality: " + String(datalayer_extended.bmwphev.iso_safety_kohm_quality) + "</h4>";
content += "<br>";
content += "<h4>Todo";
content += "<br>";
content += "<h4>Max Cell Design Voltage: " + String(datalayer.battery.info.max_cell_voltage_mV) + " mV</h4>";
content += "<h4>Min Cell Design Voltage: " + String(datalayer.battery.info.min_cell_voltage_mV) + " mV</h4>";
content += "<h4>T30 Terminal Voltage: " + String(datalayer_extended.bmwphev.T30_Voltage) + " mV</h4>";
content += "<br>";
#endif //BMW_PHEV_BATTERY
#ifdef BMW_I3_BATTERY
content += "<h4>SOC raw: " + String(datalayer_extended.bmwi3.SOC_raw) + "</h4>";
content += "<h4>SOC dash: " + String(datalayer_extended.bmwi3.SOC_dash) + "</h4>";
@ -379,13 +495,16 @@ String advanced_battery_processor(const String& var) {
float soc_ui = static_cast<float>(datalayer_extended.tesla.battery_soc_ui) * 0.1;
float BrickVoltageMax = static_cast<float>(datalayer_extended.tesla.battery_BrickVoltageMax) * 0.002;
float BrickVoltageMin = static_cast<float>(datalayer_extended.tesla.battery_BrickVoltageMin) * 0.002;
float BrickModelTMax = static_cast<float>(datalayer_extended.tesla.battery_BrickTempMinNum) * 0.5 - 40;
float BrickModelTMax = static_cast<float>(datalayer_extended.tesla.battery_BrickModelTMax) * 0.5 - 40;
float BrickModelTMin = static_cast<float>(datalayer_extended.tesla.battery_BrickModelTMin) * 0.5 - 40;
float isolationResistance = static_cast<float>(datalayer_extended.tesla.battery_BMS_isolationResistance) * 10;
float PCS_dcdcMaxOutputCurrentAllowed =
static_cast<float>(datalayer_extended.tesla.battery_PCS_dcdcMaxOutputCurrentAllowed) * 0.1;
float PCS_dcdcTemp = static_cast<float>(datalayer_extended.tesla.PCS_dcdcTemp) * 0.1 - 40;
float PCS_ambientTemp = static_cast<float>(datalayer_extended.tesla.PCS_ambientTemp) * 0.1 - 40;
float PCS_dcdcTemp = static_cast<float>(datalayer_extended.tesla.PCS_dcdcTemp) * 0.1 + 40;
float PCS_ambientTemp = static_cast<float>(datalayer_extended.tesla.PCS_ambientTemp) * 0.1 + 40;
float PCS_chgPhATemp = static_cast<float>(datalayer_extended.tesla.PCS_chgPhATemp) * 0.1 + 40;
float PCS_chgPhBTemp = static_cast<float>(datalayer_extended.tesla.PCS_chgPhBTemp) * 0.1 + 40;
float PCS_chgPhCTemp = static_cast<float>(datalayer_extended.tesla.PCS_chgPhCTemp) * 0.1 + 40;
float BMS_maxRegenPower = static_cast<float>(datalayer_extended.tesla.BMS_maxRegenPower) * 0.01;
float BMS_maxDischargePower = static_cast<float>(datalayer_extended.tesla.BMS_maxDischargePower) * 0.013;
float BMS_maxStationaryHeatPower = static_cast<float>(datalayer_extended.tesla.BMS_maxStationaryHeatPower) * 0.01;
@ -518,37 +637,118 @@ String advanced_battery_processor(const String& var) {
"<h4>Negative contactor: " + String(contactorState[datalayer_extended.tesla.packContNegativeState]) + "</h4>";
content +=
"<h4>Positive contactor: " + String(contactorState[datalayer_extended.tesla.packContPositiveState]) + "</h4>";
content +=
"<h4>Closing allowed?: " + String(noYes[datalayer_extended.tesla.packCtrsClosingAllowed]) + "</h4>"; //bool
content +=
"<h4>Pyrotest in Progress: " + String(noYes[datalayer_extended.tesla.pyroTestInProgress]) + "</h4>"; //bool
content += "<h4>Closing allowed?: " + String(noYes[datalayer_extended.tesla.packCtrsClosingAllowed]) + "</h4>";
content += "<h4>Pyrotest in Progress: " + String(noYes[datalayer_extended.tesla.pyroTestInProgress]) + "</h4>";
content += "<h4>Contactors Open Now Requested: " +
String(noYes[datalayer_extended.tesla.battery_packCtrsOpenNowRequested]) + "</h4>"; //bool
String(noYes[datalayer_extended.tesla.battery_packCtrsOpenNowRequested]) + "</h4>";
content +=
"<h4>Contactors Open Requested: " + String(noYes[datalayer_extended.tesla.battery_packCtrsOpenRequested]) +
"</h4>"; //bool
"</h4>";
content += "<h4>Contactors Request Status: " +
String(HVP_contactor[datalayer_extended.tesla.battery_packCtrsRequestStatus]) + "</h4>";
content += "<h4>Contactors Reset Request Required: " +
String(noYes[datalayer_extended.tesla.battery_packCtrsResetRequestRequired]) + "</h4>"; //bool
String(noYes[datalayer_extended.tesla.battery_packCtrsResetRequestRequired]) + "</h4>";
content +=
"<h4>DC Link Allowed to Energize: " + String(noYes[datalayer_extended.tesla.battery_dcLinkAllowedToEnergize]) +
"</h4>"; //bool
"</h4>";
char readableSerialNumber[15]; // One extra space for null terminator
memcpy(readableSerialNumber, datalayer_extended.tesla.BMS_SerialNumber,
sizeof(datalayer_extended.tesla.BMS_SerialNumber));
readableSerialNumber[14] = '\0'; // Null terminate the string
content += "<h4>BMS Serial number: " + String(readableSerialNumber) + "</h4>";
// Comment what data you would like to dislay, order can be changed.
//0x352 850 BMS_energyStatus
if (datalayer_extended.tesla.BMS352_mux == false) {
content += "<h3>BMS 0x352 w/o mux</h3>"; //if using older BMS <2021 and comment 0x352 without MUX
content += "<h4>Calculated SOH: " + String(nominal_full_pack_energy * 100 / beginning_of_life) + "</h4>";
content += "<h4>Nominal Full Pack Energy: " + String(nominal_full_pack_energy) + " KWh</h4>";
content += "<h4>Nominal Energy Remaining: " + String(nominal_energy_remaining) + " KWh</h4>";
content += "<h4>Ideal Energy Remaining: " + String(ideal_energy_remaining) + " KWh</h4>";
content += "<h4>Energy to Charge Complete: " + String(energy_to_charge_complete) + " KWh</h4>";
content += "<h4>Energy Buffer: " + String(energy_buffer) + " KWh</h4>";
content += "<h4>Full Charge Complete: " + String(noYes[datalayer_extended.tesla.battery_full_charge_complete]) +
"</h4>"; //bool
}
//0x352 850 BMS_energyStatus
if (datalayer_extended.tesla.BMS352_mux == true) {
content += "<h3>BMS 0x352 w/ mux</h3>"; //if using newer BMS >2021 and comment 0x352 with MUX
content += "<h4>Calculated SOH: " + String(nominal_full_pack_energy_m0 * 100 / beginning_of_life) + "</h4>";
content += "<h4>Nominal Full Pack Energy: " + String(nominal_full_pack_energy_m0) + " KWh</h4>";
content += "<h4>Nominal Energy Remaining: " + String(nominal_energy_remaining_m0) + " KWh</h4>";
content += "<h4>Ideal Energy Remaining: " + String(ideal_energy_remaining_m0) + " KWh</h4>";
content += "<h4>Energy to Charge Complete: " + String(energy_to_charge_complete_m1) + " KWh</h4>";
content += "<h4>Energy Buffer: " + String(energy_buffer_m1) + " KWh</h4>";
content += "<h4>Expected Energy Remaining: " + String(expected_energy_remaining_m1) + " KWh</h4>";
content += "<h4>Fully Charged: " + String(noYes[datalayer_extended.tesla.battery_fully_charged]) + "</h4>";
}
//0x3D2 978 BMS_kwhCounter
content += "<h4>Total Discharge: " + String(total_discharge) + " KWh</h4>";
content += "<h4>Total Charge: " + String(total_charge) + " KWh</h4>";
//0x292 658 BMS_socStates
content += "<h4>Battery Beginning of Life: " + String(beginning_of_life) + " KWh</h4>";
content += "<h4>BattTempPct: " + String(battTempPct) + " </h4>";
content += "<h4>Battery SOC UI: " + String(soc_ui) + " </h4>";
content += "<h4>Battery SOC Ave: " + String(soc_ave) + " </h4>";
content += "<h4>Battery SOC Max: " + String(soc_max) + " </h4>";
content += "<h4>Battery SOC Min: " + String(soc_min) + " </h4>";
content += "<h4>Battery SOC UI: " + String(soc_ui) + " </h4>";
content += "<h4>Battery Temp Percent: " + String(battTempPct) + " </h4>";
//0x2B4 PCS_dcdcRailStatus
content += "<h4>PCS Lv Output: " + String(dcdcLvOutputCurrent) + " A</h4>";
content += "<h4>PCS Lv Bus: " + String(dcdcLvBusVolt) + " V</h4>";
content += "<h4>PCS Hv Bus: " + String(dcdcHvBusVolt) + " V</h4>";
content += "<h4>PCS Lv Output: " + String(dcdcLvOutputCurrent) + " A</h4>";
//0x392 BMS_packConfig
//content += "<h4>packConfigMultiplexer: " + String(datalayer_extended.tesla.battery_packConfigMultiplexer) + "</h4>"; // Not giving useable data
//content += "<h4>moduleType: " + String(datalayer_extended.tesla.battery_moduleType) + "</h4>"; // Not giving useable data
//content += "<h4>reserveConfig: " + String(datalayer_extended.tesla.battery_reservedConfig) + "</h4>"; // Not giving useable data
content += "<h4>Battery Pack Mass: " + String(packMass) + " KG</h4>";
content += "<h4>Platform Max Bus Voltage: " + String(platformMaxBusVoltage) + " V</h4>";
//0x2D2 722 BMSVAlimits
content += "<h4>BMS Min Voltage: " + String(bms_min_voltage) + " V</h4>";
content += "<h4>BMS Max Voltage: " + String(bms_max_voltage) + " V</h4>";
content += "<h4>Max Charge Current: " + String(max_charge_current) + " A</h4>";
content += "<h4>Max Discharge Current: " + String(max_discharge_current) + " A</h4>";
//0x332 818 BMS_bmbMinMax
content += "<h4>Brick Voltage Max: " + String(BrickVoltageMax) + " V</h4>";
content += "<h4>Brick Voltage Min: " + String(BrickVoltageMin) + " V</h4>";
content += "<h4>Brick Temp Max Num: " + String(datalayer_extended.tesla.battery_BrickTempMaxNum) + " </h4>";
content += "<h4>Brick Temp Min Num: " + String(datalayer_extended.tesla.battery_BrickTempMinNum) + " </h4>";
//content += "<h4>Brick Model Temp Max: " + String(BrickModelTMax) + " C</h4>";// Not giving useable data
//content += "<h4>Brick Model Temp Min: " + String(BrickModelTMin) + " C</h4>";// Not giving useable data
//0x2A4 676 PCS_thermalStatus
content += "<h4>PCS dcdc Temp: " + String(PCS_dcdcTemp) + " DegC</h4>";
content += "<h4>PCS Ambient Temp: " + String(PCS_ambientTemp) + " DegC</h4>";
content += "<h4>PCS dcdc Temp: " + String(PCS_dcdcTemp, 2) + " DegC</h4>";
content += "<h4>PCS Ambient Temp: " + String(PCS_ambientTemp, 2) + " DegC</h4>";
content += "<h4>PCS Chg PhA Temp: " + String(PCS_chgPhATemp, 2) + " DegC</h4>";
content += "<h4>PCS Chg PhB Temp: " + String(PCS_chgPhBTemp, 2) + " DegC</h4>";
content += "<h4>PCS Chg PhC Temp: " + String(PCS_chgPhCTemp, 2) + " DegC</h4>";
//0x252 594 BMS_powerAvailable
content += "<h4>Max Regen Power: " + String(BMS_maxRegenPower) + " KW</h4>";
content += "<h4>Max Discharge Power: " + String(BMS_maxDischargePower) + " KW</h4>";
//content += "<h4>Max Stationary Heat Power: " + String(BMS_maxStationaryHeatPower) + " KWh</h4>"; // Not giving useable data
//content += "<h4>HVAC Power Budget: " + String(BMS_hvacPowerBudget) + " KW</h4>"; // Not giving useable data
//content += "<h4>Not Enough Power For Heat Pump: " + String(falseTrue[datalayer_extended.tesla.BMS_notEnoughPowerForHeatPump]) + "</h4>"; // Not giving useable data
content +=
"<h4>Power Limit State: " + String(BMS_powerLimitState[datalayer_extended.tesla.BMS_powerLimitState]) + "</h4>";
//content += "<h4>Inverter TQF: " + String(datalayer_extended.tesla.BMS_inverterTQF) + "</h4>"; // Not giving useable data
//0x212 530 BMS_status
content += "<h4>Isolation Resistance: " + String(isolationResistance) + " kOhms</h4>";
content +=
"<h4>BMS Contactor State: " + String(BMS_contactorState[datalayer_extended.tesla.battery_BMS_contactorState]) +
"</h4>";
content += "<h4>BMS State: " + String(BMS_state[datalayer_extended.tesla.battery_BMS_state]) + "</h4>";
content += "<h4>BMS HV State: " + String(BMS_hvState[datalayer_extended.tesla.battery_BMS_hvState]) + "</h4>";
content += "<h4>BMS UI Charge Status: " + String(BMS_uiChargeStatus[datalayer_extended.tesla.battery_BMS_hvState]) +
"</h4>";
content +=
"<h4>BMS PCS PWM Enabled: " + String(Fault[datalayer_extended.tesla.battery_BMS_pcsPwmEnabled]) + "</h4>";
//0x312 786 BMS_thermalStatus
content += "<h4>Power Dissipation: " + String(BMS_powerDissipation) + " kW</h4>";
content += "<h4>Flow Request: " + String(BMS_flowRequest) + " LPM</h4>";
content += "<h4>Inlet Active Cool Target Temp: " + String(BMS_inletActiveCoolTargetT) + " DegC</h4>";
content += "<h4>Inlet Passive Target Temp: " + String(BMS_inletPassiveTargetT) + " DegC</h4>";
content += "<h4>Inlet Active Heat Target Temp: " + String(BMS_inletActiveHeatTargetT) + " DegC</h4>";
content += "<h4>Pack Temp Min: " + String(BMS_packTMin) + " DegC</h4>";
content += "<h4>Pack Temp Max: " + String(BMS_packTMax) + " DegC</h4>";
content += "<h4>PCS No Flow Request: " + String(Fault[datalayer_extended.tesla.BMS_pcsNoFlowRequest]) + "</h4>";
content += "<h4>BMS No Flow Request: " + String(Fault[datalayer_extended.tesla.BMS_noFlowRequest]) + "</h4>";
//0x224 548 PCS_dcdcStatus
content +=
"<h4>Precharge Status: " + String(PCS_dcdcStatus[datalayer_extended.tesla.battery_PCS_dcdcPrechargeStatus]) +
@ -562,23 +762,23 @@ String advanced_battery_processor(const String& var) {
"<h4>Main State: " + String(PCS_dcdcMainState[datalayer_extended.tesla.battery_PCS_dcdcMainState]) + "</h4>";
content +=
"<h4>Sub State: " + String(PCS_dcdcSubState[datalayer_extended.tesla.battery_PCS_dcdcSubState]) + "</h4>";
content += "<h4>PCS Faulted: " + String(Fault[datalayer_extended.tesla.battery_PCS_dcdcFaulted]) + "</h4>"; //bool
content += "<h4>Output Is Limited: " + String(Fault[datalayer_extended.tesla.battery_PCS_dcdcOutputIsLimited]) +
"</h4>"; //bool
content += "<h4>PCS Faulted: " + String(Fault[datalayer_extended.tesla.battery_PCS_dcdcFaulted]) + "</h4>";
content +=
"<h4>Output Is Limited: " + String(Fault[datalayer_extended.tesla.battery_PCS_dcdcOutputIsLimited]) + "</h4>";
content += "<h4>Max Output Current Allowed: " + String(PCS_dcdcMaxOutputCurrentAllowed) + " A</h4>";
content += "<h4>Precharge Rty Cnt: " + String(falseTrue[datalayer_extended.tesla.battery_PCS_dcdcPrechargeRtyCnt]) +
"</h4>"; //bool
"</h4>";
content +=
"<h4>12V Support Rty Cnt: " + String(falseTrue[datalayer_extended.tesla.battery_PCS_dcdc12VSupportRtyCnt]) +
"</h4>"; // bool
"</h4>";
content += "<h4>Discharge Rty Cnt: " + String(falseTrue[datalayer_extended.tesla.battery_PCS_dcdcDischargeRtyCnt]) +
"</h4>"; //bool
content += "<h4>PWM Enable Line: " + String(Fault[datalayer_extended.tesla.battery_PCS_dcdcPwmEnableLine]) +
"</h4>"; //bool
"</h4>";
content +=
"<h4>PWM Enable Line: " + String(Fault[datalayer_extended.tesla.battery_PCS_dcdcPwmEnableLine]) + "</h4>";
content += "<h4>Supporting Fixed LV Target: " +
String(Fault[datalayer_extended.tesla.battery_PCS_dcdcSupportingFixedLvTarget]) + "</h4>"; //bool
String(Fault[datalayer_extended.tesla.battery_PCS_dcdcSupportingFixedLvTarget]) + "</h4>";
content += "<h4>Precharge Restart Cnt: " +
String(falseTrue[datalayer_extended.tesla.battery_PCS_dcdcPrechargeRestartCnt]) + "</h4>"; //bool
String(falseTrue[datalayer_extended.tesla.battery_PCS_dcdcPrechargeRestartCnt]) + "</h4>";
content += "<h4>Initial Precharge Substate: " +
String(PCS_dcdcSubState[datalayer_extended.tesla.battery_PCS_dcdcInitialPrechargeSubState]) + "</h4>";
//0x2C4 708 PCS_logging
@ -602,163 +802,74 @@ String advanced_battery_processor(const String& var) {
content += "<h4>PCS_dcdcIntervalMinLvBusVolt: " + String(PCS_dcdcIntervalMinLvBusVolt) + " V</h4>";
content += "<h4>PCS_dcdcIntervalMinLvOutputCurr: " + String(PCS_dcdcIntervalMinLvOutputCurr) + " A</h4>";
content += "<h4>PCS_dcdc12vSupportLifetimekWh: " + String(PCS_dcdc12vSupportLifetimekWh) + " kWh</h4>";
//0x3D2 978 BMS_kwhCounter
content += "<h4>Total Discharge: " + String(total_discharge) + " KWh</h4>";
content += "<h4>Total Charge: " + String(total_charge) + " KWh</h4>";
//0x212 530 BMS_status
content += "<h4>Isolation Resistance: " + String(isolationResistance) + " kOhms</h4>";
content +=
"<h4>BMS Contactor State: " + String(BMS_contactorState[datalayer_extended.tesla.battery_BMS_contactorState]) +
"</h4>";
content += "<h4>BMS State: " + String(BMS_state[datalayer_extended.tesla.battery_BMS_state]) + "</h4>";
content += "<h4>BMS HV State: " + String(BMS_hvState[datalayer_extended.tesla.battery_BMS_hvState]) + "</h4>";
content += "<h4>BMS UI Charge Status: " + String(BMS_uiChargeStatus[datalayer_extended.tesla.battery_BMS_hvState]) +
"</h4>";
content += "<h4>BMS PCS PWM Enabled: " + String(Fault[datalayer_extended.tesla.battery_BMS_pcsPwmEnabled]) +
"</h4>"; //bool
//0x352 850 BMS_energyStatus
content += "<h3>Early BMS 0x352:</h3>"; //if using older BMS <2021 and comment 0x352 without MUX
content += "<h4>Calculated SOH: " + String(nominal_full_pack_energy * 100 / beginning_of_life) + "</h4>";
content += "<h4>Nominal Full Pack Energy: " + String(nominal_full_pack_energy) + " KWh</h4>";
content += "<h4>Nominal Energy Remaining: " + String(nominal_energy_remaining) + " KWh</h4>";
content += "<h4>Ideal Energy Remaining: " + String(ideal_energy_remaining) + " KWh</h4>";
content += "<h4>Energy to Charge Complete: " + String(energy_to_charge_complete) + " KWh</h4>";
content += "<h4>Energy Buffer: " + String(energy_buffer) + " KWh</h4>";
content += "<h4>Full Charge Complete: " + String(noYes[datalayer_extended.tesla.battery_full_charge_complete]) +
"</h4>"; //bool
//0x352 850 BMS_energyStatus
content += "<h3>Late BMS 0x352 with Mux:</h3>"; //if using newer BMS >2021 and comment 0x352 with MUX
content += "<h4>Calculated SOH: " + String(nominal_full_pack_energy_m0 * 100 / beginning_of_life) + "</h4>";
content += "<h4>Nominal Full Pack Energy: " + String(nominal_full_pack_energy_m0) + " KWh</h4>";
content += "<h4>Nominal Energy Remaining: " + String(nominal_energy_remaining_m0) + " KWh</h4>";
content += "<h4>Ideal Energy Remaining: " + String(ideal_energy_remaining_m0) + " KWh</h4>";
content += "<h4>Energy to Charge Complete: " + String(energy_to_charge_complete_m1) + " KWh</h4>";
content += "<h4>Energy Buffer: " + String(energy_buffer_m1) + " KWh</h4>";
content += "<h4>Expected Energy Remaining: " + String(expected_energy_remaining_m1) + " KWh</h4>";
content += "<h4>Fully Charged: " + String(noYes[datalayer_extended.tesla.battery_fully_charged]) + "</h4>"; //bool
//0x392 BMS_packConfig
//content += "<h4>packConfigMultiplexer: " + String(datalayer_extended.tesla.battery_packConfigMultiplexer) + "</h4>";
//content += "<h4>moduleType: " + String(datalayer_extended.tesla.battery_moduleType) + "</h4>";
//content += "<h4>reserveConfig: " + String(datalayer_extended.tesla.battery_reservedConfig) + "</h4>";
content += "<h4>Battery Pack Mass: " + String(packMass) + " KG</h4>";
content += "<h4>Platform Max Bus Voltage: " + String(platformMaxBusVoltage) + " V</h4>";
//0x2D2 722 BMSVAlimits
content += "<h4>BMS Min Voltage: " + String(bms_min_voltage) + " V</h4>";
content += "<h4>BMS Max Voltage: " + String(bms_max_voltage) + " V</h4>";
content += "<h4>Max Charge Current: " + String(max_charge_current) + " A</h4>";
content += "<h4>Max Discharge Current: " + String(max_discharge_current) + " A</h4>";
//0x332 818 BMS_bmbMinMax
content += "<h4>Brick Voltage Max: " + String(BrickVoltageMax) + " V</h4>";
content += "<h4>Brick Voltage Min: " + String(BrickVoltageMin) + " V</h4>";
content += "<h4>Brick Temp Max Num: " + String(datalayer_extended.tesla.battery_BrickTempMaxNum) + " </h4>";
content += "<h4>Brick Temp Min Num: " + String(datalayer_extended.tesla.battery_BrickTempMinNum) + " </h4>";
content += "<h4>Brick Model Temp Max: " + String(BrickModelTMax) + " C</h4>";
content += "<h4>Brick Model Temp Min: " + String(BrickModelTMin) + " C</h4>";
//0x252 594 BMS_powerAvailable
content += "<h4>Max Regen Power: " + String(BMS_maxRegenPower) + " KW</h4>";
content += "<h4>Max Discharge Power: " + String(BMS_maxDischargePower) + " KW</h4>";
content += "<h4>Max Stationary Heat Power: " + String(BMS_maxStationaryHeatPower) + " KWh</h4>";
content += "<h4>HVAC Power Budget: " + String(BMS_hvacPowerBudget) + " KW</h4>";
content += "<h4>Not Enough Power For Heat Pump: " +
String(falseTrue[datalayer_extended.tesla.BMS_notEnoughPowerForHeatPump]) + "</h4>"; //bool
content +=
"<h4>Power Limit State: " + String(BMS_powerLimitState[datalayer_extended.tesla.BMS_powerLimitState]) + "</h4>";
content += "<h4>Inverter TQF: " + String(datalayer_extended.tesla.BMS_inverterTQF) + "</h4>";
//0x312 786 BMS_thermalStatus
content += "<h4>Power Dissipation: " + String(BMS_powerDissipation) + " kW</h4>";
content += "<h4>Flow Request: " + String(BMS_flowRequest) + " LPM</h4>";
content += "<h4>Inlet Active Cool Target Temp: " + String(BMS_inletActiveCoolTargetT) + " DegC</h4>";
content += "<h4>Inlet Passive Target Temp: " + String(BMS_inletPassiveTargetT) + " DegC</h4>";
content += "<h4>Inlet Active Heat Target Temp: " + String(BMS_inletActiveHeatTargetT) + " DegC</h4>";
content += "<h4>Pack Temp Min: " + String(BMS_packTMin) + " DegC</h4>";
content += "<h4>Pack Temp Max: " + String(BMS_packTMax) + " DegC</h4>";
content +=
"<h4>PCS No Flow Request: " + String(Fault[datalayer_extended.tesla.BMS_pcsNoFlowRequest]) + "</h4>"; //bool
content +=
"<h4>BMS No Flow Request: " + String(Fault[datalayer_extended.tesla.BMS_noFlowRequest]) + "</h4>"; //bool
//0x7AA 1962 HVP_debugMessage
content += "<h4>HVP_gpioPassivePyroDepl: " + String(Fault[datalayer_extended.tesla.HVP_gpioPassivePyroDepl]) +
"</h4>"; //bool
content += "<h4>HVP_gpioPyroIsoEn: " + String(Fault[datalayer_extended.tesla.HVP_gpioPyroIsoEn]) + "</h4>"; //bool
content += "<h4>HVP_gpioCpFaultIn: " + String(Fault[datalayer_extended.tesla.HVP_gpioCpFaultIn]) + "</h4>"; //bool
content += "<h4>HVP_gpioPackContPowerEn: " + String(Fault[datalayer_extended.tesla.HVP_gpioPackContPowerEn]) +
"</h4>"; //bool
content +=
"<h4>HVP_gpioHvCablesOk: " + String(Fault[datalayer_extended.tesla.HVP_gpioHvCablesOk]) + "</h4>"; //bool
content +=
"<h4>HVP_gpioHvpSelfEnable: " + String(Fault[datalayer_extended.tesla.HVP_gpioHvpSelfEnable]) + "</h4>"; //bool
content += "<h4>HVP_gpioLed: " + String(Fault[datalayer_extended.tesla.HVP_gpioLed]) + "</h4>"; //bool
content +=
"<h4>HVP_gpioCrashSignal: " + String(Fault[datalayer_extended.tesla.HVP_gpioCrashSignal]) + "</h4>"; //bool
content += "<h4>HVP_gpioShuntDataReady: " + String(Fault[datalayer_extended.tesla.HVP_gpioShuntDataReady]) +
"</h4>"; //bool
content +=
"<h4>HVP_gpioFcContPosAux: " + String(Fault[datalayer_extended.tesla.HVP_gpioFcContPosAux]) + "</h4>"; //bool
content +=
"<h4>HVP_gpioFcContNegAux: " + String(Fault[datalayer_extended.tesla.HVP_gpioFcContNegAux]) + "</h4>"; //bool
content += "<h4>HVP_gpioBmsEout: " + String(Fault[datalayer_extended.tesla.HVP_gpioBmsEout]) + "</h4>"; //bool
content +=
"<h4>HVP_gpioCpFaultOut: " + String(Fault[datalayer_extended.tesla.HVP_gpioCpFaultOut]) + "</h4>"; //bool
content += "<h4>HVP_gpioPyroPor: " + String(Fault[datalayer_extended.tesla.HVP_gpioPyroPor]) + "</h4>"; //bool
content += "<h4>HVP_gpioShuntEn: " + String(Fault[datalayer_extended.tesla.HVP_gpioShuntEn]) + "</h4>"; //bool
content += "<h4>HVP_gpioHvpVerEn: " + String(Fault[datalayer_extended.tesla.HVP_gpioHvpVerEn]) + "</h4>"; //bool
content +=
"<h4>HVP_gpioPackCoontPosFlywheel: " + String(Fault[datalayer_extended.tesla.HVP_gpioPackCoontPosFlywheel]) +
"</h4>"; //bool
content +=
"<h4>HVP_gpioCpLatchEnable: " + String(Fault[datalayer_extended.tesla.HVP_gpioCpLatchEnable]) + "</h4>"; //bool
content += "<h4>HVP_gpioPcsEnable: " + String(Fault[datalayer_extended.tesla.HVP_gpioPcsEnable]) + "</h4>"; //bool
content += "<h4>HVP_gpioPcsDcdcPwmEnable: " + String(Fault[datalayer_extended.tesla.HVP_gpioPcsDcdcPwmEnable]) +
"</h4>"; //bool
content += "<h4>HVP_gpioPcsChargePwmEnable: " + String(Fault[datalayer_extended.tesla.HVP_gpioPcsChargePwmEnable]) +
"</h4>"; //bool
content += "<h4>HVP_gpioFcContPowerEnable: " + String(Fault[datalayer_extended.tesla.HVP_gpioFcContPowerEnable]) +
"</h4>"; //bool
content +=
"<h4>HVP_gpioHvilEnable: " + String(Fault[datalayer_extended.tesla.HVP_gpioHvilEnable]) + "</h4>"; //bool
content += "<h4>HVP_gpioSecDrdy: " + String(Fault[datalayer_extended.tesla.HVP_gpioSecDrdy]) + "</h4>"; //bool
content += "<h4>HVP_hvp1v5Ref: " + String(HVP_hvp1v5Ref) + " V</h4>";
content += "<h4>HVP_shuntCurrentDebug: " + String(HVP_shuntCurrentDebug) + " A</h4>";
content +=
"<h4>HVP_packCurrentMia: " + String(noYes[datalayer_extended.tesla.HVP_packCurrentMia]) + "</h4>"; //bool
content += "<h4>HVP_auxCurrentMia: " + String(noYes[datalayer_extended.tesla.HVP_auxCurrentMia]) + "</h4>"; //bool
content +=
"<h4>HVP_currentSenseMia: " + String(noYes[datalayer_extended.tesla.HVP_currentSenseMia]) + "</h4>"; //bool
content +=
"<h4>HVP_shuntRefVoltageMismatch: " + String(noYes[datalayer_extended.tesla.HVP_shuntRefVoltageMismatch]) +
"</h4>"; //bool
content += "<h4>HVP_shuntThermistorMia: " + String(noYes[datalayer_extended.tesla.HVP_shuntThermistorMia]) +
"</h4>"; //bool
content += "<h4>HVP_shuntHwMia: " + String(noYes[datalayer_extended.tesla.HVP_shuntHwMia]) + "</h4>"; //bool
content += "<h4>HVP_battery12V: " + String(HVP_battery12V) + " V</h4>";
content += "<h4>HVP_dcLinkVoltage: " + String(HVP_dcLinkVoltage) + " V</h4>";
content += "<h4>HVP_packVoltage: " + String(HVP_packVoltage) + " V</h4>";
content += "<h4>HVP_fcLinkVoltage: " + String(HVP_fcLinkVoltage) + " V</h4>";
content += "<h4>HVP_packContVoltage: " + String(HVP_packContVoltage) + " V</h4>";
content += "<h4>HVP_packNegativeV: " + String(HVP_packNegativeV) + " V</h4>";
content += "<h4>HVP_packPositiveV: " + String(HVP_packPositiveV) + " V</h4>";
content += "<h4>HVP_packContCoilCurrent: " + String(HVP_packContCoilCurrent) + " A</h4>";
content += "<h4>HVP_pyroAnalog: " + String(HVP_pyroAnalog) + " V</h4>";
content += "<h4>HVP_dcLinkNegativeV: " + String(HVP_dcLinkNegativeV) + " V</h4>";
content += "<h4>HVP_dcLinkPositiveV: " + String(HVP_dcLinkPositiveV) + " V</h4>";
content += "<h4>HVP_fcLinkNegativeV: " + String(HVP_fcLinkNegativeV) + " V</h4>";
content += "<h4>HVP_fcContCoilCurrent: " + String(HVP_fcContCoilCurrent) + " A</h4>";
content += "<h4>HVP_fcContVoltage: " + String(HVP_fcContVoltage) + " V</h4>";
content += "<h4>HVP_hvp1v5Ref: " + String(HVP_hvp1v5Ref) + " V</h4>";
content += "<h4>HVP_hvilInVoltage: " + String(HVP_hvilInVoltage) + " V</h4>";
content += "<h4>HVP_hvilOutVoltage: " + String(HVP_hvilOutVoltage) + " V</h4>";
content += "<h4>HVP_fcLinkPositiveV: " + String(HVP_fcLinkPositiveV) + " V</h4>";
content += "<h4>HVP_packContCoilCurrent: " + String(HVP_packContCoilCurrent) + " A</h4>";
content += "<h4>HVP_battery12V: " + String(HVP_battery12V) + " V</h4>";
content += "<h4>HVP_shuntRefVoltageDbg: " + String(HVP_shuntRefVoltageDbg) + " V</h4>";
content += "<h4>HVP_shuntAuxCurrentDbg: " + String(HVP_shuntAuxCurrentDbg) + " A</h4>";
content += "<h4>HVP_shuntBarTempDbg: " + String(HVP_shuntBarTempDbg) + " DegC</h4>";
content += "<h4>HVP_shuntAsicTempDbg: " + String(HVP_shuntAsicTempDbg) + " DegC</h4>";
content +=
"<h4>HVP_shuntAuxCurrentStatus: " + String(HVP_status[datalayer_extended.tesla.HVP_shuntAuxCurrentStatus]) +
"<h4>HVP_gpioPassivePyroDepl: " + String(Fault[datalayer_extended.tesla.HVP_gpioPassivePyroDepl]) + "</h4>";
content += "<h4>HVP_gpioPyroIsoEn: " + String(Fault[datalayer_extended.tesla.HVP_gpioPyroIsoEn]) + "</h4>";
content += "<h4>HVP_gpioCpFaultIn: " + String(Fault[datalayer_extended.tesla.HVP_gpioCpFaultIn]) + "</h4>";
content +=
"<h4>HVP_gpioPackContPowerEn: " + String(Fault[datalayer_extended.tesla.HVP_gpioPackContPowerEn]) + "</h4>";
content += "<h4>HVP_gpioHvCablesOk: " + String(Fault[datalayer_extended.tesla.HVP_gpioHvCablesOk]) + "</h4>";
content += "<h4>HVP_gpioHvpSelfEnable: " + String(Fault[datalayer_extended.tesla.HVP_gpioHvpSelfEnable]) + "</h4>";
content += "<h4>HVP_gpioLed: " + String(Fault[datalayer_extended.tesla.HVP_gpioLed]) + "</h4>";
content += "<h4>HVP_gpioCrashSignal: " + String(Fault[datalayer_extended.tesla.HVP_gpioCrashSignal]) + "</h4>";
content +=
"<h4>HVP_gpioShuntDataReady: " + String(Fault[datalayer_extended.tesla.HVP_gpioShuntDataReady]) + "</h4>";
content += "<h4>HVP_gpioFcContPosAux: " + String(Fault[datalayer_extended.tesla.HVP_gpioFcContPosAux]) + "</h4>";
content += "<h4>HVP_gpioFcContNegAux: " + String(Fault[datalayer_extended.tesla.HVP_gpioFcContNegAux]) + "</h4>";
content += "<h4>HVP_gpioBmsEout: " + String(Fault[datalayer_extended.tesla.HVP_gpioBmsEout]) + "</h4>";
content += "<h4>HVP_gpioCpFaultOut: " + String(Fault[datalayer_extended.tesla.HVP_gpioCpFaultOut]) + "</h4>";
content += "<h4>HVP_gpioPyroPor: " + String(Fault[datalayer_extended.tesla.HVP_gpioPyroPor]) + "</h4>";
content += "<h4>HVP_gpioShuntEn: " + String(Fault[datalayer_extended.tesla.HVP_gpioShuntEn]) + "</h4>";
content += "<h4>HVP_gpioHvpVerEn: " + String(Fault[datalayer_extended.tesla.HVP_gpioHvpVerEn]) + "</h4>";
content +=
"<h4>HVP_gpioPackCoontPosFlywheel: " + String(Fault[datalayer_extended.tesla.HVP_gpioPackCoontPosFlywheel]) +
"</h4>";
content += "<h4>HVP_gpioCpLatchEnable: " + String(Fault[datalayer_extended.tesla.HVP_gpioCpLatchEnable]) + "</h4>";
content += "<h4>HVP_gpioPcsEnable: " + String(Fault[datalayer_extended.tesla.HVP_gpioPcsEnable]) + "</h4>";
content +=
"<h4>HVP_gpioPcsDcdcPwmEnable: " + String(Fault[datalayer_extended.tesla.HVP_gpioPcsDcdcPwmEnable]) + "</h4>";
content += "<h4>HVP_gpioPcsChargePwmEnable: " + String(Fault[datalayer_extended.tesla.HVP_gpioPcsChargePwmEnable]) +
"</h4>";
content +=
"<h4>HVP_gpioFcContPowerEnable: " + String(Fault[datalayer_extended.tesla.HVP_gpioFcContPowerEnable]) + "</h4>";
content += "<h4>HVP_gpioHvilEnable: " + String(Fault[datalayer_extended.tesla.HVP_gpioHvilEnable]) + "</h4>";
content += "<h4>HVP_gpioSecDrdy: " + String(Fault[datalayer_extended.tesla.HVP_gpioSecDrdy]) + "</h4>";
content += "<h4>HVP_shuntCurrentDebug: " + String(HVP_shuntCurrentDebug) + " A</h4>";
content += "<h4>HVP_packCurrentMia: " + String(noYes[datalayer_extended.tesla.HVP_packCurrentMia]) + "</h4>";
content += "<h4>HVP_auxCurrentMia: " + String(noYes[datalayer_extended.tesla.HVP_auxCurrentMia]) + "</h4>";
content += "<h4>HVP_currentSenseMia: " + String(noYes[datalayer_extended.tesla.HVP_currentSenseMia]) + "</h4>";
content +=
"<h4>HVP_shuntRefVoltageMismatch: " + String(noYes[datalayer_extended.tesla.HVP_shuntRefVoltageMismatch]) +
"</h4>";
content +=
"<h4>HVP_shuntBarTempStatus: " + String(HVP_status[datalayer_extended.tesla.HVP_shuntBarTempStatus]) + "</h4>";
content += "<h4>HVP_shuntAsicTempStatus: " + String(HVP_status[datalayer_extended.tesla.HVP_shuntAsicTempStatus]) +
"</h4>";
"<h4>HVP_shuntThermistorMia: " + String(noYes[datalayer_extended.tesla.HVP_shuntThermistorMia]) + "</h4>";
content += "<h4>HVP_shuntHwMia: " + String(noYes[datalayer_extended.tesla.HVP_shuntHwMia]) + "</h4>";
//content += "<h4>HVP_fcLinkVoltage: " + String(HVP_fcLinkVoltage) + " V</h4>"; // Not giving useable data
//content += "<h4>HVP_packNegativeV: " + String(HVP_packNegativeV) + " V</h4>"; // Not giving useable data
//content += "<h4>HVP_packPositiveV: " + String(HVP_packPositiveV) + " V</h4>"; // Not giving useable data
//content += "<h4>HVP_dcLinkNegativeV: " + String(HVP_dcLinkNegativeV) + " V</h4>"; // Not giving useable data
//content += "<h4>HVP_dcLinkPositiveV: " + String(HVP_dcLinkPositiveV) + " V</h4>"; // Not giving useable data
//content += "<h4>HVP_fcLinkNegativeV: " + String(HVP_fcLinkNegativeV) + " V</h4>"; // Not giving useable data
//content += "<h4>HVP_fcContCoilCurrent: " + String(HVP_fcContCoilCurrent) + " A</h4>"; // Not giving useable data
//content += "<h4>HVP_fcContVoltage: " + String(HVP_fcContVoltage) + " V</h4>"; // Not giving useable data
//content += "<h4>HVP_fcLinkPositiveV: " + String(HVP_fcLinkPositiveV) + " V</h4>"; // Not giving useable data
//content += "<h4>HVP_shuntRefVoltageDbg: " + String(HVP_shuntRefVoltageDbg) + " V</h4>"; // Not giving useable data
//content += "<h4>HVP_shuntAuxCurrentDbg: " + String(HVP_shuntAuxCurrentDbg) + " A</h4>"; // Not giving useable data
//content += "<h4>HVP_shuntBarTempDbg: " + String(HVP_shuntBarTempDbg) + " DegC</h4>"; // Not giving useable data
//content += "<h4>HVP_shuntAsicTempDbg: " + String(HVP_shuntAsicTempDbg) + " DegC</h4>"; // Not giving useable data
//content += "<h4>HVP_shuntAuxCurrentStatus: " + String(HVP_status[datalayer_extended.tesla.HVP_shuntAuxCurrentStatus]) + "</h4>"; // Not giving useable data
//content += "<h4>HVP_shuntBarTempStatus: " + String(HVP_status[datalayer_extended.tesla.HVP_shuntBarTempStatus]) + "</h4>"; // Not giving useable data
//content += "<h4>HVP_shuntAsicTempStatus: " + String(HVP_status[datalayer_extended.tesla.HVP_shuntAsicTempStatus]) + "</h4>"; // Not giving useable data
#endif
#ifdef NISSAN_LEAF_BATTERY
@ -1145,10 +1256,11 @@ String advanced_battery_processor(const String& var) {
content += "<button onclick='Volvo_BECMecuReset()'>Restart BECM module</button>";
#endif // VOLVO_SPA_BATTERY
#if !defined(BMW_IX_BATTERY) && !defined(BOLT_AMPERA_BATTERY) && !defined(TESLA_BATTERY) && \
!defined(NISSAN_LEAF_BATTERY) && !defined(BMW_I3_BATTERY) && !defined(BYD_ATTO_3_BATTERY) && \
!defined(RENAULT_ZOE_GEN2_BATTERY) && !defined(CELLPOWER_BMS) && !defined(MEB_BATTERY) && \
!defined(VOLVO_SPA_BATTERY) && !defined(KIA_HYUNDAI_64_BATTERY) //Only the listed types have extra info
#if !defined(BMW_PHEV_BATTERY) && !defined(BMW_IX_BATTERY) && !defined(BOLT_AMPERA_BATTERY) && \
!defined(TESLA_BATTERY) && !defined(NISSAN_LEAF_BATTERY) && !defined(BMW_I3_BATTERY) && \
!defined(BYD_ATTO_3_BATTERY) && !defined(RENAULT_ZOE_GEN2_BATTERY) && !defined(CELLPOWER_BMS) && \
!defined(MEB_BATTERY) && !defined(VOLVO_SPA_BATTERY) && \
!defined(KIA_HYUNDAI_64_BATTERY) //Only the listed types have extra info
content += "No extra information available for this battery type";
#endif
@ -1210,6 +1322,10 @@ String advanced_battery_processor(const String& var) {
content += "}";
content += "function goToMainPage() { window.location.href = '/'; }";
content += "</script>";
// Additial functions added
content += "<script>";
content += "function exportLog() { window.location.href = '/export_log'; }";
content += "</script>";
return content;
}