From 202991e76a79f799c15d025ca276436c803db2c8 Mon Sep 17 00:00:00 2001 From: Daniel Date: Wed, 10 Jan 2024 20:05:07 +0200 Subject: [PATCH 01/13] Add CAN sending for contactors --- .../src/battery/KIA-HYUNDAI-64-BATTERY.cpp | 65 +++++++++++++++++-- Software/src/battery/KIA-HYUNDAI-64-BATTERY.h | 32 ++++----- 2 files changed, 76 insertions(+), 21 deletions(-) diff --git a/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp b/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp index 146a1436..9fc0e627 100644 --- a/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp +++ b/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp @@ -4,9 +4,9 @@ /* 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 unsigned long previousMillis10s = 0; // will store last time a 100ms CAN Message was send static const int interval10 = 10; // interval (ms) at which send CAN Messages -static const int interval100 = 100; // interval (ms) at which send CAN Messages +static const int interval10s = 10000; // interval (ms) at which send CAN Messages static uint8_t CANstillAlive = 12; //counter for checking if CAN is still alive #define LB_MAX_SOC 1000 //BMS never goes over this value. We use this info to rescale SOC% sent to Inverter @@ -16,6 +16,33 @@ static int SOC_1 = 0; static int SOC_2 = 0; static int SOC_3 = 0; +CAN_frame_t KIA_HYUNDAI_200 = {.FIR = {.B = + { + .DLC = 8, + .FF = CAN_frame_std, + }}, + .MsgID = 0x200, + //.data = {0x00, 0x00, 0x00, 0x04, 0x00, 0x50, 0xD0, 0x00}}; //Initial value + .data = {0x00, 0x80, 0xD8, 0x04, 0x00, 0x17, 0xD0, 0x00}}; //Mid log value +CAN_frame_t KIA_HYUNDAI_523 = {.FIR = {.B = + { + .DLC = 8, + .FF = CAN_frame_std, + }}, + .MsgID = 0x523, + //.data = {0x00, 0x38, 0x28, 0x28, 0x28, 0x28, 0x00, 0x01}}; //Initial value + .data = {0x08, 0x38, 0x36, 0x36, 0x33, 0x34, 0x00, 0x01}}; //Mid log value +CAN_frame_t KIA_HYUNDAI_524 = {.FIR = {.B = + { + .DLC = 8, + .FF = CAN_frame_std, + }}, + .MsgID = 0x524, + //.data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; //Initial value + .data = {0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; //Mid log value + +static uint8_t counter_200 = 0; + void update_values_kiaHyundai_64_battery() { //This function maps all the values fetched via CAN to the correct parameters used for modbus bms_status = ACTIVE; //Startout in active mode @@ -113,12 +140,38 @@ void receive_can_kiaHyundai_64_battery(CAN_frame_t rx_frame) { } void send_can_kiaHyundai_64_battery() { unsigned long currentMillis = millis(); - // Send 100ms CAN Message - if (currentMillis - previousMillis100 >= interval100) { - previousMillis100 = currentMillis; - } //Send 10ms message if (currentMillis - previousMillis10 >= interval10) { previousMillis10 = currentMillis; } + // Send 10s CAN Message + if (currentMillis - previousMillis10s >= interval10s) { + previousMillis10s = currentMillis; + + switch (counter_200) { + case 0: + KIA_HYUNDAI_200.data.u8[5] = 0x17; + ++counter_200; + break; + case 1: + KIA_HYUNDAI_200.data.u8[5] = 0x57; + ++counter_200; + break; + case 2: + KIA_HYUNDAI_200.data.u8[5] = 0x97; + ++counter_200; + break; + case 3: + KIA_HYUNDAI_200.data.u8[5] = 0xD7; + counter_200 = 0; + break; + } + + ESP32Can.CANWriteFrame(&KIA_HYUNDAI_200); + + ESP32Can.CANWriteFrame(&KIA_HYUNDAI_523); + + ESP32Can.CANWriteFrame(&KIA_HYUNDAI_524); + + } } diff --git a/Software/src/battery/KIA-HYUNDAI-64-BATTERY.h b/Software/src/battery/KIA-HYUNDAI-64-BATTERY.h index 7e1d506a..d4b99a2e 100644 --- a/Software/src/battery/KIA-HYUNDAI-64-BATTERY.h +++ b/Software/src/battery/KIA-HYUNDAI-64-BATTERY.h @@ -10,21 +10,23 @@ #define ABSOLUTE_MIN_VOLTAGE 3100 // 310.0V if battery voltage goes under this, discharging further is disabled // These parameters need to be mapped for the Gen24 -extern uint16_t SOC; -extern uint16_t StateOfHealth; -extern uint16_t battery_voltage; -extern uint16_t battery_current; -extern uint16_t capacity_Wh; -extern uint16_t remaining_capacity_Wh; -extern uint16_t max_target_discharge_power; -extern uint16_t max_target_charge_power; -extern uint8_t bms_status; -extern uint8_t bms_char_dis_status; -extern uint16_t stat_batt_power; -extern uint16_t temperature_min; -extern uint16_t temperature_max; -extern uint16_t CANerror; -extern bool batteryAllowsContactorClosing; //Bool, 1=true, 0=false +extern uint16_t SOC; //SOC%, 0-100.00 (0-10000) +extern uint16_t StateOfHealth; //SOH%, 0-100.00 (0-10000) +extern uint16_t battery_voltage; //V+1, 0-500.0 (0-5000) +extern uint16_t battery_current; //A+1, Goes thru convert2unsignedint16 function (5.0A = 50, -5.0A = 65485) +extern uint16_t capacity_Wh; //Wh, 0-60000 +extern uint16_t remaining_capacity_Wh; //Wh, 0-60000 +extern uint16_t max_target_discharge_power; //W, 0-60000 +extern uint16_t max_target_charge_power; //W, 0-60000 +extern uint8_t bms_status; //Enum, 0-5 +extern uint8_t bms_char_dis_status; //Enum, 0-2 +extern uint16_t stat_batt_power; //W, Goes thru convert2unsignedint16 function (5W = 5, -5W = 65530) +extern uint16_t temperature_min; //C+1, Goes thru convert2unsignedint16 function (15.0C = 150, -15.0C = 65385) +extern uint16_t temperature_max; //C+1, Goes thru convert2unsignedint16 function (15.0C = 150, -15.0C = 65385) +extern uint16_t cell_max_voltage; //mV, 0-4350 +extern uint16_t cell_min_voltage; //mV, 0-4350 +extern uint8_t LEDcolor; //Enum, 0-10 +extern bool batteryAllowsContactorClosing; //Bool, 1=true, 0=false extern bool inverterAllowsContactorClosing; //Bool, 1=true, 0=false void update_values_kiaHyundai_64_battery(); From e21d7b11c5e8d5099a073af85d50bd6ac524e5a2 Mon Sep 17 00:00:00 2001 From: Daniel Date: Wed, 10 Jan 2024 21:23:31 +0200 Subject: [PATCH 02/13] Improve 200 handling --- .../src/battery/KIA-HYUNDAI-64-BATTERY.cpp | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp b/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp index 9fc0e627..c0d1b547 100644 --- a/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp +++ b/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp @@ -103,7 +103,7 @@ void receive_can_kiaHyundai_64_battery(CAN_frame_t rx_frame) { break; case 0x4E2: break; - case 0x542: + case 0x542: //BMS SOC SOC_1 = rx_frame.data.u8[0]; break; case 0x594: @@ -163,7 +163,28 @@ void send_can_kiaHyundai_64_battery() { break; case 3: KIA_HYUNDAI_200.data.u8[5] = 0xD7; - counter_200 = 0; + ++counter_200; + break; + case 4: + KIA_HYUNDAI_200.data.u8[3] = 0x10; + KIA_HYUNDAI_200.data.u8[5] = 0xFF; + ++counter_200; + break; + case 5: + KIA_HYUNDAI_200.data.u8[5] = 0x3B; + ++counter_200; + break; + case 6: + KIA_HYUNDAI_200.data.u8[5] = 0x7B; + ++counter_200; + break; + case 7: + KIA_HYUNDAI_200.data.u8[5] = 0xBB; + ++counter_200; + break; + case 8: + KIA_HYUNDAI_200.data.u8[5] = 0xFB; + counter_200 = 5; break; } From 7a4afd795329bbb0c888f4cc996c3c0944a75c70 Mon Sep 17 00:00:00 2001 From: Daniel Date: Wed, 10 Jan 2024 21:37:38 +0200 Subject: [PATCH 03/13] Merge Kona64 branch changes --- .../src/battery/KIA-HYUNDAI-64-BATTERY.cpp | 171 ++++++++++++++++-- 1 file changed, 151 insertions(+), 20 deletions(-) diff --git a/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp b/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp index c0d1b547..5598bc02 100644 --- a/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp +++ b/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp @@ -3,18 +3,39 @@ #include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h" /* 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 previousMillis10s = 0; // will store last time a 100ms CAN Message was send -static const int interval10 = 10; // interval (ms) at which send CAN Messages +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 10s CAN Message was send +static const int interval100 = 100; // interval (ms) at which send CAN Messages static const int interval10s = 10000; // interval (ms) at which send CAN Messages static uint8_t CANstillAlive = 12; //counter for checking if CAN is still alive #define LB_MAX_SOC 1000 //BMS never goes over this value. We use this info to rescale SOC% sent to Inverter #define LB_MIN_SOC 0 //BMS never goes below this value. We use this info to rescale SOC% sent to Inverter -static int SOC_1 = 0; -static int SOC_2 = 0; -static int SOC_3 = 0; +static double SOC_BMS = 0; +static double SOC_Display = 0; +static int currentSensor = 0; +static int RES_WS0 = 0; +static int tempSensH = 0; +static double aux12volt = 0; +static int testdata0 = 0x0; +static int testdata1 = 0x0; +static int testdata2 = 0x0; +static int testdata3 = 0x0; +static int testdata4 = 0x0; +static int testdata5 = 0x0; +static int testdata6 = 0x0; +static int CoolWaterSensor = 0; +static int poll_data_pid = 0; +static int battSOH = 0; +static int CellVoltMax = 0; +static int CellVmaxNo = 0; +static int CellVoltMin = 0; +static int CellVminNo = 0; +static int allowedDischargePower = 0; +static int allowedChargePower = 0; +static double battVolts = 0; +static double battAmps = 0; CAN_frame_t KIA_HYUNDAI_200 = {.FIR = {.B = { @@ -41,12 +62,23 @@ CAN_frame_t KIA_HYUNDAI_524 = {.FIR = {.B = //.data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; //Initial value .data = {0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; //Mid log value +CAN_frame_t KIA64_7E4_id1 = {.FIR = {.B = {.DLC = 8,.FF = CAN_frame_std,}},.MsgID = 0x7E4,.data = {0x03, 0x22, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00}}; //Poll PID 03 22 01 01 +CAN_frame_t KIA64_7E4_id2 = {.FIR = {.B = {.DLC = 8,.FF = CAN_frame_std,}},.MsgID = 0x7E4,.data = {0x03, 0x22, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00}}; //Poll PID 03 22 01 02 +CAN_frame_t KIA64_7E4_id3 = {.FIR = {.B = {.DLC = 8,.FF = CAN_frame_std,}},.MsgID = 0x7E4,.data = {0x03, 0x22, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00}}; //Poll PID 03 22 01 03 +CAN_frame_t KIA64_7E4_id4 = {.FIR = {.B = {.DLC = 8,.FF = CAN_frame_std,}},.MsgID = 0x7E4,.data = {0x03, 0x22, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00}}; //Poll PID 03 22 01 04 +CAN_frame_t KIA64_7E4_id5 = {.FIR = {.B = {.DLC = 8,.FF = CAN_frame_std,}},.MsgID = 0x7E4,.data = {0x03, 0x22, 0x01, 0x05, 0x00, 0x00, 0x00, 0x00}}; //Poll PID 03 22 01 05 +CAN_frame_t KIA64_7E4_id6 = {.FIR = {.B = {.DLC = 8,.FF = CAN_frame_std,}},.MsgID = 0x7E4,.data = {0x03, 0x22, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00}}; //Poll PID 03 22 01 06 + +CAN_frame_t KIA64_7E4_ack = {.FIR = {.B = {.DLC = 8,.FF = CAN_frame_std,}},.MsgID = 0x7E4,.data = {0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; //Ack frame, correct PID is returned + + + static uint8_t counter_200 = 0; void update_values_kiaHyundai_64_battery() { //This function maps all the values fetched via CAN to the correct parameters used for modbus bms_status = ACTIVE; //Startout in active mode - SOC; + SOC = (SOC_Display * 100); //Increase decimals from 50% -> 50.00% battery_voltage; @@ -75,12 +107,45 @@ void update_values_kiaHyundai_64_battery() { //This function maps all the value } #ifdef DEBUG_VIA_USB - Serial.print("SOC% candidate 1: "); - Serial.println(SOC_1); - Serial.print("SOC% candidate 2: "); - Serial.println(SOC_2); - Serial.print("SOC% candidate 3: "); - Serial.println(SOC_3); + Serial.println("Values from battery: "); + Serial.print("SOC% BMS: "); + Serial.print(SOC_BMS); + Serial.print(" | SOC% Display: "); + Serial.println(SOC_Display); + Serial.print("SOC%*100: "); + Serial.println(SOC); + Serial.print("BatteryCurrent: "); + Serial.println(currentSensor); + Serial.print("Vattensensor: "); + Serial.println(RES_WS0); + Serial.print("HighestTemp: "); + Serial.print(tempSensH); + Serial.println("°C"); + Serial.print("Aux12volt: "); + Serial.print(aux12volt); + Serial.println("V"); + Serial.print("SOH*10 "); + Serial.println(battSOH); + Serial.print("MaxCellVolt "); + Serial.print(CellVoltMax); + Serial.print(" mV No "); + Serial.print(CellVmaxNo); + Serial.print(" | MinCellVolt "); + Serial.print(CellVoltMin); + Serial.print(" mV No "); + Serial.println(CellVminNo); + Serial.print("CoolingWaterSensor "); + Serial.print(CoolWaterSensor); + Serial.println("°C"); + Serial.print("Allowed Chargepower "); + Serial.print(allowedChargePower); + Serial.print(" W | Allowed Dischargepower "); + Serial.print(allowedDischargePower); + Serial.println(" W"); + Serial.print(battAmps); + Serial.print(" Amps | "); + Serial.print(battVolts); + Serial.println(" Volts"); #endif } @@ -104,19 +169,20 @@ void receive_can_kiaHyundai_64_battery(CAN_frame_t rx_frame) { case 0x4E2: break; case 0x542: //BMS SOC - SOC_1 = rx_frame.data.u8[0]; + SOC_Display = (rx_frame.data.u8[0] / 2.00); break; case 0x594: - SOC_2 = rx_frame.data.u8[5]; + SOC_BMS = (rx_frame.data.u8[5] / 2.00); break; case 0x595: break; case 0x596: + aux12volt = (rx_frame.data.u8[1] / 10.00); + tempSensH = (rx_frame.data.u8[7]); break; case 0x597: break; case 0x598: - SOC_3 = (rx_frame.data.u8[4] * 256.0 + rx_frame.data.u8[5]); break; case 0x599: break; @@ -127,22 +193,87 @@ void receive_can_kiaHyundai_64_battery(CAN_frame_t rx_frame) { case 0x5A3: break; case 0x5D5: + RES_WS0 = rx_frame.data.u8[3]; // water sensor break; case 0x5D6: + currentSensor = (((rx_frame.data.u8[3] << 8) + rx_frame.data.u8[2]) / 10.0); //strömsensor break; case 0x5D7: break; case 0x5D8: break; - default: +case 0x7EC: //Data From polled PID group + switch (rx_frame.data.u8[0]) + { + case 0x10: //"PID Header" + if (rx_frame.data.u8[4] == poll_data_pid){ + ESP32Can.CANWriteFrame(&KIA64_7E4_ack); //Send ack to BMS if the same frame is sent as polled + } break; + case 0x21: //First datarow in PID group + if (poll_data_pid == 1){ + allowedChargePower = ((rx_frame.data.u8[3] << 8) + rx_frame.data.u8[4]); + allowedDischargePower = ((rx_frame.data.u8[5] << 8) + rx_frame.data.u8[6]); + } + if (poll_data_pid == 6){ + CoolWaterSensor = rx_frame.data.u8[2]; + } + break; + case 0x22: //Second datarow in PID group + if (poll_data_pid == 1){ + battAmps = (((rx_frame.data.u8[1] << 8) + rx_frame.data.u8[2]) / 10.0); + battVolts = (((rx_frame.data.u8[3] << 8) + rx_frame.data.u8[4]) / 10.0); + } + break; + case 0x23: //Third datarow in PID group + if (poll_data_pid == 1){ + CellVoltMax = (rx_frame.data.u8[7] * 20); //(volts *50) *20 =mV + } + break; + case 0x24: //Fourth datarow in PID group + if (poll_data_pid == 1){ + CellVmaxNo = rx_frame.data.u8[1]; + CellVminNo = rx_frame.data.u8[3]; + CellVoltMin = (rx_frame.data.u8[2] * 20); //(volts *50) *20 =mV + } + if (poll_data_pid == 5){ + battSOH = ((rx_frame.data.u8[2] << 8) + rx_frame.data.u8[3]); + } + break; + case 0x25: //Fifth datarow in PID group + break; + case 0x26: //Sixth datarow in PID group + break; + case 0x27: //Seventh datarow in PID group + break; + case 0x28: //Eighth datarow in PID group + break; + } + default: + break; } } void send_can_kiaHyundai_64_battery() { unsigned long currentMillis = millis(); - //Send 10ms message - if (currentMillis - previousMillis10 >= interval10) { - previousMillis10 = currentMillis; + //Send 100ms message + if (currentMillis - previousMillis100 >= interval100) { + previousMillis100 = currentMillis; + if (poll_data_pid >= 6){ + poll_data_pid = 0; + } + poll_data_pid++; + if (poll_data_pid == 1){ + ESP32Can.CANWriteFrame(&KIA64_7E4_id1); + } + else if (poll_data_pid == 2){ + ESP32Can.CANWriteFrame(&KIA64_7E4_id2); + } + else if (poll_data_pid == 5){ + ESP32Can.CANWriteFrame(&KIA64_7E4_id5); + } + else if (poll_data_pid == 6){ + ESP32Can.CANWriteFrame(&KIA64_7E4_id6); + } } // Send 10s CAN Message if (currentMillis - previousMillis10s >= interval10s) { From 0db4cbe55b555fe31f05e1beec70017da7bfa692 Mon Sep 17 00:00:00 2001 From: Daniel Date: Thu, 11 Jan 2024 21:24:54 +0200 Subject: [PATCH 04/13] Fixes from ml265 --- .../src/battery/KIA-HYUNDAI-64-BATTERY.cpp | 422 ++++++++++++------ 1 file changed, 282 insertions(+), 140 deletions(-) diff --git a/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp b/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp index 5598bc02..282d4514 100644 --- a/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp +++ b/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp @@ -4,38 +4,60 @@ /* 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 previousMillis10s = 0; // will store last time a 10s CAN Message was send +static unsigned long previousMillis10ms = 0; // will store last time a 10s CAN Message was send static const int interval100 = 100; // interval (ms) at which send CAN Messages -static const int interval10s = 10000; // interval (ms) at which send CAN Messages +static const int interval10ms = 10; // interval (ms) at which send CAN Messages static uint8_t CANstillAlive = 12; //counter for checking if CAN is still alive #define LB_MAX_SOC 1000 //BMS never goes over this value. We use this info to rescale SOC% sent to Inverter #define LB_MIN_SOC 0 //BMS never goes below this value. We use this info to rescale SOC% sent to Inverter -static double SOC_BMS = 0; -static double SOC_Display = 0; -static int currentSensor = 0; -static int RES_WS0 = 0; -static int tempSensH = 0; -static double aux12volt = 0; -static int testdata0 = 0x0; -static int testdata1 = 0x0; -static int testdata2 = 0x0; -static int testdata3 = 0x0; -static int testdata4 = 0x0; -static int testdata5 = 0x0; -static int testdata6 = 0x0; -static int CoolWaterSensor = 0; -static int poll_data_pid = 0; -static int battSOH = 0; -static int CellVoltMax = 0; -static int CellVmaxNo = 0; -static int CellVoltMin = 0; -static int CellVminNo = 0; -static int allowedDischargePower = 0; -static int allowedChargePower = 0; -static double battVolts = 0; -static double battAmps = 0; +static int16_t SOC_BMS = 0; +static int16_t SOC_Display = 0; +static int16_t battSOH = 0; +static int16_t leakSens = 0; +static int16_t aux12volt = 0; +static int16_t CellVoltMax = 0; +static int16_t CellVmaxNo = 0; +static int16_t CellVoltMin = 0; +static int16_t CellVminNo = 0; +static int16_t allowedDischargePower = 0; +static int16_t allowedChargePower = 0; +static int16_t battVolts = 0; +static int16_t battAmps = 0; +static int8_t tempMax = 0; +static int8_t tempMin = 0; +static int8_t temp1 = 0; +static int8_t temp2 = 0; +static int8_t temp3 = 0; +static int8_t temp4 = 0; +static int8_t tempinlet = 0; +static uint8_t battMagntMode = 0; +static uint8_t BMS_ign = 0; +static int16_t poll_data_pid = 0; +static int16_t poll109 = 0; +static int16_t pollA2A = 0; +static int16_t poll200 = 0; +static int16_t poll201 = 0; +static int16_t poll2B0 = 0; +static int16_t poll450 = 0; +static int16_t poll471 = 0; +static int16_t poll523 = 0; +static int8_t heatertemp = 0; +//static int airbag = 0; Not needed +static int battrly = 0; +static int8_t PRAtemp = 0; +static int16_t Inv_VoltsTmp = 0; +static int16_t Inv_Volts = 0; +static uint8_t mode491 = 0; +static int8_t radiatorTemp = 0; +static int8_t chargeTemp = 0; +static int16_t frame524volts = 0; +static int8_t fanMode = 0; +static int8_t fanSpeed = 0; +static int8_t state3F6 = 0; +static uint counter = 0; +static int8_t sendDiagnostic = 0; CAN_frame_t KIA_HYUNDAI_200 = {.FIR = {.B = { @@ -62,6 +84,14 @@ CAN_frame_t KIA_HYUNDAI_524 = {.FIR = {.B = //.data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; //Initial value .data = {0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; //Mid log value +//553 Needed frame 200ms +CAN_frame_t KIA64_553 = {.FIR = {.B = {.DLC = 8,.FF = CAN_frame_std,}},.MsgID = 0x553,.data = {0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00}}; +//57F Needed frame 100ms +CAN_frame_t KIA64_57F = {.FIR = {.B = {.DLC = 8,.FF = CAN_frame_std,}},.MsgID = 0x57F,.data = {0x80, 0x0A, 0x72, 0x00, 0x00, 0x00, 0x00, 0x72}}; +//Needed frame 100ms +CAN_frame_t KIA64_2A1 = {.FIR = {.B = {.DLC = 8,.FF = CAN_frame_std,}},.MsgID = 0x2A1,.data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; + + CAN_frame_t KIA64_7E4_id1 = {.FIR = {.B = {.DLC = 8,.FF = CAN_frame_std,}},.MsgID = 0x7E4,.data = {0x03, 0x22, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00}}; //Poll PID 03 22 01 01 CAN_frame_t KIA64_7E4_id2 = {.FIR = {.B = {.DLC = 8,.FF = CAN_frame_std,}},.MsgID = 0x7E4,.data = {0x03, 0x22, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00}}; //Poll PID 03 22 01 02 CAN_frame_t KIA64_7E4_id3 = {.FIR = {.B = {.DLC = 8,.FF = CAN_frame_std,}},.MsgID = 0x7E4,.data = {0x03, 0x22, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00}}; //Poll PID 03 22 01 03 @@ -76,27 +106,34 @@ CAN_frame_t KIA64_7E4_ack = {.FIR = {.B = {.DLC = 8,.FF = CAN_frame_std,}},.MsgI static uint8_t counter_200 = 0; void update_values_kiaHyundai_64_battery() { //This function maps all the values fetched via CAN to the correct parameters used for modbus - bms_status = ACTIVE; //Startout in active mode + + SOC = (SOC_Display * 10); //Increase decimals from 50.0% -> 50.00% + + StateOfHealth = (battSOH * 10); //Increase decimals from 100.0% -> 100.00% - SOC = (SOC_Display * 100); //Increase decimals from 50% -> 50.00% + battery_voltage = (uint16_t)battVolts; //value is *10 - battery_voltage; - - battery_current; + battery_current = (int16_t)battAmps; //value is *10 //Todo, the signed part breaks something here for sure capacity_Wh = BATTERY_WH_MAX; - remaining_capacity_Wh; + remaining_capacity_Wh = ((SOC/10000)*BATTERY_WH_MAX); - max_target_discharge_power; + max_target_discharge_power = (uint16_t)allowedDischargePower * 10; //From kW*100 to Watts - max_target_charge_power; + max_target_charge_power = (uint16_t)allowedChargePower * 10; //From kW*100 to Watts - stat_batt_power; + stat_batt_power = ((uint16_t)battVolts * (int16_t)battAmps) / 100; //Power in watts, Negative = charging batt. //Todo, the signed part will break something here - temperature_min; + temperature_min = ((int8_t)tempMin * 10); //Increase decimals, 17C -> 17.0C + + temperature_max = ((int8_t)tempMax * 10); //Increase decimals, 18C -> 18.0C + + cell_max_voltage = CellVoltMax; //in millivolt + + cell_min_voltage = CellVoltMin; //in millivolt - temperature_max; + bms_status = ACTIVE; //Startout in active mode /* Check if the BMS is still sending CAN messages. If we go 60s without messages we raise an error*/ if (!CANstillAlive) { @@ -107,25 +144,26 @@ void update_values_kiaHyundai_64_battery() { //This function maps all the value } #ifdef DEBUG_VIA_USB + Serial.println(); //sepatator Serial.println("Values from battery: "); - Serial.print("SOC% BMS: "); - Serial.print(SOC_BMS); - Serial.print(" | SOC% Display: "); - Serial.println(SOC_Display); - Serial.print("SOC%*100: "); - Serial.println(SOC); - Serial.print("BatteryCurrent: "); - Serial.println(currentSensor); - Serial.print("Vattensensor: "); - Serial.println(RES_WS0); - Serial.print("HighestTemp: "); - Serial.print(tempSensH); - Serial.println("°C"); - Serial.print("Aux12volt: "); - Serial.print(aux12volt); - Serial.println("V"); - Serial.print("SOH*10 "); - Serial.println(battSOH); + Serial.print("SOC BMS: "); + Serial.print((int16_t)SOC_BMS / 10.0, 1); + Serial.print("% | SOC Display: "); + Serial.print((int16_t)SOC_Display / 10.0, 1); + Serial.print("% | SOH "); + Serial.print((int16_t)battSOH / 10.0, 1); + Serial.println("%"); + Serial.print((int16_t)battAmps / 10.0, 1); + Serial.print(" Amps | "); + Serial.print((int16_t)battVolts / 10.0, 1); + Serial.print(" Volts | "); + Serial.print((int16_t)stat_batt_power); + Serial.println(" Watts"); + Serial.print("Allowed Charge "); + Serial.print((uint16_t)allowedChargePower * 10); + Serial.print(" W | Allowed Discharge "); + Serial.print((uint16_t)allowedDischargePower * 10); + Serial.println(" W"); Serial.print("MaxCellVolt "); Serial.print(CellVoltMax); Serial.print(" mV No "); @@ -134,27 +172,72 @@ void update_values_kiaHyundai_64_battery() { //This function maps all the value Serial.print(CellVoltMin); Serial.print(" mV No "); Serial.println(CellVminNo); - Serial.print("CoolingWaterSensor "); - Serial.print(CoolWaterSensor); + Serial.print("TempHi "); + Serial.print((int8_t)tempMax); + Serial.print("°C TempLo "); + Serial.print((int8_t)tempMin); + //Serial.print("°C Temp1 "); + //Serial.print((int8_t)temp1); + //Serial.print("°C Temp2 "); + //Serial.print((int8_t)temp2); + //Serial.print("°C Temp3 "); + //Serial.print((int8_t)temp3); + //Serial.print("°C Temp4 "); + //Serial.print((int8_t)temp4); + Serial.print("°C WaterInlet "); + Serial.print((int8_t)tempinlet); + Serial.print("°C PowerRelay "); + Serial.print((int8_t)PRAtemp * 2); Serial.println("°C"); - Serial.print("Allowed Chargepower "); - Serial.print(allowedChargePower); - Serial.print(" W | Allowed Dischargepower "); - Serial.print(allowedDischargePower); - Serial.println(" W"); - Serial.print(battAmps); - Serial.print(" Amps | "); - Serial.print(battVolts); + Serial.print("Aux12volt: "); + Serial.print((int16_t)aux12volt / 10.0, 1); + Serial.print("V | "); + Serial.print("LeakSensor: "); + Serial.println(leakSens); + Serial.print("BmsMagementMode "); + Serial.print((uint8_t)battMagntMode, BIN); + //Serial.print(" | IgnitionBIN "); + //Serial.print((uint8_t)BMS_ign, BIN); //bit 2=IGN + if (bitRead((uint8_t)BMS_ign, 2) == 1){ + Serial.print(" | BmsIgitionON"); + } + else { + Serial.print(" | BmsIgitionOFF"); + } + //Serial.print(" | mode491 "); + //Serial.println((uint8_t)mode491, HEX); + //Serial.print(" | HeaterTemp "); + //Serial.print((int8_t)heatertemp); + //Serial.print(" | RadTemp "); + //Serial.print((int8_t)radiatorTemp); + //Serial.print(" | ChargeTemp "); + //Serial.print((int8_t)chargeTemp); + //Serial.print(" | Batt state3F6 "); + //Serial.print((uint8_t)state3F6, HEX); + //Serial.print(" | RLY "); + //Serial.print((uint8_t)battrly, BIN); //Bit0 - BMS relay ,Bit 5 - normal charge, Bit 6 rapid charge, Bit 7 charging + + if (bitRead((uint8_t)battrly, 0) == 1){ + Serial.print(" | BMS Output ON"); + } + else { + Serial.print(" | BMS Output OFF"); + } + Serial.print(" | Inverter "); + Serial.print((int16_t)Inv_Volts); Serial.println(" Volts"); + //Serial.print("Diagnostic state(12=outputON): "); + //Serial.println(sendDiagnostic); + } #endif -} void receive_can_kiaHyundai_64_battery(CAN_frame_t rx_frame) { CANstillAlive = 12; switch (rx_frame.MsgID) { - case 0x3F6: + case 0x3F6: // Do not exist in KIA BMS ECU break; case 0x491: + mode491 = rx_frame.data.u8[0]; break; case 0x493: break; @@ -165,25 +248,31 @@ void receive_can_kiaHyundai_64_battery(CAN_frame_t rx_frame) { case 0x4DD: break; case 0x4DE: - break; + radiatorTemp = rx_frame.data.u8[4]; //-15 case 0x4E2: break; case 0x542: //BMS SOC - SOC_Display = (rx_frame.data.u8[0] / 2.00); - break; + SOC_Display = rx_frame.data.u8[0] * 5; //100% = 200 ( 200 * 5 = 1000 ) + break; case 0x594: - SOC_BMS = (rx_frame.data.u8[5] / 2.00); - break; + SOC_BMS = rx_frame.data.u8[5] * 5; //100% = 200 ( 200 * 5 = 1000 ) + break; case 0x595: - break; + battVolts = (rx_frame.data.u8[7] << 8) + rx_frame.data.u8[6]; + battAmps = (rx_frame.data.u8[5] << 8) + rx_frame.data.u8[4]; + frame524volts = (int16_t)battVolts / 10; + //if (counter > 51) {KIA64_524_1.data = {(uint8_t)frame524volts, (uint8_t)(frame524volts >> 8), 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; } //vcu volts to bms + break; case 0x596: - aux12volt = (rx_frame.data.u8[1] / 10.00); - tempSensH = (rx_frame.data.u8[7]); + aux12volt = rx_frame.data.u8[1]; //12v Battery Volts + tempMin = rx_frame.data.u8[6]; //Lowest temp in battery + tempMax = rx_frame.data.u8[7]; //Highest temp in battery break; case 0x597: break; case 0x598: - break; + chargeTemp = rx_frame.data.u8[7]; //ChargeportTemperature + break; case 0x599: break; case 0x59C: @@ -193,72 +282,20 @@ void receive_can_kiaHyundai_64_battery(CAN_frame_t rx_frame) { case 0x5A3: break; case 0x5D5: - RES_WS0 = rx_frame.data.u8[3]; // water sensor - break; + leakSens = rx_frame.data.u8[3]; //Water sensor inside pack, value 164 is no water --> 0 is short + PRAtemp = rx_frame.data.u8[7]; //PowerRelayTemp + break; case 0x5D6: - currentSensor = (((rx_frame.data.u8[3] << 8) + rx_frame.data.u8[2]) / 10.0); //strömsensor break; case 0x5D7: break; case 0x5D8: - break; -case 0x7EC: //Data From polled PID group - switch (rx_frame.data.u8[0]) - { - case 0x10: //"PID Header" - if (rx_frame.data.u8[4] == poll_data_pid){ - ESP32Can.CANWriteFrame(&KIA64_7E4_ack); //Send ack to BMS if the same frame is sent as polled - } - break; - case 0x21: //First datarow in PID group - if (poll_data_pid == 1){ - allowedChargePower = ((rx_frame.data.u8[3] << 8) + rx_frame.data.u8[4]); - allowedDischargePower = ((rx_frame.data.u8[5] << 8) + rx_frame.data.u8[6]); - } - if (poll_data_pid == 6){ - CoolWaterSensor = rx_frame.data.u8[2]; - } - break; - case 0x22: //Second datarow in PID group - if (poll_data_pid == 1){ - battAmps = (((rx_frame.data.u8[1] << 8) + rx_frame.data.u8[2]) / 10.0); - battVolts = (((rx_frame.data.u8[3] << 8) + rx_frame.data.u8[4]) / 10.0); - } - break; - case 0x23: //Third datarow in PID group - if (poll_data_pid == 1){ - CellVoltMax = (rx_frame.data.u8[7] * 20); //(volts *50) *20 =mV - } - break; - case 0x24: //Fourth datarow in PID group - if (poll_data_pid == 1){ - CellVmaxNo = rx_frame.data.u8[1]; - CellVminNo = rx_frame.data.u8[3]; - CellVoltMin = (rx_frame.data.u8[2] * 20); //(volts *50) *20 =mV - } - if (poll_data_pid == 5){ - battSOH = ((rx_frame.data.u8[2] << 8) + rx_frame.data.u8[3]); - } - break; - case 0x25: //Fifth datarow in PID group - break; - case 0x26: //Sixth datarow in PID group - break; - case 0x27: //Seventh datarow in PID group - break; - case 0x28: //Eighth datarow in PID group - break; - } - default: - break; - } -} -void send_can_kiaHyundai_64_battery() { - unsigned long currentMillis = millis(); - //Send 100ms message - if (currentMillis - previousMillis100 >= interval100) { - previousMillis100 = currentMillis; - if (poll_data_pid >= 6){ + counter++; + //ESP32Can.CANWriteFrame(&KIA64_524_1); + //ESP32Can.CANWriteFrame(&KIA64_291_1); //motor speed to 32767 if 100ms sent + + //PID data is polled after last message sent from battery: + if (poll_data_pid >= 10){ //polling one of ten PIDs at 100ms, resolution = 1s poll_data_pid = 0; } poll_data_pid++; @@ -274,10 +311,115 @@ void send_can_kiaHyundai_64_battery() { else if (poll_data_pid == 6){ ESP32Can.CANWriteFrame(&KIA64_7E4_id6); } + else if (poll_data_pid == 8){ + + } + else if (poll_data_pid == 9){ + + } + else if (poll_data_pid == 10){ + + } + + break; + case 0x7EC: //Data From polled PID group, BigEndian + switch (rx_frame.data.u8[0]) + { + case 0x02: //"Diagnostic" + if (rx_frame.data.u8[1] == 0x7E){ + sendDiagnostic = 2; + } + case 0x03: //"Diagnostic" + if (rx_frame.data.u8[1] == 0x7F){ + sendDiagnostic = 4; + } + case 0x04: //"Diagnostic" + if (rx_frame.data.u8[1] == 0x6F){ + sendDiagnostic = 3; + } + case 0x10: //"PID Header" + if (rx_frame.data.u8[4] == poll_data_pid){ + ESP32Can.CANWriteFrame(&KIA64_7E4_ack); //Send ack to BMS if the same frame is sent as polled + } + break; + case 0x21: //First frame in PID group + if (poll_data_pid == 1){ + allowedChargePower = ((rx_frame.data.u8[3] << 8) + rx_frame.data.u8[4]); + allowedDischargePower = ((rx_frame.data.u8[5] << 8) + rx_frame.data.u8[6]); + battrly = rx_frame.data.u8[7]; + } + break; + case 0x22: //Second datarow in PID group + if (poll_data_pid == 1){ + //battAmps = (rx_frame.data.u8[1] << 8) + rx_frame.data.u8[2]; //moved to passive data + //battVolts = (rx_frame.data.u8[3] << 8) + rx_frame.data.u8[4]; //moved to passive data + //tempMax = rx_frame.data.u8[5]; //moved to passive data + //tempMin = rx_frame.data.u8[6]; //moved to passive data + temp1 = rx_frame.data.u8[7]; + } + if (poll_data_pid == 6){ + battMagntMode = rx_frame.data.u8[5]; + } + break; + case 0x23: //Third datarow in PID group + if (poll_data_pid == 1){ + temp2 = rx_frame.data.u8[1]; + temp3 = rx_frame.data.u8[2]; + temp4 = rx_frame.data.u8[3]; + tempinlet = rx_frame.data.u8[6]; + CellVoltMax = (rx_frame.data.u8[7] * 20); //(volts *50) *20 =mV + } + if (poll_data_pid == 5){ + //airbag = rx_frame.data.u8[6]; Not needed + heatertemp = rx_frame.data.u8[7]; + } + break; + case 0x24: //Fourth datarow in PID group + if (poll_data_pid == 1){ + CellVmaxNo = rx_frame.data.u8[1]; + CellVminNo = rx_frame.data.u8[3]; + CellVoltMin = (rx_frame.data.u8[2] * 20); //(volts *50) *20 =mV + fanMode = rx_frame.data.u8[4]; + fanSpeed = rx_frame.data.u8[5]; + } + else if (poll_data_pid == 5){ + battSOH = ((rx_frame.data.u8[2] << 8) + rx_frame.data.u8[3]); + } + break; + case 0x25: //Fifth datarow in PID group + break; + case 0x26: //Sixth datarow in PID group + break; + case 0x27: //Seventh datarow in PID group + if (poll_data_pid == 1){ + BMS_ign = rx_frame.data.u8[6]; + Inv_VoltsTmp = rx_frame.data.u8[7]; + } + break; + case 0x28: //Eighth datarow in PID group + if (poll_data_pid == 1){ + Inv_Volts = (Inv_VoltsTmp << 8) + rx_frame.data.u8[1]; + } + break; + } + break; + default: + break; } - // Send 10s CAN Message - if (currentMillis - previousMillis10s >= interval10s) { - previousMillis10s = currentMillis; +} +void send_can_kiaHyundai_64_battery() { + unsigned long currentMillis = millis(); + //Send 100ms message + if (currentMillis - previousMillis100 >= interval100) { + previousMillis100 = currentMillis; + + ESP32Can.CANWriteFrame(&KIA64_553); + ESP32Can.CANWriteFrame(&KIA64_57F); + ESP32Can.CANWriteFrame(&KIA64_2A1); + } + // Send 10ms CAN Message + if (currentMillis - previousMillis10ms >= interval10ms) { + previousMillis10ms = currentMillis; switch (counter_200) { case 0: From 7d3657a1ff24b78a5174d564aa84aaff053dea05 Mon Sep 17 00:00:00 2001 From: Daniel Date: Thu, 11 Jan 2024 21:54:03 +0200 Subject: [PATCH 05/13] Memory optimization and added safeties --- .../src/battery/KIA-HYUNDAI-64-BATTERY.cpp | 329 +++++++++--------- 1 file changed, 156 insertions(+), 173 deletions(-) diff --git a/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp b/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp index 282d4514..38753a66 100644 --- a/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp +++ b/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp @@ -9,30 +9,32 @@ static const int interval100 = 100; // interval (ms) at which send CA static const int interval10ms = 10; // interval (ms) at which send CAN Messages static uint8_t CANstillAlive = 12; //counter for checking if CAN is still alive -#define LB_MAX_SOC 1000 //BMS never goes over this value. We use this info to rescale SOC% sent to Inverter -#define LB_MIN_SOC 0 //BMS never goes below this value. We use this info to rescale SOC% sent to Inverter +#define MAX_SOC 1000 //BMS never goes over this value. We use this info to rescale SOC% sent to Inverter +#define MIN_SOC 0 //BMS never goes below this value. We use this info to rescale SOC% sent to Inverter +#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 -static int16_t SOC_BMS = 0; -static int16_t SOC_Display = 0; -static int16_t battSOH = 0; -static int16_t leakSens = 0; +static uint16_t soc_calculated = 0; +static uint16_t SOC_BMS = 0; +static uint16_t SOC_Display = 0; +static uint16_t battSOH = 0; +static uint8_t waterleakageSensor = 164; static int16_t aux12volt = 0; -static int16_t CellVoltMax = 0; -static int16_t CellVmaxNo = 0; -static int16_t CellVoltMin = 0; -static int16_t CellVminNo = 0; +static uint16_t CellVoltMax = 3700; +static uint8_t CellVmaxNo = 0; +static uint16_t CellVoltMin = 3700; +static uint8_t CellVminNo = 0; +static uint16_t cell_deviation_mV = 0; //contains the deviation between highest and lowest cell in mV static int16_t allowedDischargePower = 0; static int16_t allowedChargePower = 0; static int16_t battVolts = 0; static int16_t battAmps = 0; -static int8_t tempMax = 0; -static int8_t tempMin = 0; +static int8_t temperatureMax = 0; +static int8_t temperatureMin = 0; static int8_t temp1 = 0; -static int8_t temp2 = 0; -static int8_t temp3 = 0; -static int8_t temp4 = 0; static int8_t tempinlet = 0; -static uint8_t battMagntMode = 0; +static uint8_t batteryManagementMode = 0; static uint8_t BMS_ign = 0; static int16_t poll_data_pid = 0; static int16_t poll109 = 0; @@ -45,13 +47,13 @@ static int16_t poll471 = 0; static int16_t poll523 = 0; static int8_t heatertemp = 0; //static int airbag = 0; Not needed -static int battrly = 0; +static uint8_t batteryRelay = 0; static int8_t PRAtemp = 0; static int16_t Inv_VoltsTmp = 0; static int16_t Inv_Volts = 0; static uint8_t mode491 = 0; -static int8_t radiatorTemp = 0; -static int8_t chargeTemp = 0; +static int8_t radiatorTemperature = 0; +static int8_t chargeTemperature = 0; static int16_t frame524volts = 0; static int8_t fanMode = 0; static int8_t fanSpeed = 0; @@ -106,8 +108,17 @@ CAN_frame_t KIA64_7E4_ack = {.FIR = {.B = {.DLC = 8,.FF = CAN_frame_std,}},.MsgI static uint8_t counter_200 = 0; void update_values_kiaHyundai_64_battery() { //This function maps all the values fetched via CAN to the correct parameters used for modbus - - SOC = (SOC_Display * 10); //Increase decimals from 50.0% -> 50.00% + + //Calculate the SOC% value to send to inverter + soc_calculated = SOC_Display; + soc_calculated = MIN_SOC + (MAX_SOC - MIN_SOC) * (soc_calculated - MINPERCENTAGE) / (MAXPERCENTAGE - MINPERCENTAGE); + if (soc_calculated < 0) { //We are in the real SOC% range of 0-20%, always set SOC sent to Inverter as 0% + soc_calculated = 0; + } + if (soc_calculated > 1000) { //We are in the real SOC% range of 80-100%, always set SOC sent to Inverter as 100% + soc_calculated = 1000; + } + SOC = (soc_calculated * 10); //increase SOC range from 0-100.0 -> 100.00 StateOfHealth = (battSOH * 10); //Increase decimals from 100.0% -> 100.00% @@ -117,7 +128,7 @@ void update_values_kiaHyundai_64_battery() { //This function maps all the value capacity_Wh = BATTERY_WH_MAX; - remaining_capacity_Wh = ((SOC/10000)*BATTERY_WH_MAX); + remaining_capacity_Wh = static_cast((static_cast(SOC) / 10000) * BATTERY_WH_MAX); max_target_discharge_power = (uint16_t)allowedDischargePower * 10; //From kW*100 to Watts @@ -125,15 +136,15 @@ void update_values_kiaHyundai_64_battery() { //This function maps all the value stat_batt_power = ((uint16_t)battVolts * (int16_t)battAmps) / 100; //Power in watts, Negative = charging batt. //Todo, the signed part will break something here - temperature_min = ((int8_t)tempMin * 10); //Increase decimals, 17C -> 17.0C + temperature_min = ((int8_t)temperatureMin * 10); //Increase decimals, 17C -> 17.0C - temperature_max = ((int8_t)tempMax * 10); //Increase decimals, 18C -> 18.0C + temperature_max = ((int8_t)temperatureMax * 10); //Increase decimals, 18C -> 18.0C cell_max_voltage = CellVoltMax; //in millivolt cell_min_voltage = CellVoltMin; //in millivolt - bms_status = ACTIVE; //Startout in active mode + bms_status = ACTIVE; //Startout in active mode. Then check safeties /* Check if the BMS is still sending CAN messages. If we go 60s without messages we raise an error*/ if (!CANstillAlive) { @@ -143,81 +154,85 @@ void update_values_kiaHyundai_64_battery() { //This function maps all the value CANstillAlive--; } + if(waterleakageSensor == 0){ + Serial.println("Water leakage inside battery detected. Operation halted. Inspect battery!"); + bms_status = FAULT; + } + + // Check if cell voltages are within allowed range + cell_deviation_mV = (cell_max_voltage - cell_min_voltage); + + if (cell_max_voltage >= MAX_CELL_VOLTAGE) { + bms_status = FAULT; + Serial.println("ERROR: CELL OVERVOLTAGE!!! Stopping battery charging and discharging. Inspect battery!"); + } + if (cell_min_voltage <= MIN_CELL_VOLTAGE) { + bms_status = FAULT; + Serial.println("ERROR: CELL UNDERVOLTAGE!!! Stopping battery charging and discharging. Inspect battery!"); + } + if (cell_deviation_mV > MAX_CELL_DEVIATION) { + LEDcolor = YELLOW; + Serial.println("ERROR: HIGH CELL DEVIATION!!! Inspect battery!"); + } + + if (bms_status == FAULT) { //Incase we enter a critical fault state, zero out the allowed limits + max_target_charge_power = 0; + max_target_discharge_power = 0; + } + + /* Safeties verified. Perform USB serial printout if configured to do so */ + #ifdef DEBUG_VIA_USB - Serial.println(); //sepatator - Serial.println("Values from battery: "); - Serial.print("SOC BMS: "); - Serial.print((int16_t)SOC_BMS / 10.0, 1); - Serial.print("% | SOC Display: "); - Serial.print((int16_t)SOC_Display / 10.0, 1); - Serial.print("% | SOH "); - Serial.print((int16_t)battSOH / 10.0, 1); - Serial.println("%"); - Serial.print((int16_t)battAmps / 10.0, 1); - Serial.print(" Amps | "); - Serial.print((int16_t)battVolts / 10.0, 1); - Serial.print(" Volts | "); - Serial.print((int16_t)stat_batt_power); - Serial.println(" Watts"); - Serial.print("Allowed Charge "); - Serial.print((uint16_t)allowedChargePower * 10); - Serial.print(" W | Allowed Discharge "); - Serial.print((uint16_t)allowedDischargePower * 10); - Serial.println(" W"); - Serial.print("MaxCellVolt "); - Serial.print(CellVoltMax); - Serial.print(" mV No "); - Serial.print(CellVmaxNo); - Serial.print(" | MinCellVolt "); - Serial.print(CellVoltMin); - Serial.print(" mV No "); - Serial.println(CellVminNo); - Serial.print("TempHi "); - Serial.print((int8_t)tempMax); - Serial.print("°C TempLo "); - Serial.print((int8_t)tempMin); - //Serial.print("°C Temp1 "); - //Serial.print((int8_t)temp1); - //Serial.print("°C Temp2 "); - //Serial.print((int8_t)temp2); - //Serial.print("°C Temp3 "); - //Serial.print((int8_t)temp3); - //Serial.print("°C Temp4 "); - //Serial.print((int8_t)temp4); - Serial.print("°C WaterInlet "); - Serial.print((int8_t)tempinlet); - Serial.print("°C PowerRelay "); - Serial.print((int8_t)PRAtemp * 2); - Serial.println("°C"); - Serial.print("Aux12volt: "); - Serial.print((int16_t)aux12volt / 10.0, 1); - Serial.print("V | "); - Serial.print("LeakSensor: "); - Serial.println(leakSens); - Serial.print("BmsMagementMode "); - Serial.print((uint8_t)battMagntMode, BIN); - //Serial.print(" | IgnitionBIN "); - //Serial.print((uint8_t)BMS_ign, BIN); //bit 2=IGN - if (bitRead((uint8_t)BMS_ign, 2) == 1){ - Serial.print(" | BmsIgitionON"); - } - else { - Serial.print(" | BmsIgitionOFF"); - } - //Serial.print(" | mode491 "); - //Serial.println((uint8_t)mode491, HEX); - //Serial.print(" | HeaterTemp "); - //Serial.print((int8_t)heatertemp); - //Serial.print(" | RadTemp "); - //Serial.print((int8_t)radiatorTemp); - //Serial.print(" | ChargeTemp "); - //Serial.print((int8_t)chargeTemp); - //Serial.print(" | Batt state3F6 "); - //Serial.print((uint8_t)state3F6, HEX); - //Serial.print(" | RLY "); - //Serial.print((uint8_t)battrly, BIN); //Bit0 - BMS relay ,Bit 5 - normal charge, Bit 6 rapid charge, Bit 7 charging - - if (bitRead((uint8_t)battrly, 0) == 1){ + Serial.println(); //sepatator + Serial.println("Values from battery: "); + Serial.print("SOC BMS: "); + Serial.print(SOC_BMS / 10.0, 1); + Serial.print("% | SOC Display: "); + Serial.print(SOC_Display / 10.0, 1); + Serial.print("% | SOH "); + Serial.print(battSOH / 10.0, 1); + Serial.println("%"); + Serial.print((int16_t)battAmps / 10.0, 1); + Serial.print(" Amps | "); + Serial.print((int16_t)battVolts / 10.0, 1); + Serial.print(" Volts | "); + Serial.print((int16_t)stat_batt_power); + Serial.println(" Watts"); + Serial.print("Allowed Charge "); + Serial.print((uint16_t)allowedChargePower * 10); + Serial.print(" W | Allowed Discharge "); + Serial.print((uint16_t)allowedDischargePower * 10); + Serial.println(" W"); + Serial.print("MaxCellVolt "); + Serial.print(CellVoltMax); + Serial.print(" mV No "); + Serial.print(CellVmaxNo); + Serial.print(" | MinCellVolt "); + Serial.print(CellVoltMin); + Serial.print(" mV No "); + Serial.println(CellVminNo); + Serial.print("TempHi "); + Serial.print((int8_t)temperatureMax); + Serial.print("°C TempLo "); + Serial.print((int8_t)temperatureMin); + Serial.print("°C WaterInlet "); + Serial.print((int8_t)tempinlet); + Serial.print("°C PowerRelay "); + Serial.print((int8_t)PRAtemp * 2); + Serial.println("°C"); + Serial.print("Aux12volt: "); + Serial.print((int16_t)aux12volt / 10.0, 1); + Serial.println("V | "); + Serial.print("BmsMagementMode "); + Serial.print((uint8_t)batteryManagementMode, BIN); + if (bitRead((uint8_t)BMS_ign, 2) == 1){ + Serial.print(" | BmsIgitionON"); + } + else { + Serial.print(" | BmsIgitionOFF"); + } + + if (bitRead((uint8_t)batteryRelay, 0) == 1){ Serial.print(" | BMS Output ON"); } else { @@ -234,94 +249,65 @@ void update_values_kiaHyundai_64_battery() { //This function maps all the value void receive_can_kiaHyundai_64_battery(CAN_frame_t rx_frame) { CANstillAlive = 12; switch (rx_frame.MsgID) { - case 0x3F6: // Do not exist in KIA BMS ECU - break; case 0x491: mode491 = rx_frame.data.u8[0]; break; - case 0x493: - break; - case 0x497: - break; - case 0x498: - break; - case 0x4DD: - break; case 0x4DE: - radiatorTemp = rx_frame.data.u8[4]; //-15 - case 0x4E2: + radiatorTemperature = rx_frame.data.u8[4]; //-15 break; case 0x542: //BMS SOC - SOC_Display = rx_frame.data.u8[0] * 5; //100% = 200 ( 200 * 5 = 1000 ) - break; - case 0x594: - SOC_BMS = rx_frame.data.u8[5] * 5; //100% = 200 ( 200 * 5 = 1000 ) - break; - case 0x595: - battVolts = (rx_frame.data.u8[7] << 8) + rx_frame.data.u8[6]; - battAmps = (rx_frame.data.u8[5] << 8) + rx_frame.data.u8[4]; - frame524volts = (int16_t)battVolts / 10; - //if (counter > 51) {KIA64_524_1.data = {(uint8_t)frame524volts, (uint8_t)(frame524volts >> 8), 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; } //vcu volts to bms - break; - case 0x596: - aux12volt = rx_frame.data.u8[1]; //12v Battery Volts - tempMin = rx_frame.data.u8[6]; //Lowest temp in battery - tempMax = rx_frame.data.u8[7]; //Highest temp in battery + SOC_Display = rx_frame.data.u8[0] * 5; //100% = 200 ( 200 * 5 = 1000 ) break; - case 0x597: + case 0x594: + SOC_BMS = rx_frame.data.u8[5] * 5; //100% = 200 ( 200 * 5 = 1000 ) + break; + case 0x595: + battVolts = (rx_frame.data.u8[7] << 8) + rx_frame.data.u8[6]; + battAmps = (rx_frame.data.u8[5] << 8) + rx_frame.data.u8[4]; + frame524volts = (int16_t)battVolts / 10; + //if (counter > 51) {KIA64_524_1.data = {(uint8_t)frame524volts, (uint8_t)(frame524volts >> 8), 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; } //vcu volts to bms + break; + case 0x596: + aux12volt = rx_frame.data.u8[1]; //12v Battery Volts + temperatureMin = rx_frame.data.u8[6]; //Lowest temp in battery + temperatureMax = rx_frame.data.u8[7]; //Highest temp in battery break; case 0x598: - chargeTemp = rx_frame.data.u8[7]; //ChargeportTemperature - break; - case 0x599: - break; - case 0x59C: - break; - case 0x59E: - break; - case 0x5A3: + chargeTemperature = rx_frame.data.u8[7]; //ChargeportTemperature break; case 0x5D5: - leakSens = rx_frame.data.u8[3]; //Water sensor inside pack, value 164 is no water --> 0 is short - PRAtemp = rx_frame.data.u8[7]; //PowerRelayTemp - break; - case 0x5D6: - break; - case 0x5D7: + waterleakageSensor = rx_frame.data.u8[3]; //Water sensor inside pack, value 164 is no water --> 0 is short + PRAtemp = rx_frame.data.u8[7]; //PowerRelayTemp break; case 0x5D8: - counter++; - //ESP32Can.CANWriteFrame(&KIA64_524_1); - //ESP32Can.CANWriteFrame(&KIA64_291_1); //motor speed to 32767 if 100ms sent + counter++; + //ESP32Can.CANWriteFrame(&KIA64_524_1); + //ESP32Can.CANWriteFrame(&KIA64_291_1); //motor speed to 32767 if 100ms sent - //PID data is polled after last message sent from battery: - if (poll_data_pid >= 10){ //polling one of ten PIDs at 100ms, resolution = 1s - poll_data_pid = 0; + //PID data is polled after last message sent from battery: + if (poll_data_pid >= 10){ //polling one of ten PIDs at 100ms, resolution = 1s + poll_data_pid = 0; + } + poll_data_pid++; + if (poll_data_pid == 1){ + ESP32Can.CANWriteFrame(&KIA64_7E4_id1); } - poll_data_pid++; - if (poll_data_pid == 1){ - ESP32Can.CANWriteFrame(&KIA64_7E4_id1); + else if (poll_data_pid == 2){ + ESP32Can.CANWriteFrame(&KIA64_7E4_id2); } - else if (poll_data_pid == 2){ - ESP32Can.CANWriteFrame(&KIA64_7E4_id2); + else if (poll_data_pid == 5){ + ESP32Can.CANWriteFrame(&KIA64_7E4_id5); } - else if (poll_data_pid == 5){ - ESP32Can.CANWriteFrame(&KIA64_7E4_id5); + else if (poll_data_pid == 6){ + ESP32Can.CANWriteFrame(&KIA64_7E4_id6); } - else if (poll_data_pid == 6){ - ESP32Can.CANWriteFrame(&KIA64_7E4_id6); + else if (poll_data_pid == 8){ } - else if (poll_data_pid == 8){ - + else if (poll_data_pid == 9){ } - else if (poll_data_pid == 9){ - + else if (poll_data_pid == 10){ } - else if (poll_data_pid == 10){ - - } - - break; + break; case 0x7EC: //Data From polled PID group, BigEndian switch (rx_frame.data.u8[0]) { @@ -346,7 +332,7 @@ void receive_can_kiaHyundai_64_battery(CAN_frame_t rx_frame) { if (poll_data_pid == 1){ allowedChargePower = ((rx_frame.data.u8[3] << 8) + rx_frame.data.u8[4]); allowedDischargePower = ((rx_frame.data.u8[5] << 8) + rx_frame.data.u8[6]); - battrly = rx_frame.data.u8[7]; + batteryRelay = rx_frame.data.u8[7]; } break; case 0x22: //Second datarow in PID group @@ -358,14 +344,11 @@ void receive_can_kiaHyundai_64_battery(CAN_frame_t rx_frame) { temp1 = rx_frame.data.u8[7]; } if (poll_data_pid == 6){ - battMagntMode = rx_frame.data.u8[5]; + batteryManagementMode = rx_frame.data.u8[5]; } break; case 0x23: //Third datarow in PID group if (poll_data_pid == 1){ - temp2 = rx_frame.data.u8[1]; - temp3 = rx_frame.data.u8[2]; - temp4 = rx_frame.data.u8[3]; tempinlet = rx_frame.data.u8[6]; CellVoltMax = (rx_frame.data.u8[7] * 20); //(volts *50) *20 =mV } @@ -402,9 +385,9 @@ void receive_can_kiaHyundai_64_battery(CAN_frame_t rx_frame) { } break; } - break; + break; default: - break; + break; } } void send_can_kiaHyundai_64_battery() { From afd03899513d5d6da7a3b354e6093ab491d3c309 Mon Sep 17 00:00:00 2001 From: Daniel Date: Thu, 11 Jan 2024 22:36:57 +0200 Subject: [PATCH 06/13] Add 12V safety. Cleanup --- .../src/battery/KIA-HYUNDAI-64-BATTERY.cpp | 487 +++++++++--------- 1 file changed, 255 insertions(+), 232 deletions(-) diff --git a/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp b/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp index 38753a66..43dbdb7e 100644 --- a/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp +++ b/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp @@ -5,12 +5,12 @@ /* 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 previousMillis10ms = 0; // will store last time a 10s CAN Message was send -static const int interval100 = 100; // interval (ms) at which send CAN Messages -static const int interval10ms = 10; // interval (ms) at which send CAN Messages -static uint8_t CANstillAlive = 12; //counter for checking if CAN is still alive +static const int interval100 = 100; // interval (ms) at which send CAN Messages +static const int interval10ms = 10; // interval (ms) at which send CAN Messages +static uint8_t CANstillAlive = 12; //counter for checking if CAN is still alive -#define MAX_SOC 1000 //BMS never goes over this value. We use this info to rescale SOC% sent to Inverter -#define MIN_SOC 0 //BMS never goes below this value. We use this info to rescale SOC% sent to Inverter +#define MAX_SOC 1000 //BMS never goes over this value. We use this info to rescale SOC% sent to Inverter +#define MIN_SOC 0 //BMS never goes below this value. We use this info to rescale SOC% sent to Inverter #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 @@ -18,22 +18,21 @@ static uint8_t CANstillAlive = 12; //counter for checking if CAN is st static uint16_t soc_calculated = 0; static uint16_t SOC_BMS = 0; static uint16_t SOC_Display = 0; -static uint16_t battSOH = 0; +static uint16_t batterySOH = 1000; static uint8_t waterleakageSensor = 164; -static int16_t aux12volt = 0; -static uint16_t CellVoltMax = 3700; +static int16_t leadAcidBatteryVoltage = 0; +static uint16_t CellVoltMax_mV = 3700; static uint8_t CellVmaxNo = 0; -static uint16_t CellVoltMin = 3700; +static uint16_t CellVoltMin_mV = 3700; static uint8_t CellVminNo = 0; -static uint16_t cell_deviation_mV = 0; //contains the deviation between highest and lowest cell in mV +static uint16_t cell_deviation_mV = 0; static int16_t allowedDischargePower = 0; static int16_t allowedChargePower = 0; -static int16_t battVolts = 0; -static int16_t battAmps = 0; +static uint16_t batteryVoltage = 0; +static int16_t batteryAmps = 0; static int8_t temperatureMax = 0; static int8_t temperatureMin = 0; -static int8_t temp1 = 0; -static int8_t tempinlet = 0; +static int8_t temperature_water_inlet = 0; static uint8_t batteryManagementMode = 0; static uint8_t BMS_ign = 0; static int16_t poll_data_pid = 0; @@ -46,66 +45,117 @@ static int16_t poll450 = 0; static int16_t poll471 = 0; static int16_t poll523 = 0; static int8_t heatertemp = 0; -//static int airbag = 0; Not needed static uint8_t batteryRelay = 0; -static int8_t PRAtemp = 0; -static int16_t Inv_VoltsTmp = 0; -static int16_t Inv_Volts = 0; -static uint8_t mode491 = 0; +static int8_t powerRelayTemperature = 0; +static uint16_t inverterVoltageFrameHigh = 0; +static uint16_t inverterVoltage = 0; static int8_t radiatorTemperature = 0; static int8_t chargeTemperature = 0; -static int16_t frame524volts = 0; static int8_t fanMode = 0; static int8_t fanSpeed = 0; static int8_t state3F6 = 0; -static uint counter = 0; -static int8_t sendDiagnostic = 0; +static uint8_t counter = 0; +static uint8_t counter_200 = 0; CAN_frame_t KIA_HYUNDAI_200 = {.FIR = {.B = - { - .DLC = 8, - .FF = CAN_frame_std, - }}, - .MsgID = 0x200, - //.data = {0x00, 0x00, 0x00, 0x04, 0x00, 0x50, 0xD0, 0x00}}; //Initial value - .data = {0x00, 0x80, 0xD8, 0x04, 0x00, 0x17, 0xD0, 0x00}}; //Mid log value + { + .DLC = 8, + .FF = CAN_frame_std, + }}, + .MsgID = 0x200, + //.data = {0x00, 0x00, 0x00, 0x04, 0x00, 0x50, 0xD0, 0x00}}; //Initial value + .data = {0x00, 0x80, 0xD8, 0x04, 0x00, 0x17, 0xD0, 0x00}}; //Mid log value CAN_frame_t KIA_HYUNDAI_523 = {.FIR = {.B = - { - .DLC = 8, - .FF = CAN_frame_std, - }}, - .MsgID = 0x523, - //.data = {0x00, 0x38, 0x28, 0x28, 0x28, 0x28, 0x00, 0x01}}; //Initial value - .data = {0x08, 0x38, 0x36, 0x36, 0x33, 0x34, 0x00, 0x01}}; //Mid log value + { + .DLC = 8, + .FF = CAN_frame_std, + }}, + .MsgID = 0x523, + //.data = {0x00, 0x38, 0x28, 0x28, 0x28, 0x28, 0x00, 0x01}}; //Initial value + .data = {0x08, 0x38, 0x36, 0x36, 0x33, 0x34, 0x00, 0x01}}; //Mid log value CAN_frame_t KIA_HYUNDAI_524 = {.FIR = {.B = - { - .DLC = 8, - .FF = CAN_frame_std, - }}, - .MsgID = 0x524, - //.data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; //Initial value - .data = {0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; //Mid log value + { + .DLC = 8, + .FF = CAN_frame_std, + }}, + .MsgID = 0x524, + .data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; //Initial value //553 Needed frame 200ms -CAN_frame_t KIA64_553 = {.FIR = {.B = {.DLC = 8,.FF = CAN_frame_std,}},.MsgID = 0x553,.data = {0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00}}; +CAN_frame_t KIA64_553 = {.FIR = {.B = + { + .DLC = 8, + .FF = CAN_frame_std, + }}, + .MsgID = 0x553, + .data = {0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00}}; //57F Needed frame 100ms -CAN_frame_t KIA64_57F = {.FIR = {.B = {.DLC = 8,.FF = CAN_frame_std,}},.MsgID = 0x57F,.data = {0x80, 0x0A, 0x72, 0x00, 0x00, 0x00, 0x00, 0x72}}; +CAN_frame_t KIA64_57F = {.FIR = {.B = + { + .DLC = 8, + .FF = CAN_frame_std, + }}, + .MsgID = 0x57F, + .data = {0x80, 0x0A, 0x72, 0x00, 0x00, 0x00, 0x00, 0x72}}; //Needed frame 100ms -CAN_frame_t KIA64_2A1 = {.FIR = {.B = {.DLC = 8,.FF = CAN_frame_std,}},.MsgID = 0x2A1,.data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; +CAN_frame_t KIA64_2A1 = {.FIR = {.B = + { + .DLC = 8, + .FF = CAN_frame_std, + }}, + .MsgID = 0x2A1, + .data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; - -CAN_frame_t KIA64_7E4_id1 = {.FIR = {.B = {.DLC = 8,.FF = CAN_frame_std,}},.MsgID = 0x7E4,.data = {0x03, 0x22, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00}}; //Poll PID 03 22 01 01 -CAN_frame_t KIA64_7E4_id2 = {.FIR = {.B = {.DLC = 8,.FF = CAN_frame_std,}},.MsgID = 0x7E4,.data = {0x03, 0x22, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00}}; //Poll PID 03 22 01 02 -CAN_frame_t KIA64_7E4_id3 = {.FIR = {.B = {.DLC = 8,.FF = CAN_frame_std,}},.MsgID = 0x7E4,.data = {0x03, 0x22, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00}}; //Poll PID 03 22 01 03 -CAN_frame_t KIA64_7E4_id4 = {.FIR = {.B = {.DLC = 8,.FF = CAN_frame_std,}},.MsgID = 0x7E4,.data = {0x03, 0x22, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00}}; //Poll PID 03 22 01 04 -CAN_frame_t KIA64_7E4_id5 = {.FIR = {.B = {.DLC = 8,.FF = CAN_frame_std,}},.MsgID = 0x7E4,.data = {0x03, 0x22, 0x01, 0x05, 0x00, 0x00, 0x00, 0x00}}; //Poll PID 03 22 01 05 -CAN_frame_t KIA64_7E4_id6 = {.FIR = {.B = {.DLC = 8,.FF = CAN_frame_std,}},.MsgID = 0x7E4,.data = {0x03, 0x22, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00}}; //Poll PID 03 22 01 06 - -CAN_frame_t KIA64_7E4_ack = {.FIR = {.B = {.DLC = 8,.FF = CAN_frame_std,}},.MsgID = 0x7E4,.data = {0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; //Ack frame, correct PID is returned - - - -static uint8_t counter_200 = 0; +CAN_frame_t KIA64_7E4_id1 = {.FIR = {.B = + { + .DLC = 8, + .FF = CAN_frame_std, + }}, + .MsgID = 0x7E4, + .data = {0x03, 0x22, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00}}; //Poll PID 03 22 01 01 +CAN_frame_t KIA64_7E4_id2 = {.FIR = {.B = + { + .DLC = 8, + .FF = CAN_frame_std, + }}, + .MsgID = 0x7E4, + .data = {0x03, 0x22, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00}}; //Poll PID 03 22 01 02 +CAN_frame_t KIA64_7E4_id3 = {.FIR = {.B = + { + .DLC = 8, + .FF = CAN_frame_std, + }}, + .MsgID = 0x7E4, + .data = {0x03, 0x22, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00}}; //Poll PID 03 22 01 03 +CAN_frame_t KIA64_7E4_id4 = {.FIR = {.B = + { + .DLC = 8, + .FF = CAN_frame_std, + }}, + .MsgID = 0x7E4, + .data = {0x03, 0x22, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00}}; //Poll PID 03 22 01 04 +CAN_frame_t KIA64_7E4_id5 = {.FIR = {.B = + { + .DLC = 8, + .FF = CAN_frame_std, + }}, + .MsgID = 0x7E4, + .data = {0x03, 0x22, 0x01, 0x05, 0x00, 0x00, 0x00, 0x00}}; //Poll PID 03 22 01 05 +CAN_frame_t KIA64_7E4_id6 = {.FIR = {.B = + { + .DLC = 8, + .FF = CAN_frame_std, + }}, + .MsgID = 0x7E4, + .data = {0x03, 0x22, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00}}; //Poll PID 03 22 01 06 +CAN_frame_t KIA64_7E4_ack = { + .FIR = {.B = + { + .DLC = 8, + .FF = CAN_frame_std, + }}, + .MsgID = 0x7E4, + .data = {0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; //Ack frame, correct PID is returned void update_values_kiaHyundai_64_battery() { //This function maps all the values fetched via CAN to the correct parameters used for modbus @@ -119,32 +169,33 @@ void update_values_kiaHyundai_64_battery() { //This function maps all the value soc_calculated = 1000; } SOC = (soc_calculated * 10); //increase SOC range from 0-100.0 -> 100.00 - - StateOfHealth = (battSOH * 10); //Increase decimals from 100.0% -> 100.00% - battery_voltage = (uint16_t)battVolts; //value is *10 + StateOfHealth = (batterySOH * 10); //Increase decimals from 100.0% -> 100.00% - battery_current = (int16_t)battAmps; //value is *10 //Todo, the signed part breaks something here for sure + battery_voltage = batteryVoltage; //value is *10 + + battery_current = (int16_t)batteryAmps; //value is *10 //Todo, the signed part breaks something here for sure capacity_Wh = BATTERY_WH_MAX; remaining_capacity_Wh = static_cast((static_cast(SOC) / 10000) * BATTERY_WH_MAX); - max_target_discharge_power = (uint16_t)allowedDischargePower * 10; //From kW*100 to Watts + max_target_discharge_power = (uint16_t)allowedDischargePower * 10; //From kW*100 to Watts - max_target_charge_power = (uint16_t)allowedChargePower * 10; //From kW*100 to Watts + max_target_charge_power = (uint16_t)allowedChargePower * 10; //From kW*100 to Watts - stat_batt_power = ((uint16_t)battVolts * (int16_t)battAmps) / 100; //Power in watts, Negative = charging batt. //Todo, the signed part will break something here + stat_batt_power = (batteryVoltage * (int16_t)batteryAmps) / + 100; //Power in watts, Negative = charging batt. //Todo, the signed part will break something here - temperature_min = ((int8_t)temperatureMin * 10); //Increase decimals, 17C -> 17.0C - - temperature_max = ((int8_t)temperatureMax * 10); //Increase decimals, 18C -> 18.0C - - cell_max_voltage = CellVoltMax; //in millivolt - - cell_min_voltage = CellVoltMin; //in millivolt + temperature_min = ((int8_t)temperatureMin * 10); //Increase decimals, 17C -> 17.0C - bms_status = ACTIVE; //Startout in active mode. Then check safeties + temperature_max = ((int8_t)temperatureMax * 10); //Increase decimals, 18C -> 18.0C + + cell_max_voltage = CellVoltMax_mV; + + cell_min_voltage = CellVoltMin_mV; + + bms_status = ACTIVE; //Startout in active mode. Then check safeties /* Check if the BMS is still sending CAN messages. If we go 60s without messages we raise an error*/ if (!CANstillAlive) { @@ -154,26 +205,31 @@ void update_values_kiaHyundai_64_battery() { //This function maps all the value CANstillAlive--; } - if(waterleakageSensor == 0){ + if (waterleakageSensor == 0) { Serial.println("Water leakage inside battery detected. Operation halted. Inspect battery!"); bms_status = FAULT; } + if (leadAcidBatteryVoltage < 110) { + Serial.println("12V battery source below required voltage to safely close contactors. Inspect the supply/battery!"); + LEDcolor = YELLOW; + } + // Check if cell voltages are within allowed range cell_deviation_mV = (cell_max_voltage - cell_min_voltage); if (cell_max_voltage >= MAX_CELL_VOLTAGE) { - bms_status = FAULT; - Serial.println("ERROR: CELL OVERVOLTAGE!!! Stopping battery charging and discharging. Inspect battery!"); - } - if (cell_min_voltage <= MIN_CELL_VOLTAGE) { - bms_status = FAULT; - Serial.println("ERROR: CELL UNDERVOLTAGE!!! Stopping battery charging and discharging. Inspect battery!"); - } - if (cell_deviation_mV > MAX_CELL_DEVIATION) { - LEDcolor = YELLOW; - Serial.println("ERROR: HIGH CELL DEVIATION!!! Inspect battery!"); - } + bms_status = FAULT; + Serial.println("ERROR: CELL OVERVOLTAGE!!! Stopping battery charging and discharging. Inspect battery!"); + } + if (cell_min_voltage <= MIN_CELL_VOLTAGE) { + bms_status = FAULT; + Serial.println("ERROR: CELL UNDERVOLTAGE!!! Stopping battery charging and discharging. Inspect battery!"); + } + if (cell_deviation_mV > MAX_CELL_DEVIATION) { + LEDcolor = YELLOW; + Serial.println("ERROR: HIGH CELL DEVIATION!!! Inspect battery!"); + } if (bms_status == FAULT) { //Incase we enter a critical fault state, zero out the allowed limits max_target_charge_power = 0; @@ -183,18 +239,18 @@ void update_values_kiaHyundai_64_battery() { //This function maps all the value /* Safeties verified. Perform USB serial printout if configured to do so */ #ifdef DEBUG_VIA_USB - Serial.println(); //sepatator + Serial.println(); //sepatator Serial.println("Values from battery: "); Serial.print("SOC BMS: "); - Serial.print(SOC_BMS / 10.0, 1); + Serial.print((uint16_t)SOC_BMS / 10.0, 1); Serial.print("% | SOC Display: "); - Serial.print(SOC_Display / 10.0, 1); + Serial.print((uint16_t)SOC_Display / 10.0, 1); Serial.print("% | SOH "); - Serial.print(battSOH / 10.0, 1); + Serial.print((uint16_t)batterySOH / 10.0, 1); Serial.println("%"); - Serial.print((int16_t)battAmps / 10.0, 1); + Serial.print((int16_t)batteryAmps / 10.0, 1); Serial.print(" Amps | "); - Serial.print((int16_t)battVolts / 10.0, 1); + Serial.print((uint16_t)batteryVoltage / 10.0, 1); Serial.print(" Volts | "); Serial.print((int16_t)stat_batt_power); Serial.println(" Watts"); @@ -204,11 +260,11 @@ void update_values_kiaHyundai_64_battery() { //This function maps all the value Serial.print((uint16_t)allowedDischargePower * 10); Serial.println(" W"); Serial.print("MaxCellVolt "); - Serial.print(CellVoltMax); + Serial.print(CellVoltMax_mV); Serial.print(" mV No "); Serial.print(CellVmaxNo); Serial.print(" | MinCellVolt "); - Serial.print(CellVoltMin); + Serial.print(CellVoltMin_mV); Serial.print(" mV No "); Serial.println(CellVminNo); Serial.print("TempHi "); @@ -216,178 +272,146 @@ void update_values_kiaHyundai_64_battery() { //This function maps all the value Serial.print("°C TempLo "); Serial.print((int8_t)temperatureMin); Serial.print("°C WaterInlet "); - Serial.print((int8_t)tempinlet); + Serial.print((int8_t)temperature_water_inlet); Serial.print("°C PowerRelay "); - Serial.print((int8_t)PRAtemp * 2); + Serial.print((int8_t)powerRelayTemperature * 2); Serial.println("°C"); Serial.print("Aux12volt: "); - Serial.print((int16_t)aux12volt / 10.0, 1); + Serial.print((int16_t)leadAcidBatteryVoltage / 10.0, 1); Serial.println("V | "); - Serial.print("BmsMagementMode "); + Serial.print("BmsManagementMode "); Serial.print((uint8_t)batteryManagementMode, BIN); - if (bitRead((uint8_t)BMS_ign, 2) == 1){ - Serial.print(" | BmsIgitionON"); + if (bitRead((uint8_t)BMS_ign, 2) == 1) { + Serial.print(" | BmsIgnitionON"); + } else { + Serial.print(" | BmsIgnitionOFF"); } - else { - Serial.print(" | BmsIgitionOFF"); - } - - if (bitRead((uint8_t)batteryRelay, 0) == 1){ + + if (bitRead((uint8_t)batteryRelay, 0) == 1) { Serial.print(" | BMS Output ON"); - } - else { + } else { Serial.print(" | BMS Output OFF"); } - Serial.print(" | Inverter "); - Serial.print((int16_t)Inv_Volts); - Serial.println(" Volts"); - //Serial.print("Diagnostic state(12=outputON): "); - //Serial.println(sendDiagnostic); - } + Serial.print(" | Inverter "); + Serial.print(inverterVoltage); + Serial.println(" Volts"); +} #endif void receive_can_kiaHyundai_64_battery(CAN_frame_t rx_frame) { - CANstillAlive = 12; switch (rx_frame.MsgID) { - case 0x491: - mode491 = rx_frame.data.u8[0]; - break; case 0x4DE: - radiatorTemperature = rx_frame.data.u8[4]; //-15 + radiatorTemperature = rx_frame.data.u8[4]; //-15 break; - case 0x542: //BMS SOC - SOC_Display = rx_frame.data.u8[0] * 5; //100% = 200 ( 200 * 5 = 1000 ) + case 0x542: //BMS SOC + 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 ) break; case 0x594: - SOC_BMS = rx_frame.data.u8[5] * 5; //100% = 200 ( 200 * 5 = 1000 ) + SOC_BMS = rx_frame.data.u8[5] * 5; //100% = 200 ( 200 * 5 = 1000 ) break; case 0x595: - battVolts = (rx_frame.data.u8[7] << 8) + rx_frame.data.u8[6]; - battAmps = (rx_frame.data.u8[5] << 8) + rx_frame.data.u8[4]; - frame524volts = (int16_t)battVolts / 10; - //if (counter > 51) {KIA64_524_1.data = {(uint8_t)frame524volts, (uint8_t)(frame524volts >> 8), 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; } //vcu volts to bms + batteryVoltage = (rx_frame.data.u8[7] << 8) + rx_frame.data.u8[6]; + batteryAmps = (rx_frame.data.u8[5] << 8) + rx_frame.data.u8[4]; + if (counter > 51) { + KIA_HYUNDAI_524.data.u8[0] = (uint8_t)(batteryVoltage / 10); + KIA_HYUNDAI_524.data.u8[1] = (uint8_t)((batteryVoltage / 10) >> 8); + } //VCU measured voltage sent back to bms break; case 0x596: - aux12volt = rx_frame.data.u8[1]; //12v Battery Volts - temperatureMin = rx_frame.data.u8[6]; //Lowest temp in battery - temperatureMax = rx_frame.data.u8[7]; //Highest temp in battery + leadAcidBatteryVoltage = rx_frame.data.u8[1]; //12v Battery Volts + temperatureMin = rx_frame.data.u8[6]; //Lowest temp in battery + temperatureMax = rx_frame.data.u8[7]; //Highest temp in battery break; case 0x598: - chargeTemperature = rx_frame.data.u8[7]; //ChargeportTemperature + chargeTemperature = rx_frame.data.u8[7]; //ChargeportTemperature break; case 0x5D5: waterleakageSensor = rx_frame.data.u8[3]; //Water sensor inside pack, value 164 is no water --> 0 is short - PRAtemp = rx_frame.data.u8[7]; //PowerRelayTemp + powerRelayTemperature = rx_frame.data.u8[7]; break; case 0x5D8: - counter++; - //ESP32Can.CANWriteFrame(&KIA64_524_1); - //ESP32Can.CANWriteFrame(&KIA64_291_1); //motor speed to 32767 if 100ms sent + if (counter < 200) { + counter++; + } //PID data is polled after last message sent from battery: - if (poll_data_pid >= 10){ //polling one of ten PIDs at 100ms, resolution = 1s + if (poll_data_pid >= 10) { //polling one of ten PIDs at 100ms, resolution = 1s poll_data_pid = 0; - } + } poll_data_pid++; - if (poll_data_pid == 1){ + if (poll_data_pid == 1) { ESP32Can.CANWriteFrame(&KIA64_7E4_id1); - } - else if (poll_data_pid == 2){ + } else if (poll_data_pid == 2) { ESP32Can.CANWriteFrame(&KIA64_7E4_id2); - } - else if (poll_data_pid == 5){ + } else if (poll_data_pid == 5) { ESP32Can.CANWriteFrame(&KIA64_7E4_id5); - } - else if (poll_data_pid == 6){ + } else if (poll_data_pid == 6) { ESP32Can.CANWriteFrame(&KIA64_7E4_id6); - } - else if (poll_data_pid == 8){ - } - else if (poll_data_pid == 9){ - } - else if (poll_data_pid == 10){ + } else if (poll_data_pid == 8) { + } else if (poll_data_pid == 9) { + } else if (poll_data_pid == 10) { } break; case 0x7EC: //Data From polled PID group, BigEndian - switch (rx_frame.data.u8[0]) - { - case 0x02: //"Diagnostic" - if (rx_frame.data.u8[1] == 0x7E){ - sendDiagnostic = 2; - } - case 0x03: //"Diagnostic" - if (rx_frame.data.u8[1] == 0x7F){ - sendDiagnostic = 4; - } - case 0x04: //"Diagnostic" - if (rx_frame.data.u8[1] == 0x6F){ - sendDiagnostic = 3; - } + switch (rx_frame.data.u8[0]) { case 0x10: //"PID Header" - if (rx_frame.data.u8[4] == poll_data_pid){ - ESP32Can.CANWriteFrame(&KIA64_7E4_ack); //Send ack to BMS if the same frame is sent as polled - } - break; + if (rx_frame.data.u8[4] == poll_data_pid) { + ESP32Can.CANWriteFrame(&KIA64_7E4_ack); //Send ack to BMS if the same frame is sent as polled + } + break; case 0x21: //First frame in PID group - if (poll_data_pid == 1){ - allowedChargePower = ((rx_frame.data.u8[3] << 8) + rx_frame.data.u8[4]); - allowedDischargePower = ((rx_frame.data.u8[5] << 8) + rx_frame.data.u8[6]); - batteryRelay = rx_frame.data.u8[7]; - } - break; + if (poll_data_pid == 1) { + allowedChargePower = ((rx_frame.data.u8[3] << 8) + rx_frame.data.u8[4]); + allowedDischargePower = ((rx_frame.data.u8[5] << 8) + rx_frame.data.u8[6]); + batteryRelay = rx_frame.data.u8[7]; + } + break; case 0x22: //Second datarow in PID group - if (poll_data_pid == 1){ - //battAmps = (rx_frame.data.u8[1] << 8) + rx_frame.data.u8[2]; //moved to passive data - //battVolts = (rx_frame.data.u8[3] << 8) + rx_frame.data.u8[4]; //moved to passive data - //tempMax = rx_frame.data.u8[5]; //moved to passive data - //tempMin = rx_frame.data.u8[6]; //moved to passive data - temp1 = rx_frame.data.u8[7]; - } - if (poll_data_pid == 6){ - batteryManagementMode = rx_frame.data.u8[5]; - } - break; + if (poll_data_pid == 6) { + batteryManagementMode = rx_frame.data.u8[5]; + } + break; case 0x23: //Third datarow in PID group - if (poll_data_pid == 1){ - tempinlet = rx_frame.data.u8[6]; - CellVoltMax = (rx_frame.data.u8[7] * 20); //(volts *50) *20 =mV - } - if (poll_data_pid == 5){ - //airbag = rx_frame.data.u8[6]; Not needed - heatertemp = rx_frame.data.u8[7]; - } - break; + if (poll_data_pid == 1) { + temperature_water_inlet = rx_frame.data.u8[6]; + CellVoltMax_mV = (rx_frame.data.u8[7] * 20); //(volts *50) *20 =mV + } + if (poll_data_pid == 5) { + //airbag = rx_frame.data.u8[6]; Not needed + heatertemp = rx_frame.data.u8[7]; + } + break; case 0x24: //Fourth datarow in PID group - if (poll_data_pid == 1){ - CellVmaxNo = rx_frame.data.u8[1]; - CellVminNo = rx_frame.data.u8[3]; - CellVoltMin = (rx_frame.data.u8[2] * 20); //(volts *50) *20 =mV - fanMode = rx_frame.data.u8[4]; - fanSpeed = rx_frame.data.u8[5]; - } - else if (poll_data_pid == 5){ - battSOH = ((rx_frame.data.u8[2] << 8) + rx_frame.data.u8[3]); - } - break; + if (poll_data_pid == 1) { + CellVmaxNo = rx_frame.data.u8[1]; + CellVminNo = rx_frame.data.u8[3]; + CellVoltMin_mV = (rx_frame.data.u8[2] * 20); //(volts *50) *20 =mV + fanMode = rx_frame.data.u8[4]; + fanSpeed = rx_frame.data.u8[5]; + } else if (poll_data_pid == 5) { + batterySOH = ((rx_frame.data.u8[2] << 8) + rx_frame.data.u8[3]); + } + break; case 0x25: //Fifth datarow in PID group - break; + break; case 0x26: //Sixth datarow in PID group - break; + break; case 0x27: //Seventh datarow in PID group - if (poll_data_pid == 1){ - BMS_ign = rx_frame.data.u8[6]; - Inv_VoltsTmp = rx_frame.data.u8[7]; - } - break; + if (poll_data_pid == 1) { + BMS_ign = rx_frame.data.u8[6]; + inverterVoltageFrameHigh = rx_frame.data.u8[7]; + } + break; case 0x28: //Eighth datarow in PID group - if (poll_data_pid == 1){ - Inv_Volts = (Inv_VoltsTmp << 8) + rx_frame.data.u8[1]; - } - break; + if (poll_data_pid == 1) { + inverterVoltage = (inverterVoltageFrameHigh << 8) + rx_frame.data.u8[1]; + } + break; } - break; - default: - break; + break; + default: + break; } } void send_can_kiaHyundai_64_battery() { @@ -404,51 +428,50 @@ void send_can_kiaHyundai_64_battery() { if (currentMillis - previousMillis10ms >= interval10ms) { previousMillis10ms = currentMillis; - switch (counter_200) { - case 0: + switch (counter_200) { + case 0: KIA_HYUNDAI_200.data.u8[5] = 0x17; ++counter_200; break; - case 1: + case 1: KIA_HYUNDAI_200.data.u8[5] = 0x57; ++counter_200; break; - case 2: + case 2: KIA_HYUNDAI_200.data.u8[5] = 0x97; ++counter_200; break; - case 3: + case 3: KIA_HYUNDAI_200.data.u8[5] = 0xD7; ++counter_200; break; - case 4: + case 4: KIA_HYUNDAI_200.data.u8[3] = 0x10; KIA_HYUNDAI_200.data.u8[5] = 0xFF; ++counter_200; break; - case 5: + case 5: KIA_HYUNDAI_200.data.u8[5] = 0x3B; ++counter_200; break; - case 6: + case 6: KIA_HYUNDAI_200.data.u8[5] = 0x7B; ++counter_200; break; - case 7: + case 7: KIA_HYUNDAI_200.data.u8[5] = 0xBB; ++counter_200; break; - case 8: + case 8: KIA_HYUNDAI_200.data.u8[5] = 0xFB; counter_200 = 5; break; - } + } - ESP32Can.CANWriteFrame(&KIA_HYUNDAI_200); + ESP32Can.CANWriteFrame(&KIA_HYUNDAI_200); - ESP32Can.CANWriteFrame(&KIA_HYUNDAI_523); - - ESP32Can.CANWriteFrame(&KIA_HYUNDAI_524); + ESP32Can.CANWriteFrame(&KIA_HYUNDAI_523); + ESP32Can.CANWriteFrame(&KIA_HYUNDAI_524); } } From 36389ca59fc9e725cbd098f7675ab28035e445a4 Mon Sep 17 00:00:00 2001 From: LevinSwe Date: Fri, 12 Jan 2024 21:03:18 +0100 Subject: [PATCH 07/13] Update KIA-HYUNDAI-64-BATTERY.cpp - Changes in when inverter volts change from 0 to battery volts - Changes in when mid-log value of frame 0x200 is sent --- Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp b/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp index 43dbdb7e..1a064128 100644 --- a/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp +++ b/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp @@ -288,9 +288,9 @@ void update_values_kiaHyundai_64_battery() { //This function maps all the value } if (bitRead((uint8_t)batteryRelay, 0) == 1) { - Serial.print(" | BMS Output ON"); + Serial.print(" | PowerRelay ON"); } else { - Serial.print(" | BMS Output OFF"); + Serial.print(" | PowerRelay OFF"); } Serial.print(" | Inverter "); Serial.print(inverterVoltage); @@ -313,7 +313,7 @@ void receive_can_kiaHyundai_64_battery(CAN_frame_t rx_frame) { case 0x595: batteryVoltage = (rx_frame.data.u8[7] << 8) + rx_frame.data.u8[6]; batteryAmps = (rx_frame.data.u8[5] << 8) + rx_frame.data.u8[4]; - if (counter > 51) { + if (counter_200 > 3) { KIA_HYUNDAI_524.data.u8[0] = (uint8_t)(batteryVoltage / 10); KIA_HYUNDAI_524.data.u8[1] = (uint8_t)((batteryVoltage / 10) >> 8); } //VCU measured voltage sent back to bms @@ -331,9 +331,7 @@ void receive_can_kiaHyundai_64_battery(CAN_frame_t rx_frame) { powerRelayTemperature = rx_frame.data.u8[7]; break; case 0x5D8: - if (counter < 200) { - counter++; - } + counter = 1; //PID data is polled after last message sent from battery: if (poll_data_pid >= 10) { //polling one of ten PIDs at 100ms, resolution = 1s @@ -443,7 +441,12 @@ void send_can_kiaHyundai_64_battery() { break; case 3: KIA_HYUNDAI_200.data.u8[5] = 0xD7; - ++counter_200; + if (counter == 1) { + ++counter_200; + } + else { + counter_200 = 0; + } break; case 4: KIA_HYUNDAI_200.data.u8[3] = 0x10; From 3f3ed09900bf40fc1ef84975170f5744ce67ab96 Mon Sep 17 00:00:00 2001 From: LevinSwe Date: Fri, 12 Jan 2024 21:07:41 +0100 Subject: [PATCH 08/13] Update webserver.h - BMS status changed to uint8 --- Software/src/devboard/webserver/webserver.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Software/src/devboard/webserver/webserver.h b/Software/src/devboard/webserver/webserver.h index 62a83096..38732c35 100644 --- a/Software/src/devboard/webserver/webserver.h +++ b/Software/src/devboard/webserver/webserver.h @@ -18,8 +18,8 @@ extern uint16_t capacity_Wh; //Wh, 0-60000 extern uint16_t remaining_capacity_Wh; //Wh, 0-60000 extern uint16_t max_target_discharge_power; //W, 0-60000 extern uint16_t max_target_charge_power; //W, 0-60000 -extern uint16_t bms_status; //Enum, 0-5 -extern uint16_t bms_char_dis_status; //Enum, 0-2 +extern uint8_t bms_status; //Enum, 0-5 +extern uint8_t bms_char_dis_status; //Enum, 0-2 extern uint16_t stat_batt_power; //W, Goes thru convert2unsignedint16 function (5W = 5, -5W = 65530) extern uint16_t temperature_min; //C+1, Goes thru convert2unsignedint16 function (15.0C = 150, -15.0C = 65385) extern uint16_t temperature_max; //C+1, Goes thru convert2unsignedint16 function (15.0C = 150, -15.0C = 65385) From cb44f4709d4196849395af415afc0af4f842c724 Mon Sep 17 00:00:00 2001 From: LevinSwe Date: Sat, 13 Jan 2024 12:01:48 +0100 Subject: [PATCH 09/13] Update KIA-HYUNDAI-64-BATTERY.cpp - Remove of unused variables - minor changes due to clang-format --- .../src/battery/KIA-HYUNDAI-64-BATTERY.cpp | 25 +++---------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp b/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp index 1a064128..f2b0f29d 100644 --- a/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp +++ b/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp @@ -36,24 +36,11 @@ static int8_t temperature_water_inlet = 0; static uint8_t batteryManagementMode = 0; static uint8_t BMS_ign = 0; static int16_t poll_data_pid = 0; -static int16_t poll109 = 0; -static int16_t pollA2A = 0; -static int16_t poll200 = 0; -static int16_t poll201 = 0; -static int16_t poll2B0 = 0; -static int16_t poll450 = 0; -static int16_t poll471 = 0; -static int16_t poll523 = 0; static int8_t heatertemp = 0; static uint8_t batteryRelay = 0; static int8_t powerRelayTemperature = 0; static uint16_t inverterVoltageFrameHigh = 0; static uint16_t inverterVoltage = 0; -static int8_t radiatorTemperature = 0; -static int8_t chargeTemperature = 0; -static int8_t fanMode = 0; -static int8_t fanSpeed = 0; -static int8_t state3F6 = 0; static uint8_t counter = 0; static uint8_t counter_200 = 0; @@ -282,9 +269,9 @@ void update_values_kiaHyundai_64_battery() { //This function maps all the value Serial.print("BmsManagementMode "); Serial.print((uint8_t)batteryManagementMode, BIN); if (bitRead((uint8_t)BMS_ign, 2) == 1) { - Serial.print(" | BmsIgnitionON"); + Serial.print(" | BmsIgnition ON"); } else { - Serial.print(" | BmsIgnitionOFF"); + Serial.print(" | BmsIgnition OFF"); } if (bitRead((uint8_t)batteryRelay, 0) == 1) { @@ -301,7 +288,6 @@ void update_values_kiaHyundai_64_battery() { //This function maps all the value void receive_can_kiaHyundai_64_battery(CAN_frame_t rx_frame) { switch (rx_frame.MsgID) { case 0x4DE: - radiatorTemperature = rx_frame.data.u8[4]; //-15 break; case 0x542: //BMS SOC CANstillAlive = 12; //We use this message to verify that BMS is still alive @@ -324,7 +310,6 @@ void receive_can_kiaHyundai_64_battery(CAN_frame_t rx_frame) { temperatureMax = rx_frame.data.u8[7]; //Highest temp in battery break; case 0x598: - chargeTemperature = rx_frame.data.u8[7]; //ChargeportTemperature break; case 0x5D5: waterleakageSensor = rx_frame.data.u8[3]; //Water sensor inside pack, value 164 is no water --> 0 is short @@ -376,7 +361,6 @@ void receive_can_kiaHyundai_64_battery(CAN_frame_t rx_frame) { CellVoltMax_mV = (rx_frame.data.u8[7] * 20); //(volts *50) *20 =mV } if (poll_data_pid == 5) { - //airbag = rx_frame.data.u8[6]; Not needed heatertemp = rx_frame.data.u8[7]; } break; @@ -385,8 +369,6 @@ void receive_can_kiaHyundai_64_battery(CAN_frame_t rx_frame) { CellVmaxNo = rx_frame.data.u8[1]; CellVminNo = rx_frame.data.u8[3]; CellVoltMin_mV = (rx_frame.data.u8[2] * 20); //(volts *50) *20 =mV - fanMode = rx_frame.data.u8[4]; - fanSpeed = rx_frame.data.u8[5]; } else if (poll_data_pid == 5) { batterySOH = ((rx_frame.data.u8[2] << 8) + rx_frame.data.u8[3]); } @@ -443,8 +425,7 @@ void send_can_kiaHyundai_64_battery() { KIA_HYUNDAI_200.data.u8[5] = 0xD7; if (counter == 1) { ++counter_200; - } - else { + } else { counter_200 = 0; } break; From 41b41720853a669f5eab7d0c173314397731f48e Mon Sep 17 00:00:00 2001 From: LevinSwe Date: Sat, 13 Jan 2024 13:19:17 +0100 Subject: [PATCH 10/13] Update webserver.cpp - Temperature calculation fix when negative. --- Software/src/devboard/webserver/webserver.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Software/src/devboard/webserver/webserver.cpp b/Software/src/devboard/webserver/webserver.cpp index ca6e5357..915c32b5 100644 --- a/Software/src/devboard/webserver/webserver.cpp +++ b/Software/src/devboard/webserver/webserver.cpp @@ -264,12 +264,12 @@ String processor(const String& var) { float tempMaxFloat = 0; float tempMinFloat = 0; if (temperature_max > 32767) { //Handle negative values on this unsigned value - tempMaxFloat = static_cast(-(65535 - temperature_max)) / 10.0; // Convert to float and divide by 10 + tempMaxFloat = static_cast(-(65536 - temperature_max)) / 10.0; // Convert to float and divide by 10 } else { tempMaxFloat = static_cast(temperature_max) / 10.0; // Convert to float and divide by 10 } if (temperature_min > 32767) { //Handle negative values on this unsigned value - tempMinFloat = static_cast(-(65535 - temperature_min)) / 10.0; // Convert to float and divide by 10 + tempMinFloat = static_cast(-(65536 - temperature_min)) / 10.0; // Convert to float and divide by 10 } else { tempMinFloat = static_cast(temperature_min) / 10.0; // Convert to float and divide by 10 } From 01aba5c7b10daeddbc405109bd8285e990a720ab Mon Sep 17 00:00:00 2001 From: LevinSwe Date: Sat, 13 Jan 2024 14:27:23 +0100 Subject: [PATCH 11/13] Update webserver.h - clang pre commit fix --- Software/src/devboard/webserver/webserver.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Software/src/devboard/webserver/webserver.h b/Software/src/devboard/webserver/webserver.h index 38732c35..eb99c06b 100644 --- a/Software/src/devboard/webserver/webserver.h +++ b/Software/src/devboard/webserver/webserver.h @@ -18,8 +18,8 @@ extern uint16_t capacity_Wh; //Wh, 0-60000 extern uint16_t remaining_capacity_Wh; //Wh, 0-60000 extern uint16_t max_target_discharge_power; //W, 0-60000 extern uint16_t max_target_charge_power; //W, 0-60000 -extern uint8_t bms_status; //Enum, 0-5 -extern uint8_t bms_char_dis_status; //Enum, 0-2 +extern uint8_t bms_status; //Enum, 0-5 +extern uint8_t bms_char_dis_status; //Enum, 0-2 extern uint16_t stat_batt_power; //W, Goes thru convert2unsignedint16 function (5W = 5, -5W = 65530) extern uint16_t temperature_min; //C+1, Goes thru convert2unsignedint16 function (15.0C = 150, -15.0C = 65385) extern uint16_t temperature_max; //C+1, Goes thru convert2unsignedint16 function (15.0C = 150, -15.0C = 65385) From 5d40e5a98635700054902b91216383794cddd1a3 Mon Sep 17 00:00:00 2001 From: Daniel Date: Sun, 14 Jan 2024 10:19:02 +0200 Subject: [PATCH 12/13] Fix TODO scalings --- .../src/battery/KIA-HYUNDAI-64-BATTERY.cpp | 36 ++++++++++++------- Software/src/battery/KIA-HYUNDAI-64-BATTERY.h | 3 +- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp b/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp index f2b0f29d..d17a383b 100644 --- a/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp +++ b/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp @@ -30,8 +30,9 @@ static int16_t allowedDischargePower = 0; static int16_t allowedChargePower = 0; static uint16_t batteryVoltage = 0; static int16_t batteryAmps = 0; -static int8_t temperatureMax = 0; -static int8_t temperatureMin = 0; +static int16_t powerWatt = 0; +static int16_t temperatureMax = 0; +static int16_t temperatureMin = 0; static int8_t temperature_water_inlet = 0; static uint8_t batteryManagementMode = 0; static uint8_t BMS_ign = 0; @@ -41,7 +42,7 @@ static uint8_t batteryRelay = 0; static int8_t powerRelayTemperature = 0; static uint16_t inverterVoltageFrameHigh = 0; static uint16_t inverterVoltage = 0; -static uint8_t counter = 0; +static uint8_t startedUp = false; static uint8_t counter_200 = 0; CAN_frame_t KIA_HYUNDAI_200 = {.FIR = {.B = @@ -159,9 +160,9 @@ void update_values_kiaHyundai_64_battery() { //This function maps all the value StateOfHealth = (batterySOH * 10); //Increase decimals from 100.0% -> 100.00% - battery_voltage = batteryVoltage; //value is *10 + battery_voltage = batteryVoltage; //value is *10 (3700 = 370.0) - battery_current = (int16_t)batteryAmps; //value is *10 //Todo, the signed part breaks something here for sure + battery_current = convertToUnsignedInt16(batteryAmps); //value is *10 (150 = 15.0) capacity_Wh = BATTERY_WH_MAX; @@ -171,12 +172,13 @@ void update_values_kiaHyundai_64_battery() { //This function maps all the value max_target_charge_power = (uint16_t)allowedChargePower * 10; //From kW*100 to Watts - stat_batt_power = (batteryVoltage * (int16_t)batteryAmps) / - 100; //Power in watts, Negative = charging batt. //Todo, the signed part will break something here + powerWatt = ((batteryVoltage * batteryAmps) / 100); - temperature_min = ((int8_t)temperatureMin * 10); //Increase decimals, 17C -> 17.0C + stat_batt_power = convertToUnsignedInt16(powerWatt); //Power in watts, Negative = charging batt - temperature_max = ((int8_t)temperatureMax * 10); //Increase decimals, 18C -> 18.0C + temperature_min = convertToUnsignedInt16(temperatureMin * 10); //Increase decimals, 17C -> 17.0C + + temperature_max = convertToUnsignedInt16(temperatureMax * 10); //Increase decimals, 18C -> 18.0C cell_max_voltage = CellVoltMax_mV; @@ -255,9 +257,9 @@ void update_values_kiaHyundai_64_battery() { //This function maps all the value Serial.print(" mV No "); Serial.println(CellVminNo); Serial.print("TempHi "); - Serial.print((int8_t)temperatureMax); + Serial.print((int16_t)temperatureMax); Serial.print("°C TempLo "); - Serial.print((int8_t)temperatureMin); + Serial.print((int16_t)temperatureMin); Serial.print("°C WaterInlet "); Serial.print((int8_t)temperature_water_inlet); Serial.print("°C PowerRelay "); @@ -316,7 +318,7 @@ void receive_can_kiaHyundai_64_battery(CAN_frame_t rx_frame) { powerRelayTemperature = rx_frame.data.u8[7]; break; case 0x5D8: - counter = 1; + startedUp = 1; //PID data is polled after last message sent from battery: if (poll_data_pid >= 10) { //polling one of ten PIDs at 100ms, resolution = 1s @@ -423,7 +425,7 @@ void send_can_kiaHyundai_64_battery() { break; case 3: KIA_HYUNDAI_200.data.u8[5] = 0xD7; - if (counter == 1) { + if (startedUp) { ++counter_200; } else { counter_200 = 0; @@ -459,3 +461,11 @@ void send_can_kiaHyundai_64_battery() { ESP32Can.CANWriteFrame(&KIA_HYUNDAI_524); } } + +uint16_t convertToUnsignedInt16(int16_t signed_value) { + if (signed_value < 0) { + return (65535 + signed_value); + } else { + return (uint16_t)signed_value; + } +} diff --git a/Software/src/battery/KIA-HYUNDAI-64-BATTERY.h b/Software/src/battery/KIA-HYUNDAI-64-BATTERY.h index d4b99a2e..d933b015 100644 --- a/Software/src/battery/KIA-HYUNDAI-64-BATTERY.h +++ b/Software/src/battery/KIA-HYUNDAI-64-BATTERY.h @@ -26,11 +26,12 @@ extern uint16_t temperature_max; //C+1, Goes thru convert2unsignedint16 funct extern uint16_t cell_max_voltage; //mV, 0-4350 extern uint16_t cell_min_voltage; //mV, 0-4350 extern uint8_t LEDcolor; //Enum, 0-10 -extern bool batteryAllowsContactorClosing; //Bool, 1=true, 0=false +extern bool batteryAllowsContactorClosing; //Bool, 1=true, 0=false extern bool inverterAllowsContactorClosing; //Bool, 1=true, 0=false void update_values_kiaHyundai_64_battery(); void receive_can_kiaHyundai_64_battery(CAN_frame_t rx_frame); void send_can_kiaHyundai_64_battery(); +uint16_t convertToUnsignedInt16(int16_t signed_value); #endif From 8204676c9d69bbb8a10ea6381e9fd127e5d8065c Mon Sep 17 00:00:00 2001 From: Daniel Date: Wed, 17 Jan 2024 16:48:05 +0200 Subject: [PATCH 13/13] Add estimated charge/discharge values --- Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp | 16 +++++++++++++--- Software/src/battery/KIA-HYUNDAI-64-BATTERY.h | 2 ++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp b/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp index d17a383b..91413fed 100644 --- a/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp +++ b/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp @@ -168,9 +168,19 @@ void update_values_kiaHyundai_64_battery() { //This function maps all the value remaining_capacity_Wh = static_cast((static_cast(SOC) / 10000) * BATTERY_WH_MAX); - max_target_discharge_power = (uint16_t)allowedDischargePower * 10; //From kW*100 to Watts - - max_target_charge_power = (uint16_t)allowedChargePower * 10; //From kW*100 to Watts + //max_target_charge_power = (uint16_t)allowedChargePower * 10; //From kW*100 to Watts + //The allowed charge power is not available. We estimate this value + if (SOC == 10000) { // When scaled SOC is 100%, set allowed charge power to 0 + max_target_charge_power = 0; + } else { // No limits, max charging power allowed + max_target_charge_power = MAXCHARGEPOWERALLOWED; + } + //max_target_discharge_power = (uint16_t)allowedDischargePower * 10; //From kW*100 to Watts + if (SOC < 100) { // When scaled SOC is <1%, set allowed charge power to 0 + max_target_discharge_power = 0; + } else { // No limits, max charging power allowed + max_target_discharge_power = MAXDISCHARGEPOWERALLOWED; + } powerWatt = ((batteryVoltage * batteryAmps) / 100); diff --git a/Software/src/battery/KIA-HYUNDAI-64-BATTERY.h b/Software/src/battery/KIA-HYUNDAI-64-BATTERY.h index d933b015..47d5e2ba 100644 --- a/Software/src/battery/KIA-HYUNDAI-64-BATTERY.h +++ b/Software/src/battery/KIA-HYUNDAI-64-BATTERY.h @@ -8,6 +8,8 @@ #define ABSOLUTE_MAX_VOLTAGE \ 4040 // 404.4V,if battery voltage goes over this, charging is not possible (goes into forced discharge) #define ABSOLUTE_MIN_VOLTAGE 3100 // 310.0V if battery voltage goes under this, discharging further is disabled +#define MAXCHARGEPOWERALLOWED 10000 +#define MAXDISCHARGEPOWERALLOWED 10000 // These parameters need to be mapped for the Gen24 extern uint16_t SOC; //SOC%, 0-100.00 (0-10000)