diff --git a/Software/Software.ino b/Software/Software.ino index 8c2e24b0..b40f677b 100644 --- a/Software/Software.ino +++ b/Software/Software.ino @@ -226,6 +226,7 @@ void core_loop(void* task_time_us) { if (millis() - previousMillisUpdateVal >= intervalUpdateValues) // Every 5s normally { previousMillisUpdateVal = millis(); + update_machineryprotection(); update_SOC(); // Check if real or calculated SOC% value should be sent update_values(); // Update values heading towards inverter. Prepare for sending on CAN, or write directly to Modbus. if (DUMMY_EVENT_ENABLED) { @@ -459,36 +460,6 @@ void init_battery() { // Functions #ifdef DEBUG_CANFD_DATA void print_canfd_frame(CANFDMessage rx_frame) { - // Frame ID-s that battery transmits. For debugging and development. - // switch (frame.id) - // { - // case 0x7EC: - // case 0x360: - // case 0x3BA: - // case 0x325: - // case 0x330: - // case 0x215: - // case 0x235: - // case 0x2FA: - // case 0x21A: - // case 0x275: - // case 0x150: - // case 0x1F5: - // case 0x335: - // case 0x25A: - // case 0x365: - // case 0x055: - // case 0x245: - // case 0x3F5: - // // case 0x: - // // case 0x: - // // case 0x: - // // Dont print known frames - // return; - // default: - // break; - // } - int i = 0; Serial.print(rx_frame.id, HEX); Serial.print(" "); @@ -499,7 +470,6 @@ void print_canfd_frame(CANFDMessage rx_frame) { } Serial.println(" "); } - #endif void receive_canfd() { // This section checks if we have a complete CAN-FD message incoming CANFDMessage frame; diff --git a/Software/src/battery/BMW-I3-BATTERY.cpp b/Software/src/battery/BMW-I3-BATTERY.cpp index 73e2f743..36d273c4 100644 --- a/Software/src/battery/BMW-I3-BATTERY.cpp +++ b/Software/src/battery/BMW-I3-BATTERY.cpp @@ -15,8 +15,6 @@ static unsigned long previousMillis640 = 0; // will store last time a 600ms C static unsigned long previousMillis1000 = 0; // will store last time a 1000ms CAN Message was send static unsigned long previousMillis5000 = 0; // will store last time a 5000ms CAN Message was send static unsigned long previousMillis10000 = 0; // will store last time a 10000ms CAN Message was send -static uint8_t CANstillAlive = 12; // counter for checking if CAN is still alive -static uint16_t CANerror = 0; // counter on how many CAN errors encountered #define ALIVE_MAX_VALUE 14 // BMW CAN messages contain alive counter, goes from 0...14 enum BatterySize { BATTERY_60AH, BATTERY_94AH, BATTERY_120AH }; @@ -357,7 +355,6 @@ static uint16_t battery_soc = 0; static uint16_t battery_soc_hvmax = 0; static uint16_t battery_soc_hvmin = 0; static uint16_t battery_capacity_cah = 0; -static uint16_t battery_cell_deviation_mV = 0; static int16_t battery_temperature_HV = 0; static int16_t battery_temperature_heat_exchanger = 0; static int16_t battery_temperature_max = 0; @@ -454,27 +451,10 @@ void update_values_battery() { //This function maps all the values fetched via if (datalayer.battery.status.cell_voltages_mV[0] > 0 && datalayer.battery.status.cell_voltages_mV[2] > 0) { datalayer.battery.status.cell_min_voltage_mV = datalayer.battery.status.cell_voltages_mV[0]; datalayer.battery.status.cell_max_voltage_mV = datalayer.battery.status.cell_voltages_mV[2]; - - battery_cell_deviation_mV = - (datalayer.battery.status.cell_max_voltage_mV - datalayer.battery.status.cell_min_voltage_mV); - } else { - battery_cell_deviation_mV = 0; } if (battery_info_available) { // Start checking safeties. First up, cellvoltages! - if (battery_cell_deviation_mV > MAX_CELL_DEVIATION_MV) { - uint8_t report_value = 0; - if (battery_cell_deviation_mV <= 20 * 254) { - report_value = battery_cell_deviation_mV / 20; - } else { - report_value = 255; - } - - set_event(EVENT_CELL_DEVIATION_HIGH, report_value); - } else { - clear_event(EVENT_CELL_DEVIATION_HIGH); - } if (detectedBattery == BATTERY_60AH) { datalayer.battery.info.max_design_voltage_dV = MAX_PACK_VOLTAGE_60AH; datalayer.battery.info.min_design_voltage_dV = MIN_PACK_VOLTAGE_60AH; @@ -505,18 +485,6 @@ void update_values_battery() { //This function maps all the values fetched via } } - /* Check if the BMS is still sending CAN messages. If we go 60s without messages we raise an error*/ - if (!CANstillAlive) { - set_event(EVENT_CAN_RX_FAILURE, 0); - } else { - CANstillAlive--; - clear_event(EVENT_CAN_RX_FAILURE); - } - // Check if we have encountered any malformed CAN messages - if (CANerror > MAX_CAN_FAILURES) { - set_event(EVENT_CAN_RX_WARNING, 0); - } - // Perform other safety checks if (battery_status_error_locking == 2) { // HVIL seated? set_event(EVENT_HVIL_FAILURE, 0); @@ -559,7 +527,8 @@ void receive_can_battery(CAN_frame_t rx_frame) { switch (rx_frame.MsgID) { case 0x112: //BMS [10ms] Status Of High-Voltage Battery - 2 battery_awake = true; - CANstillAlive = 12; //This message is only sent if 30C (Wakeup pin on battery) is energized with 12V + datalayer.battery.status.CAN_battery_still_alive = + 12; //This message is only sent if 30C (Wakeup pin on battery) is energized with 12V battery_current = (rx_frame.data.u8[1] << 8 | rx_frame.data.u8[0]) - 8192; //deciAmps (-819.2 to 819.0A) battery_volts = (rx_frame.data.u8[3] << 8 | rx_frame.data.u8[2]); //500.0 V battery_HVBatt_SOC = ((rx_frame.data.u8[5] & 0x0F) << 8 | rx_frame.data.u8[4]); @@ -596,7 +565,7 @@ void receive_can_battery(CAN_frame_t rx_frame) { battery_awake = true; if (calculateCRC(rx_frame, rx_frame.FIR.B.DLC, 0x15) != rx_frame.data.u8[0]) { //If calculated CRC does not match transmitted CRC, increase CANerror counter - CANerror++; + datalayer.battery.status.CAN_error_counter++; break; } battery_status_diagnostics_HV = (rx_frame.data.u8[2] & 0x0F); diff --git a/Software/src/battery/CHADEMO-BATTERY.cpp b/Software/src/battery/CHADEMO-BATTERY.cpp index 3d3f9f3a..9054d059 100644 --- a/Software/src/battery/CHADEMO-BATTERY.cpp +++ b/Software/src/battery/CHADEMO-BATTERY.cpp @@ -8,7 +8,6 @@ /* Do not change code below unless you are sure what you are doing */ static unsigned long previousMillis100 = 0; // will store last time a 100ms CAN Message was send -static uint8_t CANstillAlive = 12; //counter for checking if CAN is still alive CAN_frame_t CHADEMO_108 = {.FIR = {.B = { @@ -105,14 +104,6 @@ void update_values_battery() { //This function maps all the values fetched via datalayer.battery.status.remaining_capacity_Wh = static_cast( (static_cast(datalayer.battery.status.real_soc) / 10000) * datalayer.battery.info.total_capacity_Wh); - /* Check if the Vehicle is still sending CAN messages. If we go 60s without messages we raise an error*/ - if (!CANstillAlive) { - set_event(EVENT_CAN_RX_FAILURE, 0); - } else { - CANstillAlive--; - clear_event(EVENT_CAN_RX_FAILURE); - } - #ifdef DEBUG_VIA_USB Serial.print("SOC 0x100: "); Serial.println(ConstantOfChargingRateIndication); @@ -120,7 +111,8 @@ void update_values_battery() { //This function maps all the values fetched via } void receive_can_battery(CAN_frame_t rx_frame) { - CANstillAlive == 12; //We are getting CAN messages from the vehicle, inform the watchdog + datalayer.battery.status.CAN_battery_still_alive == + 12; //We are getting CAN messages from the vehicle, inform the watchdog switch (rx_frame.MsgID) { case 0x100: diff --git a/Software/src/battery/CHADEMO-BATTERY.h b/Software/src/battery/CHADEMO-BATTERY.h index 910f17d4..f58bb636 100644 --- a/Software/src/battery/CHADEMO-BATTERY.h +++ b/Software/src/battery/CHADEMO-BATTERY.h @@ -5,6 +5,7 @@ #include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h" #define BATTERY_SELECTED +#define MAX_CELL_DEVIATION 9999 void setup_battery(void); diff --git a/Software/src/battery/IMIEV-CZERO-ION-BATTERY.cpp b/Software/src/battery/IMIEV-CZERO-ION-BATTERY.cpp index 98e10570..2e79b55e 100644 --- a/Software/src/battery/IMIEV-CZERO-ION-BATTERY.cpp +++ b/Software/src/battery/IMIEV-CZERO-ION-BATTERY.cpp @@ -10,8 +10,7 @@ //Figure out if CAN messages need to be sent to keep the system happy? /* Do not change code below unless you are sure what you are doing */ -static uint8_t CANstillAlive = 12; //counter for checking if CAN is still alive -static uint8_t errorCode = 0; //stores if we have an error code active from battery control logic +static uint8_t errorCode = 0; //stores if we have an error code active from battery control logic static uint8_t BMU_Detected = 0; static uint8_t CMU_Detected = 0; @@ -108,14 +107,6 @@ void update_values_battery() { //This function maps all the values fetched via datalayer.battery.status.temperature_min_dC = (int16_t)(max_temp_cel * 10); - /* Check if the BMS is still sending CAN messages. If we go 60s without messages we raise an error*/ - if (!CANstillAlive) { - set_event(EVENT_CAN_RX_FAILURE, 0); - } else { - CANstillAlive--; - clear_event(EVENT_CAN_RX_FAILURE); - } - if (!BMU_Detected) { #ifdef DEBUG_VIA_USB Serial.println("BMU not detected, check wiring!"); @@ -144,7 +135,7 @@ void update_values_battery() { //This function maps all the values fetched via } void receive_can_battery(CAN_frame_t rx_frame) { - CANstillAlive = + datalayer.battery.status.CAN_battery_still_alive = 12; //TODO: move this inside a known message ID to prevent CAN inverter from keeping battery alive detection going switch (rx_frame.MsgID) { case 0x374: //BMU message, 10ms - SOC diff --git a/Software/src/battery/IMIEV-CZERO-ION-BATTERY.h b/Software/src/battery/IMIEV-CZERO-ION-BATTERY.h index 8300c1ab..8de35314 100644 --- a/Software/src/battery/IMIEV-CZERO-ION-BATTERY.h +++ b/Software/src/battery/IMIEV-CZERO-ION-BATTERY.h @@ -5,6 +5,7 @@ #include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h" #define BATTERY_SELECTED +#define MAX_CELL_DEVIATION_MV 500 void setup_battery(void); diff --git a/Software/src/battery/KIA-E-GMP-BATTERY.cpp b/Software/src/battery/KIA-E-GMP-BATTERY.cpp index de685c5c..f7122633 100644 --- a/Software/src/battery/KIA-E-GMP-BATTERY.cpp +++ b/Software/src/battery/KIA-E-GMP-BATTERY.cpp @@ -9,11 +9,9 @@ /* Do not change code below unless you are sure what you are doing */ static unsigned long previousMillis500ms = 0; // will store last time a 500ms CAN Message was send -static uint8_t CANstillAlive = 12; //counter for checking if CAN is still alive -#define MAX_CELL_VOLTAGE 4250 //Battery is put into emergency stop if one cell goes over this value -#define MIN_CELL_VOLTAGE 2950 //Battery is put into emergency stop if one cell goes below this value -#define MAX_CELL_DEVIATION 150 //LED turns yellow on the board if mv delta exceeds this value +#define MAX_CELL_VOLTAGE 4250 //Battery is put into emergency stop if one cell goes over this value +#define MIN_CELL_VOLTAGE 2950 //Battery is put into emergency stop if one cell goes below this value static uint16_t inverterVoltageFrameHigh = 0; static uint16_t inverterVoltage = 0; @@ -23,7 +21,6 @@ static uint16_t SOC_Display = 0; static uint16_t batterySOH = 1000; static uint16_t CellVoltMax_mV = 3700; static uint16_t CellVoltMin_mV = 3700; -static uint16_t cell_deviation_mV = 0; static uint16_t batteryVoltage = 0; static int16_t leadAcidBatteryVoltage = 120; static int16_t batteryAmps = 0; @@ -97,10 +94,10 @@ void update_values_battery() { //This function maps all the values fetched via datalayer.battery.status.cell_min_voltage_mV = CellVoltMin_mV; /* Check if the BMS is still sending CAN messages. If we go 60s without messages we raise an error*/ - if (!CANstillAlive) { + if (!datalayer.battery.status.CAN_battery_still_alive) { set_event(EVENT_CANFD_RX_FAILURE, 0); } else { - CANstillAlive--; + datalayer.battery.status.CAN_battery_still_alive--; clear_event(EVENT_CANFD_RX_FAILURE); } @@ -113,19 +110,12 @@ void update_values_battery() { //This function maps all the values fetched via } // Check if cell voltages are within allowed range - cell_deviation_mV = (datalayer.battery.status.cell_max_voltage_mV - datalayer.battery.status.cell_min_voltage_mV); - if (CellVoltMax_mV >= MAX_CELL_VOLTAGE) { set_event(EVENT_CELL_OVER_VOLTAGE, 0); } if (CellVoltMin_mV <= MIN_CELL_VOLTAGE) { set_event(EVENT_CELL_UNDER_VOLTAGE, 0); } - if (cell_deviation_mV > MAX_CELL_DEVIATION) { - set_event(EVENT_CELL_DEVIATION_HIGH, 0); - } else { - clear_event(EVENT_CELL_DEVIATION_HIGH); - } if (datalayer.battery.status.bms_status == FAULT) { //Incase we enter a critical fault state, zero out the allowed limits @@ -208,7 +198,7 @@ void send_canfd_frame(CANFDMessage frame) { } void receive_canfd_battery(CANFDMessage frame) { - CANstillAlive = 12; + datalayer.battery.status.CAN_battery_still_alive = 12; switch (frame.id) { case 0x7EC: // print_canfd_frame(frame); diff --git a/Software/src/battery/KIA-E-GMP-BATTERY.h b/Software/src/battery/KIA-E-GMP-BATTERY.h index 9802b0ac..d7b3620d 100644 --- a/Software/src/battery/KIA-E-GMP-BATTERY.h +++ b/Software/src/battery/KIA-E-GMP-BATTERY.h @@ -8,7 +8,7 @@ extern ACAN2517FD canfd; #define BATTERY_SELECTED - +#define MAX_CELL_DEVIATION_MV 150 #define MAXCHARGEPOWERALLOWED 10000 #define MAXDISCHARGEPOWERALLOWED 10000 diff --git a/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp b/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp index 806ec093..a43aef44 100644 --- a/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp +++ b/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp @@ -9,11 +9,9 @@ /* Do not change code below unless you are sure what you are doing */ static unsigned long previousMillis100 = 0; // will store last time a 100ms CAN Message was send static unsigned long previousMillis10 = 0; // will store last time a 10s CAN Message was send -static uint8_t CANstillAlive = 12; //counter for checking if CAN is still alive -#define MAX_CELL_VOLTAGE 4250 //Battery is put into emergency stop if one cell goes over this value -#define MIN_CELL_VOLTAGE 2950 //Battery is put into emergency stop if one cell goes below this value -#define MAX_CELL_DEVIATION 150 //LED turns yellow on the board if mv delta exceeds this value +#define MAX_CELL_VOLTAGE 4250 //Battery is put into emergency stop if one cell goes over this value +#define MIN_CELL_VOLTAGE 2950 //Battery is put into emergency stop if one cell goes below this value static uint16_t soc_calculated = 0; static uint16_t SOC_BMS = 0; @@ -21,7 +19,6 @@ static uint16_t SOC_Display = 0; static uint16_t batterySOH = 1000; static uint16_t CellVoltMax_mV = 3700; static uint16_t CellVoltMin_mV = 3700; -static uint16_t cell_deviation_mV = 0; static uint16_t allowedDischargePower = 0; static uint16_t allowedChargePower = 0; static uint16_t batteryVoltage = 0; @@ -182,14 +179,6 @@ void update_values_battery() { //This function maps all the values fetched via datalayer.battery.status.cell_min_voltage_mV = CellVoltMin_mV; - /* Check if the BMS is still sending CAN messages. If we go 60s without messages we raise an error*/ - if (!CANstillAlive) { - set_event(EVENT_CAN_RX_FAILURE, 0); - } else { - CANstillAlive--; - clear_event(EVENT_CAN_RX_FAILURE); - } - if (waterleakageSensor == 0) { set_event(EVENT_WATER_INGRESS, 0); } @@ -216,19 +205,12 @@ void update_values_battery() { //This function maps all the values fetched via } // Check if cell voltages are within allowed range - cell_deviation_mV = (datalayer.battery.status.cell_max_voltage_mV - datalayer.battery.status.cell_min_voltage_mV); - if (CellVoltMax_mV >= MAX_CELL_VOLTAGE) { set_event(EVENT_CELL_OVER_VOLTAGE, 0); } if (CellVoltMin_mV <= MIN_CELL_VOLTAGE) { set_event(EVENT_CELL_UNDER_VOLTAGE, 0); } - if (cell_deviation_mV > MAX_CELL_DEVIATION) { - set_event(EVENT_CELL_DEVIATION_HIGH, 0); - } else { - clear_event(EVENT_CELL_DEVIATION_HIGH); - } if (datalayer.battery.status.bms_status == FAULT) { //Incase we enter a critical fault state, zero out the allowed limits @@ -305,8 +287,8 @@ void receive_can_battery(CAN_frame_t rx_frame) { break; case 0x542: //BMS SOC startedUp = true; - CANstillAlive = 12; //We use this message to verify that BMS is still alive - SOC_Display = rx_frame.data.u8[0] * 5; //100% = 200 ( 200 * 5 = 1000 ) + datalayer.battery.status.CAN_battery_still_alive = 12; //We use this message to verify that BMS is still alive + SOC_Display = rx_frame.data.u8[0] * 5; //100% = 200 ( 200 * 5 = 1000 ) break; case 0x594: startedUp = true; diff --git a/Software/src/battery/KIA-HYUNDAI-64-BATTERY.h b/Software/src/battery/KIA-HYUNDAI-64-BATTERY.h index 1425eaa9..1e8c25f1 100644 --- a/Software/src/battery/KIA-HYUNDAI-64-BATTERY.h +++ b/Software/src/battery/KIA-HYUNDAI-64-BATTERY.h @@ -5,6 +5,7 @@ #include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h" #define BATTERY_SELECTED +#define MAX_CELL_DEVIATION_MV 150 void setup_battery(void); diff --git a/Software/src/battery/NISSAN-LEAF-BATTERY.cpp b/Software/src/battery/NISSAN-LEAF-BATTERY.cpp index e9a024c6..5ad901b9 100644 --- a/Software/src/battery/NISSAN-LEAF-BATTERY.cpp +++ b/Software/src/battery/NISSAN-LEAF-BATTERY.cpp @@ -13,8 +13,6 @@ static unsigned long previousMillis10 = 0; // will store last time a 10ms CAN Message was send static unsigned long previousMillis100 = 0; // will store last time a 100ms CAN Message was send static unsigned long previousMillis10s = 0; // will store last time a 1s CAN Message was send -static uint16_t CANerror = 0; //counter on how many CAN errors encountered -static uint8_t CANstillAlive = 12; //counter for checking if CAN is still alive static uint8_t mprun10r = 0; //counter 0-20 for 0x1F2 message static uint8_t mprun10 = 0; //counter 0-3 static uint8_t mprun100 = 0; //counter 0-3 @@ -91,7 +89,6 @@ static uint8_t crctable[256] = { static uint8_t LEAF_Battery_Type = ZE0_BATTERY; #define MAX_CELL_VOLTAGE 4250 //Battery is put into emergency stop if one cell goes over this value #define MIN_CELL_VOLTAGE 2700 //Battery is put into emergency stop if one cell goes below this value -#define MAX_CELL_DEVIATION 500 //LED turns yellow on the board if mv delta exceeds this value #define WH_PER_GID 77 //One GID is this amount of Watt hours static uint16_t LB_Discharge_Power_Limit = 0; //Limit in kW static uint16_t LB_Charge_Power_Limit = 0; //Limit in kW @@ -136,10 +133,9 @@ static uint8_t stop_battery_query = 1; static uint8_t hold_off_with_polling_10seconds = 10; static uint16_t cell_voltages[97]; //array with all the cellvoltages static uint8_t cellcounter = 0; -static uint16_t min_max_voltage[2]; //contains cell min[0] and max[1] values in mV -static uint16_t cell_deviation_mV = 0; //contains the deviation between highest and lowest cell in mV -static uint16_t HX = 0; //Internal resistance -static uint16_t insulation = 0; //Insulation resistance +static uint16_t min_max_voltage[2]; //contains cell min[0] and max[1] values in mV +static uint16_t HX = 0; //Internal resistance +static uint16_t insulation = 0; //Insulation resistance static uint16_t temp_raw_1 = 0; static uint8_t temp_raw_2_highnibble = 0; static uint16_t temp_raw_2 = 0; @@ -308,14 +304,6 @@ void update_values_battery() { /* This function maps all the values fetched via clear_event(EVENT_BATTERY_CHG_DISCHG_STOP_REQ); } - if (LB_StateOfHealth < 25) { //Battery is extremely degraded, not fit for secondlifestorage. Zero it all out. - if (LB_StateOfHealth != 0) { //Extra check to see that we actually have a SOH Value available - set_event(EVENT_LOW_SOH, LB_StateOfHealth); - } else { - clear_event(EVENT_LOW_SOH); - } - } - #ifdef INTERLOCK_REQUIRED if (!LB_Interlock) { set_event(EVENT_HVIL_FAILURE, 0); @@ -324,19 +312,6 @@ void update_values_battery() { /* This function maps all the values fetched via } #endif - /* Check if the BMS is still sending CAN messages. If we go 60s without messages we raise an error*/ - if (!CANstillAlive) { - set_event(EVENT_CAN_RX_FAILURE, 0); - } else { - CANstillAlive--; - clear_event(EVENT_CAN_RX_FAILURE); - } - if (CANerror > - MAX_CAN_FAILURES) //Also check if we have recieved too many malformed CAN messages. If so, signal via LED - { - set_event(EVENT_CAN_RX_WARNING, 0); - } - if (LB_HeatExist) { if (LB_Heating_Stop) { set_event(EVENT_BATTERY_WARMED_UP, 0); @@ -361,7 +336,6 @@ void update_values_battery() { /* This function maps all the values fetched via print_with_units(", Has heater: ", LB_HeatExist, " "); print_with_units(", Max cell voltage: ", min_max_voltage[1], "mV "); print_with_units(", Min cell voltage: ", min_max_voltage[0], "mV "); - print_with_units(", Cell deviation: ", cell_deviation_mV, "mV "); #endif } @@ -369,7 +343,7 @@ void receive_can_battery(CAN_frame_t rx_frame) { switch (rx_frame.MsgID) { case 0x1DB: if (is_message_corrupt(rx_frame)) { - CANerror++; + datalayer.battery.status.CAN_error_counter++; break; //Message content malformed, abort reading data from it } LB_Current2 = (rx_frame.data.u8[0] << 3) | (rx_frame.data.u8[1] & 0xe0) >> 5; @@ -394,7 +368,7 @@ void receive_can_battery(CAN_frame_t rx_frame) { break; case 0x1DC: if (is_message_corrupt(rx_frame)) { - CANerror++; + datalayer.battery.status.CAN_error_counter++; break; //Message content malformed, abort reading data from it } LB_Discharge_Power_Limit = ((rx_frame.data.u8[0] << 2 | rx_frame.data.u8[1] >> 6) / 4.0); @@ -403,7 +377,7 @@ void receive_can_battery(CAN_frame_t rx_frame) { break; case 0x55B: if (is_message_corrupt(rx_frame)) { - CANerror++; + datalayer.battery.status.CAN_error_counter++; break; //Message content malformed, abort reading data from it } LB_TEMP = (rx_frame.data.u8[0] << 2 | rx_frame.data.u8[1] >> 6); @@ -413,7 +387,8 @@ void receive_can_battery(CAN_frame_t rx_frame) { LB_Capacity_Empty = (bool)((rx_frame.data.u8[6] & 0x80) >> 7); break; case 0x5BC: - CANstillAlive = 12; //Indicate that we are still getting CAN messages from the BMS + datalayer.battery.status.CAN_battery_still_alive = + 12; //Indicate that we are still getting CAN messages from the BMS LB_MAX = ((rx_frame.data.u8[5] & 0x10) >> 4); if (LB_MAX) { @@ -521,15 +496,9 @@ void receive_can_battery(CAN_frame_t rx_frame) { min_max_voltage[1] = cell_voltages[cellcounter]; } - cell_deviation_mV = (min_max_voltage[1] - min_max_voltage[0]); - datalayer.battery.status.cell_max_voltage_mV = min_max_voltage[1]; datalayer.battery.status.cell_min_voltage_mV = min_max_voltage[0]; - if (cell_deviation_mV > MAX_CELL_DEVIATION) { - set_event(EVENT_CELL_DEVIATION_HIGH, 0); - } - if (min_max_voltage[1] >= MAX_CELL_VOLTAGE) { set_event(EVENT_CELL_OVER_VOLTAGE, 0); } diff --git a/Software/src/battery/NISSAN-LEAF-BATTERY.h b/Software/src/battery/NISSAN-LEAF-BATTERY.h index e3a8eca8..e2b1a7d9 100644 --- a/Software/src/battery/NISSAN-LEAF-BATTERY.h +++ b/Software/src/battery/NISSAN-LEAF-BATTERY.h @@ -6,6 +6,7 @@ #include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h" #define BATTERY_SELECTED +#define MAX_CELL_DEVIATION_MV 500 uint16_t Temp_fromRAW_to_F(uint16_t temperature); bool is_message_corrupt(CAN_frame_t rx_frame); diff --git a/Software/src/battery/PYLON-BATTERY.cpp b/Software/src/battery/PYLON-BATTERY.cpp index f9c3db33..e11e25e2 100644 --- a/Software/src/battery/PYLON-BATTERY.cpp +++ b/Software/src/battery/PYLON-BATTERY.cpp @@ -15,7 +15,6 @@ /* Do not change code below unless you are sure what you are doing */ static unsigned long previousMillis1000 = 0; // will store last time a 1s CAN Message was sent -static uint8_t CANstillAlive = 12; //counter for checking if CAN is still alive //Actual content messages CAN_frame_t PYLON_3010 = {.FIR = {.B = @@ -96,18 +95,10 @@ void update_values_battery() { datalayer.battery.info.max_design_voltage_dV = charge_cutoff_voltage; datalayer.battery.info.min_design_voltage_dV = discharge_cutoff_voltage; - - /* Check if the BMS is still sending CAN messages. If we go 60s without messages we raise an error*/ - if (!CANstillAlive) { - set_event(EVENT_CAN_RX_FAILURE, 0); - } else { - CANstillAlive--; - clear_event(EVENT_CAN_RX_FAILURE); - } } void receive_can_battery(CAN_frame_t rx_frame) { - CANstillAlive = 12; + datalayer.battery.status.CAN_battery_still_alive = 12; switch (rx_frame.MsgID) { case 0x7310: case 0x7311: diff --git a/Software/src/battery/PYLON-BATTERY.h b/Software/src/battery/PYLON-BATTERY.h index 0233c649..f8f796f6 100644 --- a/Software/src/battery/PYLON-BATTERY.h +++ b/Software/src/battery/PYLON-BATTERY.h @@ -5,6 +5,7 @@ #include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h" #define BATTERY_SELECTED +#define MAX_CELL_DEVIATION 9999 void setup_battery(void); diff --git a/Software/src/battery/RENAULT-KANGOO-BATTERY.cpp b/Software/src/battery/RENAULT-KANGOO-BATTERY.cpp index da91487b..994e0600 100644 --- a/Software/src/battery/RENAULT-KANGOO-BATTERY.cpp +++ b/Software/src/battery/RENAULT-KANGOO-BATTERY.cpp @@ -34,9 +34,7 @@ static uint16_t LB_Charge_Power_Limit = 0; static uint16_t LB_kWh_Remaining = 0; static uint16_t LB_Cell_Max_Voltage = 3700; static uint16_t LB_Cell_Min_Voltage = 3700; -static uint16_t cell_deviation_mV = 0; //contains the deviation between highest and lowest cell in mV static uint16_t LB_MaxChargeAllowed_W = 0; -static uint8_t CANstillAlive = 12; //counter for checking if CAN is still alive static uint8_t LB_Discharge_Power_Limit_Byte1 = 0; static uint8_t GVI_Pollcounter = 0; static uint8_t LB_EOCR = 0; @@ -130,27 +128,12 @@ void update_values_battery() { //This function maps all the values fetched via datalayer.battery.status.cell_max_voltage_mV = LB_Cell_Max_Voltage; - cell_deviation_mV = (datalayer.battery.status.cell_max_voltage_mV - datalayer.battery.status.cell_min_voltage_mV); - - /* Check if the BMS is still sending CAN messages. If we go 60s without messages we raise an error*/ - if (!CANstillAlive) { - set_event(EVENT_CAN_RX_FAILURE, 0); - } else { - CANstillAlive--; - clear_event(EVENT_CAN_RX_FAILURE); - } - if (LB_Cell_Max_Voltage >= ABSOLUTE_CELL_MAX_VOLTAGE) { set_event(EVENT_CELL_OVER_VOLTAGE, (LB_Cell_Max_Voltage / 20)); } if (LB_Cell_Min_Voltage <= ABSOLUTE_CELL_MIN_VOLTAGE) { set_event(EVENT_CELL_UNDER_VOLTAGE, (LB_Cell_Min_Voltage / 20)); } - if (cell_deviation_mV > MAX_CELL_DEVIATION_MV) { - set_event(EVENT_CELL_DEVIATION_HIGH, (cell_deviation_mV / 20)); - } else { - clear_event(EVENT_CELL_DEVIATION_HIGH); - } #ifdef DEBUG_VIA_USB Serial.println("Values going to inverter:"); @@ -189,14 +172,16 @@ void update_values_battery() { //This function maps all the values fetched via void receive_can_battery(CAN_frame_t rx_frame) { switch (rx_frame.MsgID) { - case 0x155: //BMS1 - CANstillAlive = 12; //Indicate that we are still getting CAN messages from the BMS + case 0x155: //BMS1 + datalayer.battery.status.CAN_battery_still_alive = + 12; //Indicate that we are still getting CAN messages from the BMS LB_MaxChargeAllowed_W = (rx_frame.data.u8[0] * 300); LB_Current = word((rx_frame.data.u8[1] & 0xF), rx_frame.data.u8[2]) * 0.25 - 500; //OK! LB_SOC = ((rx_frame.data.u8[4] << 8) | (rx_frame.data.u8[5])) * 0.0025; //OK! break; - case 0x424: //BMS2 - CANstillAlive = 12; //Indicate that we are still getting CAN messages from the BMS + case 0x424: //BMS2 + datalayer.battery.status.CAN_battery_still_alive = + 12; //Indicate that we are still getting CAN messages from the BMS LB_EOCR = (rx_frame.data.u8[0] & 0x03); LB_HVBUV = (rx_frame.data.u8[0] & 0x0C) >> 2; LB_HVBIR = (rx_frame.data.u8[0] & 0x30) >> 4; @@ -212,11 +197,13 @@ void receive_can_battery(CAN_frame_t rx_frame) { LB_MAX_TEMPERATURE = ((rx_frame.data.u8[7]) - 40); //OK! break; case 0x425: - CANstillAlive = 12; //Indicate that we are still getting CAN messages from the BMS + datalayer.battery.status.CAN_battery_still_alive = + 12; //Indicate that we are still getting CAN messages from the BMS LB_kWh_Remaining = word((rx_frame.data.u8[0] & 0x1), rx_frame.data.u8[1]) / 10; //OK! break; case 0x445: - CANstillAlive = 12; //Indicate that we are still getting CAN messages from the BMS + datalayer.battery.status.CAN_battery_still_alive = + 12; //Indicate that we are still getting CAN messages from the BMS LB_Cell_Max_Voltage = 1000 + word((rx_frame.data.u8[3] & 0x1), rx_frame.data.u8[4]) * 10; //OK! LB_Cell_Min_Voltage = 1000 + (word(rx_frame.data.u8[5], rx_frame.data.u8[6]) >> 7) * 10; //OK! @@ -227,7 +214,8 @@ void receive_can_battery(CAN_frame_t rx_frame) { } break; case 0x7BB: - CANstillAlive = 12; //Indicate that we are still getting CAN messages from the BMS + datalayer.battery.status.CAN_battery_still_alive = + 12; //Indicate that we are still getting CAN messages from the BMS if (rx_frame.data.u8[0] == 0x10) { //1st response Bytes 0-7 GVB_79B_Continue = true; diff --git a/Software/src/battery/RENAULT-ZOE-BATTERY.cpp b/Software/src/battery/RENAULT-ZOE-BATTERY.cpp index 60c8d353..a4b07bd5 100644 --- a/Software/src/battery/RENAULT-ZOE-BATTERY.cpp +++ b/Software/src/battery/RENAULT-ZOE-BATTERY.cpp @@ -7,8 +7,7 @@ #include "RENAULT-ZOE-BATTERY.h" /* Do not change code below unless you are sure what you are doing */ -static uint8_t CANstillAlive = 12; //counter for checking if CAN is still alive -static uint8_t errorCode = 0; //stores if we have an error code active from battery control logic +static uint8_t errorCode = 0; //stores if we have an error code active from battery control logic static uint16_t LB_SOC = 50; static uint16_t LB_SOH = 99; static int16_t LB_MIN_TEMPERATURE = 0; @@ -21,7 +20,6 @@ static int32_t LB_Current = 0; static uint16_t LB_kWh_Remaining = 0; static uint16_t LB_Cell_Max_Voltage = 3700; static uint16_t LB_Cell_Min_Voltage = 3700; -static uint16_t cell_deviation_mV = 0; //contains the deviation between highest and lowest cell in mV static uint32_t LB_Battery_Voltage = 3700; static uint8_t LB_Discharge_Power_Limit_Byte1 = 0; @@ -65,27 +63,12 @@ void update_values_battery() { //This function maps all the values fetched via datalayer.battery.status.cell_max_voltage_mV; - cell_deviation_mV = (datalayer.battery.status.cell_max_voltage_mV - datalayer.battery.status.cell_min_voltage_mV); - - /* Check if the BMS is still sending CAN messages. If we go 60s without messages we raise an error*/ - if (!CANstillAlive) { - set_event(EVENT_CAN_RX_FAILURE, 0); - } else { - CANstillAlive--; - clear_event(EVENT_CAN_RX_FAILURE); - } - if (LB_Cell_Max_Voltage >= ABSOLUTE_CELL_MAX_VOLTAGE) { set_event(EVENT_CELL_OVER_VOLTAGE, 0); } if (LB_Cell_Min_Voltage <= ABSOLUTE_CELL_MIN_VOLTAGE) { set_event(EVENT_CELL_UNDER_VOLTAGE, 0); } - if (cell_deviation_mV > MAX_CELL_DEVIATION_MV) { - set_event(EVENT_CELL_DEVIATION_HIGH, 0); - } else { - clear_event(EVENT_CELL_DEVIATION_HIGH); - } #ifdef DEBUG_VIA_USB Serial.println("Values going to inverter:"); @@ -122,7 +105,7 @@ void update_values_battery() { //This function maps all the values fetched via } void receive_can_battery(CAN_frame_t rx_frame) { - + datalayer.battery.status.CAN_battery_still_alive = 12; switch (rx_frame.MsgID) { case 0x42E: //HV SOC & Battery Temp & Charging Power break; diff --git a/Software/src/battery/RENAULT-ZOE-BATTERY.h b/Software/src/battery/RENAULT-ZOE-BATTERY.h index 723d7928..129925fc 100644 --- a/Software/src/battery/RENAULT-ZOE-BATTERY.h +++ b/Software/src/battery/RENAULT-ZOE-BATTERY.h @@ -5,11 +5,9 @@ #define BATTERY_SELECTED -#define ABSOLUTE_CELL_MAX_VOLTAGE \ - 4100 // Max Cell Voltage mV! if voltage goes over this, charging is not possible (goes into forced discharge) -#define ABSOLUTE_CELL_MIN_VOLTAGE \ - 3000 // Min Cell Voltage mV! if voltage goes under this, discharging further is disabled -#define MAX_CELL_DEVIATION_MV 500 //LED turns yellow on the board if mv delta exceeds this value +#define ABSOLUTE_CELL_MAX_VOLTAGE 4100 +#define ABSOLUTE_CELL_MIN_VOLTAGE 3000 +#define MAX_CELL_DEVIATION_MV 500 void setup_battery(void); diff --git a/Software/src/battery/SANTA-FE-PHEV-BATTERY.cpp b/Software/src/battery/SANTA-FE-PHEV-BATTERY.cpp index b033f594..75420388 100644 --- a/Software/src/battery/SANTA-FE-PHEV-BATTERY.cpp +++ b/Software/src/battery/SANTA-FE-PHEV-BATTERY.cpp @@ -18,7 +18,6 @@ TODO: Map all values from battery CAN messages /* Do not change code below unless you are sure what you are doing */ static unsigned long previousMillis10 = 0; // will store last time a 10ms CAN Message was send static unsigned long previousMillis100 = 0; // will store last time a 100ms CAN Message was send -static uint8_t CANstillAlive = 12; //counter for checking if CAN is still alive static int SOC_1 = 0; static int SOC_2 = 0; @@ -77,21 +76,13 @@ void update_values_battery() { //This function maps all the values fetched via datalayer.battery.status.temperature_max_dC; - /* Check if the BMS is still sending CAN messages. If we go 60s without messages we raise an error*/ - if (!CANstillAlive) { - set_event(EVENT_CAN_RX_FAILURE, 0); - } else { - CANstillAlive--; - clear_event(EVENT_CAN_RX_FAILURE); - } - #ifdef DEBUG_VIA_USB #endif } void receive_can_battery(CAN_frame_t rx_frame) { - CANstillAlive = 12; + datalayer.battery.status.CAN_battery_still_alive = 12; switch (rx_frame.MsgID) { case 0x200: break; diff --git a/Software/src/battery/SANTA-FE-PHEV-BATTERY.h b/Software/src/battery/SANTA-FE-PHEV-BATTERY.h index b6b4a1ee..0773af3f 100644 --- a/Software/src/battery/SANTA-FE-PHEV-BATTERY.h +++ b/Software/src/battery/SANTA-FE-PHEV-BATTERY.h @@ -5,6 +5,7 @@ #include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h" #define BATTERY_SELECTED +#define MAX_CELL_DEVIATION 250 uint8_t CalculateCRC8(CAN_frame_t rx_frame); void setup_battery(void); diff --git a/Software/src/battery/TESLA-MODEL-3-BATTERY.cpp b/Software/src/battery/TESLA-MODEL-3-BATTERY.cpp index 9f28ad4b..544bde06 100644 --- a/Software/src/battery/TESLA-MODEL-3-BATTERY.cpp +++ b/Software/src/battery/TESLA-MODEL-3-BATTERY.cpp @@ -10,7 +10,6 @@ /* 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 uint8_t stillAliveCAN = 6; //counter for checking if CAN is still alive CAN_frame_t TESLA_221_1 = { .FIR = {.B = @@ -232,14 +231,6 @@ void update_values_battery() { //This function maps all the values fetched via /* Value mapping is completed. Start to check all safeties */ - /* Check if the BMS is still sending CAN messages. If we go 60s without messages we raise an error*/ - if (!stillAliveCAN) { - set_event(EVENT_CAN_RX_FAILURE, 0); - } else { - stillAliveCAN--; - clear_event(EVENT_CAN_RX_FAILURE); - } - if (hvil_status == 3) { //INTERNAL_OPEN_FAULT - Someone disconnected a high voltage cable while battery was in use set_event(EVENT_INTERNAL_OPEN_FAULT, 0); } else { @@ -513,7 +504,7 @@ void receive_can_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 + datalayer.battery.status.CAN_battery_still_alive = 12; //We are getting CAN messages from the BMS bat_beginning_of_life = (((rx_frame.data.u8[6] & 0x03) << 8) | rx_frame.data.u8[5]); 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)); diff --git a/Software/src/battery/TESLA-MODEL-3-BATTERY.h b/Software/src/battery/TESLA-MODEL-3-BATTERY.h index 3761242a..6eb725bc 100644 --- a/Software/src/battery/TESLA-MODEL-3-BATTERY.h +++ b/Software/src/battery/TESLA-MODEL-3-BATTERY.h @@ -8,6 +8,7 @@ //#define LFP_CHEMISTRY // Enable this line to startup in LFP mode #define RAMPDOWN_SOC 900 // 90.0 SOC% to start ramping down from max charge power towards 0 at 100.00% +#define MAX_CELL_DEVIATION 9999 // Handled inside the Tesla.cpp file, just for compilation #define FLOAT_MAX_POWER_W 200 // W, what power to allow for top balancing battery #define FLOAT_START_MV 20 // mV, how many mV under overvoltage to start float charging #define MAXCHARGEPOWERALLOWED 15000 // 15000W we use a define since the value supplied by Tesla is always 0 diff --git a/Software/src/battery/TEST-FAKE-BATTERY.h b/Software/src/battery/TEST-FAKE-BATTERY.h index 1331345d..29433a38 100644 --- a/Software/src/battery/TEST-FAKE-BATTERY.h +++ b/Software/src/battery/TEST-FAKE-BATTERY.h @@ -3,6 +3,7 @@ #include "../include.h" #define BATTERY_SELECTED +#define MAX_CELL_DEVIATION 9999 void setup_battery(void); diff --git a/Software/src/battery/VOLVO-SPA-BATTERY.cpp b/Software/src/battery/VOLVO-SPA-BATTERY.cpp index 1c9733c7..c3b910da 100644 --- a/Software/src/battery/VOLVO-SPA-BATTERY.cpp +++ b/Software/src/battery/VOLVO-SPA-BATTERY.cpp @@ -9,11 +9,9 @@ /* Do not change code below unless you are sure what you are doing */ static unsigned long previousMillis100 = 0; // will store last time a 100ms CAN Message was send static unsigned long previousMillis60s = 0; // will store last time a 60s CAN Message was send -static uint8_t CANstillAlive = 12; //counter for checking if CAN is still alive -#define MAX_CELL_VOLTAGE 4210 //Battery is put into emergency stop if one cell goes over this value -#define MIN_CELL_VOLTAGE 2700 //Battery is put into emergency stop if one cell goes below this value -#define MAX_CELL_DEVIATION 500 //LED turns yellow on the board if mv delta exceeds this value +#define MAX_CELL_VOLTAGE 4210 //Battery is put into emergency stop if one cell goes over this value +#define MIN_CELL_VOLTAGE 2700 //Battery is put into emergency stop if one cell goes below this value static float BATT_U = 0; //0x3A static float MAX_U = 0; //0x3A @@ -26,16 +24,14 @@ static float BATT_T_MIN = 0; //0x413 static float BATT_T_AVG = 0; //0x413 static uint16_t SOC_BMS = 0; //0X37D static uint16_t SOC_CALC = 0; -static uint16_t CELL_U_MAX = 0; //0x37D -static uint16_t CELL_U_MIN = 0; //0x37D -static uint8_t CELL_ID_U_MAX = 0; //0x37D -static uint16_t HvBattPwrLimDchaSoft = 0; //0x369 - +static uint16_t CELL_U_MAX = 0; //0x37D +static uint16_t CELL_U_MIN = 0; //0x37D +static uint8_t CELL_ID_U_MAX = 0; //0x37D +static uint16_t HvBattPwrLimDchaSoft = 0; //0x369 static uint8_t batteryModuleNumber = 0x10; // First battery module static uint8_t battery_request_idx = 0; static uint8_t rxConsecutiveFrames = 0; -static uint16_t min_max_voltage[2]; //contains cell min[0] and max[1] values in mV -static uint16_t cell_deviation_mV = 0; //contains the deviation between highest and lowest cell in mV +static uint16_t min_max_voltage[2]; //contains cell min[0] and max[1] values in mV static uint8_t cellcounter = 0; static uint32_t remaining_capacity = 0; static uint16_t cell_voltages[108]; //array with all the cellvoltages @@ -114,14 +110,6 @@ void update_values_battery() { //This function maps all the values fetched via datalayer.battery.status.cell_voltages_mV[i] = cell_voltages[i]; } - /* Check if the BMS is still sending CAN messages. If we go 60s without messages we raise an error*/ - if (!CANstillAlive) { - set_event(EVENT_CAN_RX_FAILURE, 0); - } else { - CANstillAlive--; - clear_event(EVENT_CAN_RX_FAILURE); - } - #ifdef DEBUG_VIA_USB Serial.print("BMS reported SOC%: "); Serial.println(SOC_BMS); @@ -159,8 +147,6 @@ void update_values_battery() { //This function maps all the values fetched via Serial.println(min_max_voltage[1]); Serial.print("Lowest cell voltage: "); Serial.println(min_max_voltage[0]); - Serial.print("Cell deviation voltage: "); - Serial.println(cell_deviation_mV); Serial.print("Cell voltage,"); while (cnt < 108) { Serial.print(cell_voltages[cnt++]); @@ -171,7 +157,7 @@ void update_values_battery() { //This function maps all the values fetched via } void receive_can_battery(CAN_frame_t rx_frame) { - CANstillAlive = 12; + datalayer.battery.status.CAN_battery_still_alive = 12; switch (rx_frame.MsgID) { case 0x3A: if ((rx_frame.data.u8[6] & 0x80) == 0x80) @@ -314,12 +300,6 @@ void receive_can_battery(CAN_frame_t rx_frame) { min_max_voltage[1] = cell_voltages[cellcounter]; } - cell_deviation_mV = (min_max_voltage[1] - min_max_voltage[0]); - - if (cell_deviation_mV > MAX_CELL_DEVIATION) { - set_event(EVENT_CELL_DEVIATION_HIGH, 0); - } - if (min_max_voltage[1] >= MAX_CELL_VOLTAGE) { set_event(EVENT_CELL_OVER_VOLTAGE, 0); } diff --git a/Software/src/battery/VOLVO-SPA-BATTERY.h b/Software/src/battery/VOLVO-SPA-BATTERY.h index 403fbac8..1d861f69 100644 --- a/Software/src/battery/VOLVO-SPA-BATTERY.h +++ b/Software/src/battery/VOLVO-SPA-BATTERY.h @@ -5,6 +5,7 @@ #include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h" #define BATTERY_SELECTED +#define MAX_CELL_DEVIATION_MV 250 void setup_battery(void); diff --git a/Software/src/datalayer/datalayer.h b/Software/src/datalayer/datalayer.h index 4c44ccfc..6d6be61c 100644 --- a/Software/src/datalayer/datalayer.h +++ b/Software/src/datalayer/datalayer.h @@ -68,6 +68,11 @@ typedef struct { * battery.settings.soc_scaling_active */ uint16_t reported_soc; + /** A counter that increases incase a CAN CRC read error occurs */ + uint16_t CAN_error_counter; + /** uint8_t */ + /** A counter set each time a new message comes from battery.*/ + uint8_t CAN_battery_still_alive = 12; /** Other */ /** The current BMS status */ diff --git a/Software/src/devboard/safety/safety.cpp b/Software/src/devboard/safety/safety.cpp new file mode 100644 index 00000000..8c875145 --- /dev/null +++ b/Software/src/devboard/safety/safety.cpp @@ -0,0 +1,52 @@ +#include "../../datalayer/datalayer.h" +#include "../utils/events.h" + +static uint16_t cell_deviation_mV = 0; + +void update_machineryprotection() { + // Start checking that the battery is within reason. Incase we see any funny business, raise an event! + + // Battery is overheated! + if (datalayer.battery.status.temperature_max_dC > 500) { + set_event(EVENT_BATTERY_OVERHEAT, datalayer.battery.status.temperature_max_dC); + } else { + clear_event(EVENT_BATTERY_OVERHEAT); + } + + // Battery is frozen! + if (datalayer.battery.status.temperature_min_dC < -250) { + set_event(EVENT_BATTERY_FROZEN, datalayer.battery.status.temperature_min_dC); + } else { + clear_event(EVENT_BATTERY_FROZEN); + } + + // Battery is extremely degraded, not fit for secondlifestorage + if (datalayer.battery.status.soh_pptt < 2500) { + set_event(EVENT_LOW_SOH, datalayer.battery.status.soh_pptt); + } else { + clear_event(EVENT_LOW_SOH); + } + + // Check diff between highest and lowest cell + cell_deviation_mV = (datalayer.battery.status.cell_max_voltage_mV - datalayer.battery.status.cell_min_voltage_mV); + if (cell_deviation_mV > MAX_CELL_DEVIATION_MV) { + set_event(EVENT_CELL_DEVIATION_HIGH, (cell_deviation_mV / 20)); + } else { + clear_event(EVENT_CELL_DEVIATION_HIGH); + } + + // Check if the BMS is still sending CAN messages. If we go 60s without messages we raise an error + if (!datalayer.battery.status.CAN_battery_still_alive) { + set_event(EVENT_CAN_RX_FAILURE, 0); + } else { + datalayer.battery.status.CAN_battery_still_alive--; + clear_event(EVENT_CAN_RX_FAILURE); + } + + // Also check if we have recieved too many malformed CAN messages + if (datalayer.battery.status.CAN_error_counter > MAX_CAN_FAILURES) { + set_event(EVENT_CAN_RX_WARNING, 0); + } else { + clear_event(EVENT_CAN_RX_WARNING); + } +} diff --git a/Software/src/devboard/safety/safety.h b/Software/src/devboard/safety/safety.h new file mode 100644 index 00000000..27347014 --- /dev/null +++ b/Software/src/devboard/safety/safety.h @@ -0,0 +1,9 @@ +#ifndef SAFETY_H +#define SAFETY_H +#include + +#define MAX_CAN_FAILURES 50 + +void update_machineryprotection(); + +#endif diff --git a/Software/src/devboard/utils/events.cpp b/Software/src/devboard/utils/events.cpp index e40fb218..c60ad481 100644 --- a/Software/src/devboard/utils/events.cpp +++ b/Software/src/devboard/utils/events.cpp @@ -144,10 +144,12 @@ void init_events(void) { events.entries[EVENT_KWH_PLAUSIBILITY_ERROR].level = EVENT_LEVEL_INFO; events.entries[EVENT_BATTERY_EMPTY].level = EVENT_LEVEL_INFO; events.entries[EVENT_BATTERY_FULL].level = EVENT_LEVEL_INFO; + events.entries[EVENT_BATTERY_FROZEN].level = EVENT_LEVEL_INFO; events.entries[EVENT_BATTERY_CAUTION].level = EVENT_LEVEL_INFO; events.entries[EVENT_BATTERY_CHG_STOP_REQ].level = EVENT_LEVEL_ERROR; events.entries[EVENT_BATTERY_DISCHG_STOP_REQ].level = EVENT_LEVEL_ERROR; events.entries[EVENT_BATTERY_CHG_DISCHG_STOP_REQ].level = EVENT_LEVEL_ERROR; + events.entries[EVENT_BATTERY_OVERHEAT].level = EVENT_LEVEL_ERROR; events.entries[EVENT_LOW_SOH].level = EVENT_LEVEL_ERROR; events.entries[EVENT_HVIL_FAILURE].level = EVENT_LEVEL_ERROR; events.entries[EVENT_PRECHARGE_FAILURE].level = EVENT_LEVEL_INFO; @@ -220,6 +222,8 @@ const char* get_event_message_string(EVENTS_ENUM_TYPE event) { return "Info: Battery is completely discharged"; case EVENT_BATTERY_FULL: return "Info: Battery is fully charged"; + case EVENT_BATTERY_FROZEN: + return "Info: Battery is too cold to operate optimally. Consider warming it up!"; case EVENT_BATTERY_CAUTION: return "Info: Battery has raised a general caution flag. Might want to inspect it closely."; case EVENT_BATTERY_CHG_STOP_REQ: @@ -232,6 +236,8 @@ const char* get_event_message_string(EVENTS_ENUM_TYPE event) { return "Info: COLD BATTERY! Battery requesting heating pads to activate!"; case EVENT_BATTERY_WARMED_UP: return "Info: Battery requesting heating pads to stop. The battery is now warm enough."; + case EVENT_BATTERY_OVERHEAT: + return "ERROR: Battery overheated. Shutting down to prevent thermal runaway!"; case EVENT_LOW_SOH: return "ERROR: State of health critically low. Battery internal resistance too high to continue. Recycle " "battery."; diff --git a/Software/src/devboard/utils/events.h b/Software/src/devboard/utils/events.h index ae2ff9e9..cfbff87f 100644 --- a/Software/src/devboard/utils/events.h +++ b/Software/src/devboard/utils/events.h @@ -6,7 +6,7 @@ // #define INCLUDE_EVENTS_TEST // Enable to run an event test loop, see events_test_on_target.cpp -#define EE_MAGIC_HEADER_VALUE 0x0004 // 0x0000 to 0xFFFF +#define EE_MAGIC_HEADER_VALUE 0x0005 // 0x0000 to 0xFFFF #define GENERATE_ENUM(ENUM) ENUM, #define GENERATE_STRING(STRING) #STRING, @@ -38,10 +38,12 @@ XX(EVENT_KWH_PLAUSIBILITY_ERROR) \ XX(EVENT_BATTERY_EMPTY) \ XX(EVENT_BATTERY_FULL) \ + XX(EVENT_BATTERY_FROZEN) \ XX(EVENT_BATTERY_CAUTION) \ XX(EVENT_BATTERY_CHG_STOP_REQ) \ XX(EVENT_BATTERY_DISCHG_STOP_REQ) \ XX(EVENT_BATTERY_CHG_DISCHG_STOP_REQ) \ + XX(EVENT_BATTERY_OVERHEAT) \ XX(EVENT_BATTERY_REQUESTS_HEAT) \ XX(EVENT_BATTERY_WARMED_UP) \ XX(EVENT_LOW_SOH) \ diff --git a/Software/src/devboard/utils/types.h b/Software/src/devboard/utils/types.h index ac37adca..7a6cc67a 100644 --- a/Software/src/devboard/utils/types.h +++ b/Software/src/devboard/utils/types.h @@ -28,6 +28,4 @@ enum led_color { GREEN, YELLOW, RED, BLUE, RGB }; #define INTERVAL_100_MS_DELAYED 120 #define INTERVAL_500_MS_DELAYED 550 -#define MAX_CAN_FAILURES 500 // Amount of malformed CAN messages to allow before raising a warning - #endif diff --git a/Software/src/include.h b/Software/src/include.h index 5722fc5f..7db1b640 100644 --- a/Software/src/include.h +++ b/Software/src/include.h @@ -8,6 +8,7 @@ #include "system_settings.h" #include "devboard/hal/hal.h" +#include "devboard/safety/safety.h" #include "devboard/utils/time_meas.h" #include "devboard/utils/types.h"