diff --git a/Software/src/battery/BMW-I3-BATTERY.cpp b/Software/src/battery/BMW-I3-BATTERY.cpp index 526bfbd8..51571e6b 100644 --- a/Software/src/battery/BMW-I3-BATTERY.cpp +++ b/Software/src/battery/BMW-I3-BATTERY.cpp @@ -27,7 +27,7 @@ unsigned long turnOnTime; // Variables to store timestamps enum State { POWERON, STATE_ON, STATE_OFF }; static State WUPState = POWERON; -enum CmdState { SOH, CELL_VOLTAGE, SOC, CELL_VOLTAGE_AVG }; +enum CmdState { SOH, CELL_VOLTAGE_MINMAX, SOC, CELL_VOLTAGE_AVG, CELL_VOLTAGE_CELLNO }; static CmdState cmdState = SOH; const unsigned char crc8_table[256] = @@ -302,6 +302,13 @@ CAN_frame_t BMW_6F1_CELL_VOLTAGE_AVG = {.FIR = {.B = }}, .MsgID = 0x6F1, .data = {0x07, 0x03, 0x22, 0xDF, 0xA0}}; +CAN_frame_t BMW_6F1_CELL_VOLTAGE_CELLNO = {.FIR = {.B = + { + .DLC = 7, + .FF = CAN_frame_std, + }}, + .MsgID = 0x6F1, + .data = {0x07, 0x05, 0x31, 0x01, 0xAD, 0x6E, 0x01}}; CAN_frame_t BMW_6F1_CONTINUE = {.FIR = {.B = { @@ -310,6 +317,13 @@ CAN_frame_t BMW_6F1_CONTINUE = {.FIR = {.B = }}, .MsgID = 0x6F1, .data = {0x07, 0x30, 0x00, 0x02}}; +CAN_frame_t BMW_6F1_CELL_CONTINUE = {.FIR = {.B = + { + .DLC = 6, + .FF = CAN_frame_std, + }}, + .MsgID = 0x6F1, + .data = {0x07, 0x04, 0x31, 0x03, 0xAD, 0x6E}}; //The above CAN messages need to be sent towards the battery to keep it alive static uint8_t startup_counter_contactor = 0; @@ -397,6 +411,7 @@ static uint8_t battery_soh = 99; static uint8_t message_data[50]; static uint8_t next_data = 0; +static uint8_t current_cell_polled = 1; static uint8_t calculateCRC(CAN_frame_t rx_frame, uint8_t length, uint8_t initial_value) { uint8_t crc = initial_value; @@ -441,11 +456,6 @@ void update_values_battery() { //This function maps all the values fetched via datalayer.battery.status.temperature_max_dC = battery_temperature_max * 10; // Add a decimal - 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]; - } - if (battery_info_available) { // Start checking safeties. First up, cellvoltages! if (detectedBattery == BATTERY_60AH) { @@ -631,6 +641,16 @@ void receive_can_battery(CAN_frame_t rx_frame) { battery_ID2 = rx_frame.data.u8[0]; break; case 0x607: //BMS - responses to message requests on 0x615 + if ((cmdState == CELL_VOLTAGE_CELLNO) && (rx_frame.data.u8[0] == 0xF4)) { + if (rx_frame.FIR.B.DLC == 6) { + ESP32Can.CANWriteFrame(&BMW_6F1_CELL_CONTINUE); // tell battery to send the cellvoltage + } + if (rx_frame.FIR.B.DLC == 8) { // We have the full value, map it + datalayer.battery.status.cell_voltages_mV[current_cell_polled - 1] = + (rx_frame.data.u8[6] << 8 | rx_frame.data.u8[7]); + } + } + if (rx_frame.FIR.B.DLC > 6 && next_data == 0 && rx_frame.data.u8[0] == 0xf1) { uint8_t count = 6; while (count < rx_frame.FIR.B.DLC && next_data < 49) { @@ -646,15 +666,15 @@ void receive_can_battery(CAN_frame_t rx_frame) { } switch (cmdState) { - case CELL_VOLTAGE: + case CELL_VOLTAGE_MINMAX: if (next_data >= 4) { - datalayer.battery.status.cell_voltages_mV[0] = (message_data[0] << 8 | message_data[1]); - datalayer.battery.status.cell_voltages_mV[2] = (message_data[2] << 8 | message_data[3]); + datalayer.battery.status.cell_min_voltage_mV = (message_data[0] << 8 | message_data[1]); + datalayer.battery.status.cell_max_voltage_mV = (message_data[2] << 8 | message_data[3]); } break; case CELL_VOLTAGE_AVG: - if (next_data >= 30) { - datalayer.battery.status.cell_voltages_mV[1] = (message_data[10] << 8 | message_data[11]) / 10; + if (next_data >= 30) { //AVG not used + //datalayer.battery.status.cell_voltages_mV[1] = (message_data[10] << 8 | message_data[11]) / 10; battery_capacity_cah = (message_data[4] << 8 | message_data[5]); } break; @@ -800,9 +820,9 @@ void send_can_battery() { switch (cmdState) { case SOC: ESP32Can.CANWriteFrame(&BMW_6F1_CELL); - cmdState = CELL_VOLTAGE; + cmdState = CELL_VOLTAGE_MINMAX; break; - case CELL_VOLTAGE: + case CELL_VOLTAGE_MINMAX: ESP32Can.CANWriteFrame(&BMW_6F1_SOH); cmdState = SOH; break; @@ -811,6 +831,15 @@ void send_can_battery() { cmdState = CELL_VOLTAGE_AVG; break; case CELL_VOLTAGE_AVG: + ESP32Can.CANWriteFrame(&BMW_6F1_CELL_VOLTAGE_CELLNO); + cmdState = CELL_VOLTAGE_CELLNO; + current_cell_polled++; + if (current_cell_polled > 96) { + current_cell_polled = 1; + } + BMW_6F1_CELL_VOLTAGE_CELLNO.data.u8[6] = current_cell_polled; + break; + case CELL_VOLTAGE_CELLNO: ESP32Can.CANWriteFrame(&BMW_6F1_SOC); cmdState = SOC; break;