Add events for BMS_a145_SW_SOC_Change, BMS reset and SOC reset

This commit is contained in:
James Brookes 2025-09-25 19:03:54 +01:00
parent 8cc10a1b71
commit 95ee6ff9ae
3 changed files with 61 additions and 21 deletions

View file

@ -483,11 +483,17 @@ void TeslaBattery::
} else { } else {
clear_event(EVENT_BATTERY_FUSE); clear_event(EVENT_BATTERY_FUSE);
} }
// Raise any informational Tesla BMS events in BE
if (BMS_a145_SW_SOC_Change == true) { // BMS has recalibrated pack SOC
set_event(EVENT_BATTERY_SOC_RECALIBRATION, 0);
} else {
clear_event(EVENT_BATTERY_SOC_RECALIBRATION);
}
if (user_selected_tesla_GTW_chassisType > 1) { //{{0, "Model S"}, {1, "Model X"}, {2, "Model 3"}, {3, "Model Y"}}; if (user_selected_tesla_GTW_chassisType > 1) { //{{0, "Model S"}, {1, "Model X"}, {2, "Model 3"}, {3, "Model Y"}};
// Autodetect algoritm for chemistry on 3/Y packs. // Autodetect algorithm for chemistry on 3/Y packs.
// NCM/A batteries have 96s, LFP has 102-108s // NCM/A batteries have 96s, LFP has 102-108s
// Drawback with this check is that it takes 3-5minutes before all cells have been counted! // Drawback with this check is that it takes 3-5 minutes before all cells have been counted!
if (datalayer.battery.info.number_of_cells > 101) { if (datalayer.battery.info.number_of_cells > 101) {
datalayer.battery.info.chemistry = battery_chemistry_enum::LFP; datalayer.battery.info.chemistry = battery_chemistry_enum::LFP;
} }
@ -528,23 +534,28 @@ void TeslaBattery::
//Start the BMS ECU reset statemachine, only if contactors are OPEN and BMS ECU allows it //Start the BMS ECU reset statemachine, only if contactors are OPEN and BMS ECU allows it
stateMachineBMSReset = 0; stateMachineBMSReset = 0;
datalayer.battery.settings.user_requests_tesla_bms_reset = false; datalayer.battery.settings.user_requests_tesla_bms_reset = false;
logging.println("BMS reset requested"); logging.println("INFO: BMS reset requested");
} else { } else {
logging.println("ERROR: BMS reset failed due to contactors not being open, or BMS ECU not allowing it"); logging.println("ERROR: BMS reset failed due to contactors not being open, or BMS ECU not allowing it");
stateMachineBMSReset = 0xFF; stateMachineBMSReset = 0xFF;
datalayer.battery.settings.user_requests_tesla_bms_reset = false; datalayer.battery.settings.user_requests_tesla_bms_reset = false;
set_event(EVENT_BMS_RESET_REQ_FAIL, 0);
clear_event(EVENT_BMS_RESET_REQ_FAIL);
} }
} }
if (datalayer.battery.settings.user_requests_tesla_soc_reset) { if (datalayer.battery.settings.user_requests_tesla_soc_reset) {
if (datalayer.battery.status.real_soc < 1500 || datalayer.battery.status.real_soc > 9000) { if ((datalayer.battery.status.real_soc < 1500 || datalayer.battery.status.real_soc > 9000) &&
//Start the SOC reset statemachine, only if SOC < 15% or > 90% battery_contactor == 1) {
//Start the SOC reset statemachine, only if SOC less than 15% or greater than 90%, and contactors open
stateMachineSOCReset = 0; stateMachineSOCReset = 0;
datalayer.battery.settings.user_requests_tesla_soc_reset = false; datalayer.battery.settings.user_requests_tesla_soc_reset = false;
logging.println("SOC reset requested"); logging.println("INFO: SOC reset requested");
} else { } else {
logging.println("ERROR: SOC reset failed due to SOC not being less than 15 or greater than 90"); logging.println("ERROR: SOC reset failed, SOC not < 15 or > 90");
stateMachineSOCReset = 0xFF; stateMachineSOCReset = 0xFF;
datalayer.battery.settings.user_requests_tesla_soc_reset = false; datalayer.battery.settings.user_requests_tesla_soc_reset = false;
set_event(EVENT_BATTERY_SOC_RESET_FAIL, 0);
clear_event(EVENT_BATTERY_SOC_RESET_FAIL);
} }
} }
@ -779,7 +790,7 @@ void TeslaBattery::
datalayer_extended.tesla.HVP_shuntBarTempStatus = HVP_shuntBarTempStatus; datalayer_extended.tesla.HVP_shuntBarTempStatus = HVP_shuntBarTempStatus;
datalayer_extended.tesla.HVP_shuntAsicTempStatus = HVP_shuntAsicTempStatus; datalayer_extended.tesla.HVP_shuntAsicTempStatus = HVP_shuntAsicTempStatus;
//Safety checks for CAN message sesnding //Safety checks for CAN message sending
if ((datalayer.system.status.inverter_allows_contactor_closing == true) && if ((datalayer.system.status.inverter_allows_contactor_closing == true) &&
(datalayer.battery.status.bms_status != FAULT) && (!datalayer.system.settings.equipment_stop_active)) { (datalayer.battery.status.bms_status != FAULT) && (!datalayer.system.settings.equipment_stop_active)) {
// Carry on: 0x221 DRIVE state & reset power down timer // Carry on: 0x221 DRIVE state & reset power down timer
@ -1667,10 +1678,10 @@ void TeslaBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
} }
*/ */
break; break;
case 0x612: // CAN UDSs for BMS case 0x612: // CAN UDS responses for BMS
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
//BMS Query //BMS Query
if (stateMachineBMSQuery != 0xFF && stateMachineBMSReset == 0xFF) { if (stateMachineBMSQuery != 0xFF && stateMachineBMSReset == 0xFF && stateMachineSOCReset == 0xFF) {
if (memcmp(rx_frame.data.u8, "\x02\x50\x03\xAA\xAA\xAA\xAA\xAA", 8) == 0) { if (memcmp(rx_frame.data.u8, "\x02\x50\x03\xAA\xAA\xAA\xAA\xAA", 8) == 0) {
//Received initial response, proceed to actual query //Received initial response, proceed to actual query
logging.println("CAN UDS: Received BMS query initial handshake reply"); logging.println("CAN UDS: Received BMS query initial handshake reply");
@ -1713,15 +1724,28 @@ void TeslaBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
break; break;
} }
} }
//BMS Reset //BMS ECU responses
if (stateMachineBMSQuery == 0xFF) { // Make sure this is reset request not query if (memcmp(rx_frame.data.u8, "\x02\x67\x06\xAA\xAA\xAA\xAA\xAA", 8) == 0) {
if (memcmp(rx_frame.data.u8, "\x02\x67\x06\xAA\xAA\xAA\xAA\xAA", 8) == 0) { logging.println("CAN UDS: BMS ECU unlocked");
logging.println("CAN UDS: ECU unlocked"); }
} else if (memcmp(rx_frame.data.u8, "\x03\x7F\x11\x78\xAA\xAA\xAA\xAA", 8) == 0) { if (memcmp(rx_frame.data.u8, "\x03\x7F\x11\x78\xAA\xAA\xAA\xAA", 8) == 0) {
logging.println("CAN UDS: ECU reset request successful but ECU busy, response pending"); logging.println("CAN UDS: BMS ECU reset request successful but ECU busy, response pending");
} else if (memcmp(rx_frame.data.u8, "\x02\x51\x01\xAA\xAA\xAA\xAA\xAA", 8) == 0) { }
logging.println("CAN UDS: ECU reset positive response, 1 second downtime"); if (memcmp(rx_frame.data.u8, "\x02\x51\x01\xAA\xAA\xAA\xAA\xAA", 8) == 0) {
} logging.println("CAN UDS: BMS ECU reset positive response, 1 second downtime");
set_event(EVENT_BMS_RESET_REQ_SUCCESS, 0);
clear_event(EVENT_BMS_RESET_REQ_SUCCESS);
}
if (memcmp(rx_frame.data.u8, "\x05\x71\x01\x04\x07\x01\xAA\xAA", 8) == 0) {
logging.println("CAN UDS: BMS SOC reset accepted, resetting BMS ECU");
set_event(EVENT_BATTERY_SOC_RESET_SUCCESS, 0);
clear_event(EVENT_BATTERY_SOC_RESET_SUCCESS);
stateMachineBMSReset = 6; // BMS ECU already unlocked etc. so we jump straight to reset
}
if (memcmp(rx_frame.data.u8, "\x05\x71\x01\x04\x07\x00\xAA\xAA", 8) == 0) {
logging.println("CAN UDS: BMS SOC reset failed");
set_event(EVENT_BATTERY_SOC_RESET_FAIL, 0);
clear_event(EVENT_BATTERY_SOC_RESET_FAIL);
} }
break; break;
default: default:
@ -2308,7 +2332,7 @@ void TeslaBattery::printFaultCodesIfActive() {
printDebugIfActive(BMS_a139_SW_DC_Link_V_Irrational, "ERROR: BMS_a139_SW_DC_Link_V_Irrational"); printDebugIfActive(BMS_a139_SW_DC_Link_V_Irrational, "ERROR: BMS_a139_SW_DC_Link_V_Irrational");
printDebugIfActive(BMS_a141_SW_BMB_Status_Warning, "ERROR: BMS_a141_SW_BMB_Status_Warning"); printDebugIfActive(BMS_a141_SW_BMB_Status_Warning, "ERROR: BMS_a141_SW_BMB_Status_Warning");
printDebugIfActive(BMS_a144_Hvp_Config_Mismatch, "ERROR: BMS_a144_Hvp_Config_Mismatch"); printDebugIfActive(BMS_a144_Hvp_Config_Mismatch, "ERROR: BMS_a144_Hvp_Config_Mismatch");
printDebugIfActive(BMS_a145_SW_SOC_Change, "ERROR: BMS_a145_SW_SOC_Change"); printDebugIfActive(BMS_a145_SW_SOC_Change, "INFO: BMS_a145_SW_SOC_Change");
printDebugIfActive(BMS_a146_SW_Brick_Overdischarged, "ERROR: BMS_a146_SW_Brick_Overdischarged"); printDebugIfActive(BMS_a146_SW_Brick_Overdischarged, "ERROR: BMS_a146_SW_Brick_Overdischarged");
printDebugIfActive(BMS_a149_SW_Missing_Config_Block, "ERROR: BMS_a149_SW_Missing_Config_Block"); printDebugIfActive(BMS_a149_SW_Missing_Config_Block, "ERROR: BMS_a149_SW_Missing_Config_Block");
printDebugIfActive(BMS_a151_SW_external_isolation, "ERROR: BMS_a151_SW_external_isolation"); printDebugIfActive(BMS_a151_SW_external_isolation, "ERROR: BMS_a151_SW_external_isolation");

View file

@ -67,6 +67,9 @@ void init_events(void) {
events.entries[EVENT_BATTERY_UNDERVOLTAGE].level = EVENT_LEVEL_WARNING; events.entries[EVENT_BATTERY_UNDERVOLTAGE].level = EVENT_LEVEL_WARNING;
events.entries[EVENT_BATTERY_VALUE_UNAVAILABLE].level = EVENT_LEVEL_WARNING; events.entries[EVENT_BATTERY_VALUE_UNAVAILABLE].level = EVENT_LEVEL_WARNING;
events.entries[EVENT_BATTERY_ISOLATION].level = EVENT_LEVEL_WARNING; events.entries[EVENT_BATTERY_ISOLATION].level = EVENT_LEVEL_WARNING;
events.entries[EVENT_BATTERY_SOC_RECALIBRATION].level = EVENT_LEVEL_INFO;
events.entries[EVENT_BATTERY_SOC_RESET_SUCCESS].level = EVENT_LEVEL_INFO;
events.entries[EVENT_BATTERY_SOC_RESET_FAIL].level = EVENT_LEVEL_INFO;
events.entries[EVENT_VOLTAGE_DIFFERENCE].level = EVENT_LEVEL_INFO; events.entries[EVENT_VOLTAGE_DIFFERENCE].level = EVENT_LEVEL_INFO;
events.entries[EVENT_SOH_DIFFERENCE].level = EVENT_LEVEL_WARNING; events.entries[EVENT_SOH_DIFFERENCE].level = EVENT_LEVEL_WARNING;
events.entries[EVENT_SOH_LOW].level = EVENT_LEVEL_ERROR; events.entries[EVENT_SOH_LOW].level = EVENT_LEVEL_ERROR;
@ -124,6 +127,8 @@ void init_events(void) {
events.entries[EVENT_EQUIPMENT_STOP].level = EVENT_LEVEL_ERROR; events.entries[EVENT_EQUIPMENT_STOP].level = EVENT_LEVEL_ERROR;
events.entries[EVENT_SD_INIT_FAILED].level = EVENT_LEVEL_WARNING; events.entries[EVENT_SD_INIT_FAILED].level = EVENT_LEVEL_WARNING;
events.entries[EVENT_PERIODIC_BMS_RESET].level = EVENT_LEVEL_INFO; events.entries[EVENT_PERIODIC_BMS_RESET].level = EVENT_LEVEL_INFO;
events.entries[EVENT_BMS_RESET_REQ_SUCCESS].level = EVENT_LEVEL_INFO;
events.entries[EVENT_BMS_RESET_REQ_FAIL].level = EVENT_LEVEL_INFO;
events.entries[EVENT_BATTERY_TEMP_DEVIATION_HIGH].level = EVENT_LEVEL_WARNING; events.entries[EVENT_BATTERY_TEMP_DEVIATION_HIGH].level = EVENT_LEVEL_WARNING;
events.entries[EVENT_GPIO_CONFLICT].level = EVENT_LEVEL_ERROR; events.entries[EVENT_GPIO_CONFLICT].level = EVENT_LEVEL_ERROR;
events.entries[EVENT_GPIO_NOT_DEFINED].level = EVENT_LEVEL_ERROR; events.entries[EVENT_GPIO_NOT_DEFINED].level = EVENT_LEVEL_ERROR;
@ -244,6 +249,8 @@ String get_event_message_string(EVENTS_ENUM_TYPE event) {
return "Battery measurement unavailable. Check 12V power supply and battery wiring!"; return "Battery measurement unavailable. Check 12V power supply and battery wiring!";
case EVENT_BATTERY_ISOLATION: case EVENT_BATTERY_ISOLATION:
return "Battery reports isolation error. High voltage might be leaking to ground. Check battery!"; return "Battery reports isolation error. High voltage might be leaking to ground. Check battery!";
case EVENT_BATTERY_SOC_RECALIBRATION:
return "The BMS updated the HV battery State of Charge (SOC) by more than 3% based on SocByOcv.";
case EVENT_VOLTAGE_DIFFERENCE: case EVENT_VOLTAGE_DIFFERENCE:
return "Too large voltage diff between the batteries. Second battery cannot join the DC-link"; return "Too large voltage diff between the batteries. Second battery cannot join the DC-link";
case EVENT_SOH_DIFFERENCE: case EVENT_SOH_DIFFERENCE:
@ -361,7 +368,11 @@ String get_event_message_string(EVENTS_ENUM_TYPE event) {
case EVENT_SD_INIT_FAILED: case EVENT_SD_INIT_FAILED:
return "SD card initialization failed, check hardware. Power must be removed to reset the SD card."; return "SD card initialization failed, check hardware. Power must be removed to reset the SD card.";
case EVENT_PERIODIC_BMS_RESET: case EVENT_PERIODIC_BMS_RESET:
return "BMS Reset Event Completed."; return "BMS reset event completed.";
case EVENT_BMS_RESET_REQ_SUCCESS:
return "BMS reset request completed successfully.";
case EVENT_BMS_RESET_REQ_FAIL:
return "BMS reset request failed - check contactors are open.";
case EVENT_GPIO_CONFLICT: case EVENT_GPIO_CONFLICT:
return "GPIO Pin Conflict: The pin used by '" + esp32hal->failed_allocator() + "' is already allocated by '" + return "GPIO Pin Conflict: The pin used by '" + esp32hal->failed_allocator() + "' is already allocated by '" +
esp32hal->conflicting_allocator() + "'. Please check your configuration and assign different pins."; esp32hal->conflicting_allocator() + "'. Please check your configuration and assign different pins.";

View file

@ -49,6 +49,9 @@
XX(EVENT_BATTERY_ISOLATION) \ XX(EVENT_BATTERY_ISOLATION) \
XX(EVENT_BATTERY_REQUESTS_HEAT) \ XX(EVENT_BATTERY_REQUESTS_HEAT) \
XX(EVENT_BATTERY_WARMED_UP) \ XX(EVENT_BATTERY_WARMED_UP) \
XX(EVENT_BATTERY_SOC_RECALIBRATION) \
XX(EVENT_BATTERY_SOC_RESET_SUCCESS) \
XX(EVENT_BATTERY_SOC_RESET_FAIL) \
XX(EVENT_VOLTAGE_DIFFERENCE) \ XX(EVENT_VOLTAGE_DIFFERENCE) \
XX(EVENT_SOH_DIFFERENCE) \ XX(EVENT_SOH_DIFFERENCE) \
XX(EVENT_SOH_LOW) \ XX(EVENT_SOH_LOW) \
@ -107,6 +110,8 @@
XX(EVENT_AUTOMATIC_PRECHARGE_FAILURE) \ XX(EVENT_AUTOMATIC_PRECHARGE_FAILURE) \
XX(EVENT_SD_INIT_FAILED) \ XX(EVENT_SD_INIT_FAILED) \
XX(EVENT_PERIODIC_BMS_RESET) \ XX(EVENT_PERIODIC_BMS_RESET) \
XX(EVENT_BMS_RESET_REQ_SUCCESS) \
XX(EVENT_BMS_RESET_REQ_FAIL) \
XX(EVENT_BATTERY_TEMP_DEVIATION_HIGH) \ XX(EVENT_BATTERY_TEMP_DEVIATION_HIGH) \
XX(EVENT_GPIO_NOT_DEFINED) \ XX(EVENT_GPIO_NOT_DEFINED) \
XX(EVENT_GPIO_CONFLICT) \ XX(EVENT_GPIO_CONFLICT) \