Merge pull request #764 from dalathegreat/feature/reset-isolation-tesla

Feature: Tesla, add isolation clearing function
This commit is contained in:
Daniel Öster 2025-01-10 17:34:39 +03:00 committed by GitHub
commit f0fd607c5e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 93 additions and 4 deletions

View file

@ -8,7 +8,8 @@
/* Do not change code below unless you are sure what you are doing */ /* Do not change code below unless you are sure what you are doing */
/* Credits: Most of the code comes from Per Carlen's bms_comms_tesla_model3.py (https://gitlab.com/pelle8/batt2gen24/) */ /* Credits: Most of the code comes from Per Carlen's bms_comms_tesla_model3.py (https://gitlab.com/pelle8/batt2gen24/) */
static unsigned long previousMillis50 = 0; // will store last time a 50ms CAN Message was send static unsigned long previousMillis50 = 0; // will store last time a 50ms CAN Message was send
static unsigned long previousMillis100 = 0; // will store last time a 100ms CAN Message was send
//0x221 545 VCFRONT_LVPowerState: "GenMsgCycleTime" 50ms //0x221 545 VCFRONT_LVPowerState: "GenMsgCycleTime" 50ms
CAN_frame TESLA_221_1 = { CAN_frame TESLA_221_1 = {
.FD = false, .FD = false,
@ -22,7 +23,12 @@ CAN_frame TESLA_221_2 = {
.DLC = 8, .DLC = 8,
.ID = 0x221, .ID = 0x221,
.data = {0x61, 0x15, 0x01, 0x00, 0x00, 0x00, 0x20, 0xBA}}; //Contactor Frame 221 - hv_up_for_drive .data = {0x61, 0x15, 0x01, 0x00, 0x00, 0x00, 0x20, 0xBA}}; //Contactor Frame 221 - hv_up_for_drive
CAN_frame TESLA_602 = {.FD = false,
.ext_ID = false,
.DLC = 8,
.ID = 0x602,
.data = {0x02, 0x27, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00}}; //Diagnostic request
static uint8_t stateMachineClearIsolationFault = 0xFF;
static uint16_t sendContactorClosingMessagesStill = 300; static uint16_t sendContactorClosingMessagesStill = 300;
static uint16_t battery_cell_max_v = 3300; static uint16_t battery_cell_max_v = 3300;
static uint16_t battery_cell_min_v = 3300; static uint16_t battery_cell_min_v = 3300;
@ -817,6 +823,10 @@ static const char* hvilStatusState[] = {"NOT OK",
"UNKNOWN(14)", "UNKNOWN(14)",
"UNKNOWN(15)"}; "UNKNOWN(15)"};
void clearIsolationFault() {
//CAN UDS messages to clear a latched isolation fault
}
void update_values_battery() { //This function maps all the values fetched via CAN to the correct parameters used for modbus void update_values_battery() { //This function maps all the values fetched via CAN to the correct parameters used for modbus
//After values are mapped, we perform some safety checks, and do some serial printouts //After values are mapped, we perform some safety checks, and do some serial printouts
@ -913,6 +923,12 @@ void update_values_battery() { //This function maps all the values fetched via
} }
#endif // TESLA_MODEL_3Y_BATTERY #endif // TESLA_MODEL_3Y_BATTERY
// Check if user requests some action
if (datalayer.battery.settings.user_requests_isolation_clear) {
stateMachineClearIsolationFault = 0; //Start the statemachine
datalayer.battery.settings.user_requests_isolation_clear = false;
}
// Update webserver datalayer // Update webserver datalayer
//0x20A //0x20A
datalayer_extended.tesla.status_contactor = battery_contactor; datalayer_extended.tesla.status_contactor = battery_contactor;
@ -2675,7 +2691,7 @@ the first, for a few cycles, then stop all messages which causes the contactor
} }
#endif //defined(TESLA_MODEL_SX_BATTERY) || defined(EXP_TESLA_BMS_DIGITAL_HVIL) #endif //defined(TESLA_MODEL_SX_BATTERY) || defined(EXP_TESLA_BMS_DIGITAL_HVIL)
//Send 30ms message //Send 50ms message
if (currentMillis - previousMillis50 >= INTERVAL_50_MS) { if (currentMillis - previousMillis50 >= INTERVAL_50_MS) {
// Check if sending of CAN messages has been delayed too much. // Check if sending of CAN messages has been delayed too much.
if ((currentMillis - previousMillis50 >= INTERVAL_50_MS_DELAYED) && (currentMillis > BOOTUP_TIME)) { if ((currentMillis - previousMillis50 >= INTERVAL_50_MS_DELAYED) && (currentMillis > BOOTUP_TIME)) {
@ -2707,6 +2723,54 @@ the first, for a few cycles, then stop all messages which causes the contactor
} }
} }
} }
//Send 100ms message
if (currentMillis - previousMillis100 >= INTERVAL_100_MS) {
previousMillis100 = currentMillis;
if (stateMachineClearIsolationFault != 0xFF) {
//This implementation should be rewritten to actually replying to the UDS replied sent by the BMS
//While this may work, it is not the correct way to implement this clearing logic
switch (stateMachineClearIsolationFault) {
case 0:
TESLA_602.data = {0x02, 0x27, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00};
transmit_can_frame(&TESLA_602, can_config.battery);
stateMachineClearIsolationFault = 1;
break;
case 1:
TESLA_602.data = {0x30, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00};
transmit_can_frame(&TESLA_602, can_config.battery);
// BMS should reply 02 50 C0 FF FF FF FF FF
stateMachineClearIsolationFault = 2;
break;
case 2:
TESLA_602.data = {0x10, 0x12, 0x27, 0x06, 0x35, 0x34, 0x37, 0x36};
transmit_can_frame(&TESLA_602, can_config.battery);
// BMS should reply 7E FF FF FF FF FF FF
stateMachineClearIsolationFault = 3;
break;
case 3:
TESLA_602.data = {0x21, 0x31, 0x30, 0x33, 0x32, 0x3D, 0x3C, 0x3F};
transmit_can_frame(&TESLA_602, can_config.battery);
stateMachineClearIsolationFault = 4;
break;
case 4:
TESLA_602.data = {0x22, 0x3E, 0x39, 0x38, 0x3B, 0x3A, 0x00, 0x00};
transmit_can_frame(&TESLA_602, can_config.battery);
stateMachineClearIsolationFault = 5;
break;
case 5:
TESLA_602.data = {0x04, 0x31, 0x01, 0x04, 0x0A, 0x00, 0x00, 0x00};
transmit_can_frame(&TESLA_602, can_config.battery);
stateMachineClearIsolationFault = 0xFF;
break;
default:
//Something went wrong. Reset all and cancel
stateMachineClearIsolationFault = 0xFF;
break;
}
}
}
} }
void print_int_with_units(char* header, int value, char* units) { void print_int_with_units(char* header, int value, char* units) {

View file

@ -122,8 +122,9 @@ typedef struct {
uint16_t max_user_set_discharge_voltage_dV = BATTERY_MAX_DISCHARGE_VOLTAGE; uint16_t max_user_set_discharge_voltage_dV = BATTERY_MAX_DISCHARGE_VOLTAGE;
/** Tesla specific settings that are edited on the fly when manually forcing a balance charge for LFP chemistry */ /** Tesla specific settings that are edited on the fly when manually forcing a balance charge for LFP chemistry */
/* Bool for specifying if user has requested manual balancing */ /* Bool for specifying if user has requested manual function */
bool user_requests_balancing = false; bool user_requests_balancing = false;
bool user_requests_isolation_clear = false;
/* Forced balancing max time & start timestamp */ /* Forced balancing max time & start timestamp */
uint32_t balancing_time_ms = 3600000; //1h default, (60min*60sec*1000ms) uint32_t balancing_time_ms = 3600000; //1h default, (60min*60sec*1000ms)
uint32_t balancing_start_time_ms = 0; //For keeping track when balancing started uint32_t balancing_start_time_ms = 0; //For keeping track when balancing started

View file

@ -509,6 +509,8 @@ String advanced_battery_processor(const String& var) {
static const char* falseTrue[] = {"False", "True"}; static const char* falseTrue[] = {"False", "True"};
static const char* noYes[] = {"No", "Yes"}; static const char* noYes[] = {"No", "Yes"};
static const char* Fault[] = {"NOT_ACTIVE", "ACTIVE"}; static const char* Fault[] = {"NOT_ACTIVE", "ACTIVE"};
//Buttons for user action
content += "<button onclick='askClearIsolation()'>Clear isolation fault</button>";
//0x20A 522 HVP_contatorState //0x20A 522 HVP_contatorState
content += "<h4>Contactor Status: " + String(contactorText[datalayer_extended.tesla.status_contactor]) + "</h4>"; content += "<h4>Contactor Status: " + String(contactorText[datalayer_extended.tesla.status_contactor]) + "</h4>";
content += "<h4>HVIL: " + String(hvilStatusState[datalayer_extended.tesla.hvil_status]) + "</h4>"; content += "<h4>HVIL: " + String(hvilStatusState[datalayer_extended.tesla.hvil_status]) + "</h4>";
@ -1149,6 +1151,19 @@ String advanced_battery_processor(const String& var) {
content += "</div>"; content += "</div>";
content += "<script>"; content += "<script>";
content +=
"function askClearIsolation() { if (window.confirm('Are you sure you want to clear any active isolation "
"fault?')) { "
"clearIsolation(); } }";
content += "function clearIsolation() {";
content += " var xhr = new XMLHttpRequest();";
content += " xhr.open('GET', '/clearIsolation', true);";
content += " xhr.send();";
content += "}";
content += "function goToMainPage() { window.location.href = '/'; }";
content += "</script>";
content += "<script>";
content += "<script>";
content += content +=
"function askResetSOH() { if (window.confirm('Are you sure you want to reset degradation data? " "function askResetSOH() { if (window.confirm('Are you sure you want to reset degradation data? "
"Note this should only be used on 2011-2017 24/30kWh batteries!')) { " "Note this should only be used on 2011-2017 24/30kWh batteries!')) { "

View file

@ -385,6 +385,15 @@ void init_webserver() {
} }
}); });
// Route for clearing isolation faults on Tesla
server.on("/clearIsolation", HTTP_GET, [](AsyncWebServerRequest* request) {
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password)) {
return request->requestAuthentication();
}
datalayer.battery.settings.user_requests_isolation_clear = true;
request->send(200, "text/plain", "Updated successfully");
});
// Route for resetting SOH on Nissan LEAF batteries // Route for resetting SOH on Nissan LEAF batteries
server.on("/resetSOH", HTTP_GET, [](AsyncWebServerRequest* request) { server.on("/resetSOH", HTTP_GET, [](AsyncWebServerRequest* request) {
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password)) { if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password)) {