From 441549b6459b499653850268022786f35a7a94fa Mon Sep 17 00:00:00 2001 From: Daniel Date: Sun, 17 Sep 2023 11:06:48 +0300 Subject: [PATCH 1/6] Move CANstillAlive inside BMS message --- Software/TESLA-MODEL-3-BATTERY.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Software/TESLA-MODEL-3-BATTERY.cpp b/Software/TESLA-MODEL-3-BATTERY.cpp index 0e093913..212cb918 100644 --- a/Software/TESLA-MODEL-3-BATTERY.cpp +++ b/Software/TESLA-MODEL-3-BATTERY.cpp @@ -66,6 +66,7 @@ static const char* hvilStatusState[] = {"NOT OK","STATUS_OK","CURRENT_SOURCE_FAU void update_values_tesla_model_3_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 StateOfHealth = 9900; //Hardcoded to 99%SOH //Calculate the SOC% value to send to inverter @@ -118,6 +119,8 @@ void update_values_tesla_model_3_battery() max_temp = (max_temp * 10); temperature_max = convert2unsignedint16(max_temp); + /* Value mapping is completed. Start to check all safeties */ + bms_status = ACTIVE; //Startout in active mode before checking if we have any faults /* Check if the BMS is still sending CAN messages. If we go 60s without messages we raise an error*/ @@ -147,6 +150,8 @@ void update_values_tesla_model_3_battery() Serial.println("HIGH CELL DEVIATION!!! Inspect battery!"); } + /* Safeties verified. Perform USB serial printout if configured to do so */ + #ifdef DEBUG_VIA_USB if (packCtrsClosingAllowed == 0) { @@ -234,8 +239,6 @@ void receive_can_tesla_model_3_battery(CAN_frame_t rx_frame) { static int mux = 0; static int temp = 0; - - stillAliveCAN = 12; //We are getting CAN messages, set the CAN detect counter switch (rx_frame.MsgID) { @@ -325,6 +328,7 @@ void receive_can_tesla_model_3_battery(CAN_frame_t rx_frame) output_current = (((rx_frame.data.u8[4] & 0x0F) << 8) | rx_frame.data.u8[3]) / 100; break; case 0x292: + stillAliveCAN = 12; //We are getting CAN messages from the BMS, set the CAN detect counter soc_min = (((rx_frame.data.u8[1] & 0x03) << 8) | rx_frame.data.u8[0]); soc_vi = (((rx_frame.data.u8[2] & 0x0F) << 6) | ((rx_frame.data.u8[1] & 0xFC) >> 2)); soc_max = (((rx_frame.data.u8[3] & 0x3F) << 4) | ((rx_frame.data.u8[2] & 0xF0) >> 4)); From dd9570510728e078449de6a531ca5d9bba655c36 Mon Sep 17 00:00:00 2001 From: Daniel Date: Sun, 17 Sep 2023 11:21:25 +0300 Subject: [PATCH 2/6] Improve fault-contactor opening handling --- Software/TESLA-MODEL-3-BATTERY.cpp | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/Software/TESLA-MODEL-3-BATTERY.cpp b/Software/TESLA-MODEL-3-BATTERY.cpp index 212cb918..c0a185b7 100644 --- a/Software/TESLA-MODEL-3-BATTERY.cpp +++ b/Software/TESLA-MODEL-3-BATTERY.cpp @@ -3,12 +3,14 @@ #include "CAN_config.h" /* 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/) */ + static unsigned long previousMillis30 = 0; // will store last time a 30ms CAN Message was send static const int interval30 = 30; // interval (ms) at which send CAN Messages static uint8_t stillAliveCAN = 6; //counter for checking if CAN is still alive -CAN_frame_t TESLA_221_1 = {.FIR = {.B = {.DLC = 8,.FF = CAN_frame_std,}},.MsgID = 0x221,.data = {0x41, 0x11, 0x01, 0x00, 0x00, 0x00, 0x20, 0x96}}; -CAN_frame_t TESLA_221_2 = {.FIR = {.B = {.DLC = 8,.FF = CAN_frame_std,}},.MsgID = 0x221,.data = {0x61, 0x15, 0x01, 0x00, 0x00, 0x00, 0x20, 0xBA}}; +CAN_frame_t TESLA_221_1 = {.FIR = {.B = {.DLC = 8,.FF = CAN_frame_std,}},.MsgID = 0x221,.data = {0x41, 0x11, 0x01, 0x00, 0x00, 0x00, 0x20, 0x96}}; //Contactor frame 221 - close contactors +CAN_frame_t TESLA_221_2 = {.FIR = {.B = {.DLC = 8,.FF = CAN_frame_std,}},.MsgID = 0x221,.data = {0x61, 0x15, 0x01, 0x00, 0x00, 0x00, 0x20, 0xBA}}; //Contactor Frame 221 - hv_up_for_drive static uint32_t temporaryvariable = 0; static uint32_t total_discharge = 0; @@ -53,6 +55,7 @@ static uint8_t packContPositiveState = 0; static uint8_t packContactorSetState = 0; static uint8_t packCtrsClosingAllowed = 0; static uint8_t pyroTestInProgress = 0; +static uint8_t send221still = 10; static const char* contactorText[] = {"UNKNOWN(0)","OPEN","CLOSING","BLOCKED","OPENING","CLOSED","UNKNOWN(6)","WELDED","POS_CL","NEG_CL","UNKNOWN(10)","UNKNOWN(11)","UNKNOWN(12)"}; static const char* contactorState[] = {"SNA","OPEN","PRECHARGE","BLOCKED","PULLED_IN","OPENING","ECONOMIZED","WELDED","UNKNOWN(8)","UNKNOWN(9)","UNKNOWN(10)","UNKNOWN(11)"}; static const char* hvilStatusState[] = {"NOT OK","STATUS_OK","CURRENT_SOURCE_FAULT","INTERNAL_OPEN_FAULT","VEHICLE_OPEN_FAULT","PENTHOUSE_LID_OPEN_FAULT","UNKNOWN_LOCATION_OPEN_FAULT","VEHICLE_NODE_FAULT","NO_12V_SUPPLY","VEHICLE_OR_PENTHOUSE_LID_OPENFAULT","UNKNOWN(10)","UNKNOWN(11)","UNKNOWN(12)","UNKNOWN(13)","UNKNOWN(14)","UNKNOWN(15)"}; @@ -340,14 +343,30 @@ void receive_can_tesla_model_3_battery(CAN_frame_t rx_frame) } void send_can_tesla_model_3_battery() { +/*From bielec: My fist 221 message, to close the contactors is 0x41, 0x11, 0x01, 0x00, 0x00, 0x00, 0x20, 0x96 and then, +to cause "hv_up_for_drive" I send an additional 221 message 0x61, 0x15, 0x01, 0x00, 0x00, 0x00, 0x20, 0xBA so +two 221 messages are being continuously transmitted. When I want to shut down, I stop the second message and only send +the first, for a few cycles, then stop all messages which causes the contactor to open. */ + unsigned long currentMillis = millis(); //Send 30ms message if (currentMillis - previousMillis30 >= interval30) { previousMillis30 = currentMillis; - if(bms_status != FAULT){ + + if(bms_status == ACTIVE){ + send221still = 10; ESP32Can.CANWriteFrame(&TESLA_221_1); ESP32Can.CANWriteFrame(&TESLA_221_2); + } + else if(bms_status == FAULT){ + if(send221still > 0){ + ESP32Can.CANWriteFrame(&TESLA_221_1); + send221still--; + } + } + else{ + //Updating or some other state we dont use } } } From 1bf651abc20b3b1bcfe4e61f8b94bf2643ff16c1 Mon Sep 17 00:00:00 2001 From: Daniel Date: Sun, 17 Sep 2023 11:24:20 +0300 Subject: [PATCH 3/6] Add HVIL safety --- Software/TESLA-MODEL-3-BATTERY.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Software/TESLA-MODEL-3-BATTERY.cpp b/Software/TESLA-MODEL-3-BATTERY.cpp index c0a185b7..8a41722f 100644 --- a/Software/TESLA-MODEL-3-BATTERY.cpp +++ b/Software/TESLA-MODEL-3-BATTERY.cpp @@ -137,6 +137,11 @@ void update_values_tesla_model_3_battery() stillAliveCAN--; } + if (hvil_status == 3){ //INTERNAL_OPEN_FAULT - Someone disconnected a high voltage cable while battery was in use + bms_status = FAULT; + Serial.println("High voltage cable removed while battery running. Opening contactors!"); + } + if(cell_max_v >= MAX_CELL_VOLTAGE){ bms_status = FAULT; Serial.println("CELL OVERVOLTAGE!!! Stopping battery charging and discharging. Inspect battery!"); From 0c6fe1fc077d47c456b31c74ed1241885f2f654d Mon Sep 17 00:00:00 2001 From: Daniel Date: Sun, 17 Sep 2023 12:44:41 +0300 Subject: [PATCH 4/6] Contactor fix --- Software/TESLA-MODEL-3-BATTERY.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Software/TESLA-MODEL-3-BATTERY.cpp b/Software/TESLA-MODEL-3-BATTERY.cpp index 8a41722f..3fa724fe 100644 --- a/Software/TESLA-MODEL-3-BATTERY.cpp +++ b/Software/TESLA-MODEL-3-BATTERY.cpp @@ -364,14 +364,11 @@ the first, for a few cycles, then stop all messages which causes the contactor ESP32Can.CANWriteFrame(&TESLA_221_1); ESP32Can.CANWriteFrame(&TESLA_221_2); } - else if(bms_status == FAULT){ + else{ //bms_status == FAULT if(send221still > 0){ ESP32Can.CANWriteFrame(&TESLA_221_1); send221still--; } - } - else{ - //Updating or some other state we dont use } } } From cb0522fa44f8cde471f8d9a68aaa986f7695db90 Mon Sep 17 00:00:00 2001 From: Daniel Date: Sun, 17 Sep 2023 18:18:26 +0300 Subject: [PATCH 5/6] Fix for charge W value --- Software/TESLA-MODEL-3-BATTERY.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Software/TESLA-MODEL-3-BATTERY.cpp b/Software/TESLA-MODEL-3-BATTERY.cpp index 3fa724fe..47173346 100644 --- a/Software/TESLA-MODEL-3-BATTERY.cpp +++ b/Software/TESLA-MODEL-3-BATTERY.cpp @@ -105,13 +105,12 @@ void update_values_tesla_model_3_battery() max_target_discharge_power = temporaryvariable; } - //Calculate the allowed charge power, cap it if it gets too large - temporaryvariable = (max_charge_current * volts); - if(temporaryvariable > 60000){ - max_target_charge_power = 60000; + //The allowed charge power behaves strangely. We instead estimate this value + if(SOC == 10000){ + max_target_charge_power = 0; //When battery is 100% full, set allowed charge W to 0 } else{ - max_target_charge_power = temporaryvariable; + max_target_charge_power = 15000; //Otherwise we can push 15kW into the pack! } stat_batt_power = (volts * amps); //TODO, check if scaling is OK From 75595b3aa66103974ef124cc5e190f9b2d3dc122 Mon Sep 17 00:00:00 2001 From: Daniel Date: Sun, 17 Sep 2023 20:39:24 +0300 Subject: [PATCH 6/6] Map cellvoltages to variable used for inverter --- Software/NISSAN-LEAF-BATTERY.cpp | 3 +++ Software/NISSAN-LEAF-BATTERY.h | 2 ++ Software/TESLA-MODEL-3-BATTERY.cpp | 4 ++++ Software/TESLA-MODEL-3-BATTERY.h | 2 ++ 4 files changed, 11 insertions(+) diff --git a/Software/NISSAN-LEAF-BATTERY.cpp b/Software/NISSAN-LEAF-BATTERY.cpp index 1b61a00a..fd18a3d5 100644 --- a/Software/NISSAN-LEAF-BATTERY.cpp +++ b/Software/NISSAN-LEAF-BATTERY.cpp @@ -513,6 +513,9 @@ void receive_can_leaf_battery(CAN_frame_t rx_frame) cell_deviation_mV = (min_max_voltage[1] - min_max_voltage[0]); + cell_max_voltage = min_max_voltage[1]; + cell_min_voltage = min_max_voltage[0]; + if(cell_deviation_mV > MAX_CELL_DEVIATION){ LEDcolor = YELLOW; Serial.println("HIGH CELL DEVIATION!!! Inspect battery!"); diff --git a/Software/NISSAN-LEAF-BATTERY.h b/Software/NISSAN-LEAF-BATTERY.h index e0cf0381..878a9f72 100644 --- a/Software/NISSAN-LEAF-BATTERY.h +++ b/Software/NISSAN-LEAF-BATTERY.h @@ -21,6 +21,8 @@ extern uint16_t bms_char_dis_status; extern uint16_t stat_batt_power; extern uint16_t temperature_min; extern uint16_t temperature_max; +extern uint16_t cell_max_voltage; +extern uint16_t cell_min_voltage; extern uint8_t batteryAllowsContactorClosing; extern uint8_t LEDcolor; // Definitions for BMS status diff --git a/Software/TESLA-MODEL-3-BATTERY.cpp b/Software/TESLA-MODEL-3-BATTERY.cpp index 47173346..e5bbcd0c 100644 --- a/Software/TESLA-MODEL-3-BATTERY.cpp +++ b/Software/TESLA-MODEL-3-BATTERY.cpp @@ -121,6 +121,10 @@ void update_values_tesla_model_3_battery() max_temp = (max_temp * 10); temperature_max = convert2unsignedint16(max_temp); + cell_max_voltage = cell_max_v; + + cell_min_voltage = cell_min_v; + /* Value mapping is completed. Start to check all safeties */ bms_status = ACTIVE; //Startout in active mode before checking if we have any faults diff --git a/Software/TESLA-MODEL-3-BATTERY.h b/Software/TESLA-MODEL-3-BATTERY.h index 7eb15c6b..0bdfaed2 100644 --- a/Software/TESLA-MODEL-3-BATTERY.h +++ b/Software/TESLA-MODEL-3-BATTERY.h @@ -22,6 +22,8 @@ extern uint16_t stat_batt_power; extern uint16_t temperature_min; extern uint16_t temperature_max; extern uint16_t CANerror; +extern uint16_t cell_max_voltage; +extern uint16_t cell_min_voltage; extern uint8_t LEDcolor; // Definitions for BMS status #define STANDBY 0