Merge pull request #249 from dalathegreat/feature/BMW-3-additional-data

Feature/bmw 3 additional data
This commit is contained in:
Daniel Öster 2024-04-10 18:56:04 +03:00 committed by GitHub
commit 241dda109d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 109 additions and 9 deletions

View file

@ -25,6 +25,9 @@ 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 };
static CmdState cmdState = SOH;
const unsigned char crc8_table[256] =
{ // CRC8_SAE_J1850_ZER0 formula,0x1D Poly,initial value 0x3F,Final XOR value varies
0x00, 0x1D, 0x3A, 0x27, 0x74, 0x69, 0x4E, 0x53, 0xE8, 0xF5, 0xD2, 0xCF, 0x9C, 0x81, 0xA6, 0xBB, 0xCD, 0xD0,
@ -266,6 +269,45 @@ CAN_frame_t BMW_5F8 = {.FIR = {.B =
.MsgID = 0x5F8,
.data = {0x64, 0x01, 0x00, 0x0B, 0x92, 0x03, 0x00, 0x05}};
CAN_frame_t BMW_6F1_CELL = {.FIR = {.B =
{
.DLC = 5,
.FF = CAN_frame_std,
}},
.MsgID = 0x6F1,
.data = {0x07, 0x03, 0x22, 0xDD, 0xBF}};
CAN_frame_t BMW_6F1_SOH = {.FIR = {.B =
{
.DLC = 5,
.FF = CAN_frame_std,
}},
.MsgID = 0x6F1,
.data = {0x07, 0x03, 0x22, 0x63, 0x35}};
CAN_frame_t BMW_6F1_SOC = {.FIR = {.B =
{
.DLC = 5,
.FF = CAN_frame_std,
}},
.MsgID = 0x6F1,
.data = {0x07, 0x03, 0x22, 0xDD, 0xBC}};
CAN_frame_t BMW_6F1_CELL_VOLTAGE_AVG = {.FIR = {.B =
{
.DLC = 5,
.FF = CAN_frame_std,
}},
.MsgID = 0x6F1,
.data = {0x07, 0x03, 0x22, 0xDF, 0xA0}};
CAN_frame_t BMW_6F1_CONTINUE = {.FIR = {.B =
{
.DLC = 4,
.FF = CAN_frame_std,
}},
.MsgID = 0x6F1,
.data = {0x07, 0x30, 0x00, 0x02}};
//The above CAN messages need to be sent towards the battery to keep it alive
static uint8_t startup_counter_contactor = 0;
@ -306,6 +348,11 @@ static uint16_t battery_prediction_voltage_longterm_charge = 0;
static uint16_t battery_prediction_voltage_longterm_discharge = 0;
static uint16_t battery_prediction_duration_charging_minutes = 0;
static uint16_t battery_target_voltage_in_CV_mode = 0;
static uint16_t battery_soc = 0;
static uint16_t battery_soc_hvmax = 0;
static uint16_t battery_soc_hvmin = 0;
static uint16_t battery_capacity_cah = 0;
static int16_t battery_temperature_HV = 0;
static int16_t battery_temperature_heat_exchanger = 0;
static int16_t battery_temperature_max = 0;
@ -344,6 +391,10 @@ static uint8_t battery_status_diagnosis_powertrain_maximum_multiplexer = 0;
static uint8_t battery_status_diagnosis_powertrain_immediate_multiplexer = 0;
static uint8_t battery_ID2 = 0;
static uint8_t battery_cellvoltage_mux = 0;
static uint8_t battery_soh = 0;
static uint8_t message_data[50];
static uint8_t next_data = 0;
static uint8_t calculateCRC(CAN_frame_t rx_frame, uint8_t length, uint8_t initial_value) {
uint8_t crc = initial_value;
@ -363,7 +414,7 @@ static uint8_t increment_alive_counter(uint8_t counter) {
void update_values_battery() { //This function maps all the values fetched via CAN to the correct parameters used for modbus
system_real_SOC_pptt = (battery_display_SOC * 100); //increase Display_SOC range from 0-100 -> 100.00
system_real_SOC_pptt = (battery_HVBatt_SOC * 10);
system_battery_voltage_dV = battery_volts; //Unit V+1 (5000 = 500.0V)
@ -373,16 +424,17 @@ void update_values_battery() { //This function maps all the values fetched via
system_remaining_capacity_Wh = (battery_energy_content_maximum_kWh * 1000); // Convert kWh to Wh
if ((battery_max_charge_amperage * system_battery_voltage_dV) > 65000) {
system_max_charge_power_W = 65000;
} else {
system_max_charge_power_W = (battery_max_charge_amperage * system_battery_voltage_dV);
}
system_SOH_pptt = battery_soh * 100;
if ((battery_max_discharge_amperage * system_battery_voltage_dV) > 65000) {
if (battery_BEV_available_power_longterm_discharge > 65000) {
system_max_discharge_power_W = 65000;
} else {
system_max_discharge_power_W = (battery_max_discharge_amperage * system_battery_voltage_dV);
system_max_discharge_power_W = battery_BEV_available_power_longterm_discharge;
}
if (battery_BEV_available_power_longterm_charge > 65000) {
system_max_charge_power_W = 65000;
} else {
system_max_charge_power_W = battery_BEV_available_power_longterm_charge;
}
battery_power = (system_battery_current_dA * (system_battery_voltage_dV / 100));
@ -393,6 +445,9 @@ void update_values_battery() { //This function maps all the values fetched via
system_temperature_max_dC = battery_temperature_max * 10; // Add a decimal
system_cell_min_voltage_mV = system_cellvoltages_mV[0];
system_cell_max_voltage_mV = system_cellvoltages_mV[1];
/* Check if the BMS is still sending CAN messages. If we go 60s without messages we raise an error*/
if (!CANstillAlive) {
set_event(EVENT_CAN_RX_FAILURE, 0);
@ -549,7 +604,48 @@ void receive_can_battery(CAN_frame_t rx_frame) {
case 0x587: //BMS [5s] Services
battery_ID2 = rx_frame.data.u8[0];
break;
case 0x607: //BMS - No use for this message
case 0x607: //BMS - responses to message requests on 0x615
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) {
message_data[next_data++] = rx_frame.data.u8[count++];
}
ESP32Can.CANWriteFrame(&BMW_6F1_CONTINUE); // tell battery to send additional messages
} else if (rx_frame.FIR.B.DLC > 3 && next_data > 0 && rx_frame.data.u8[0] == 0xf1 &&
((rx_frame.data.u8[1] & 0xF0) == 0x20)) {
uint8_t count = 2;
while (count < rx_frame.FIR.B.DLC && next_data < 49) {
message_data[next_data++] = rx_frame.data.u8[count++];
}
switch (cmdState) {
case CELL_VOLTAGE:
if (next_data >= 4) {
system_cellvoltages_mV[0] = (message_data[0] << 8 | message_data[1]);
system_cellvoltages_mV[2] = (message_data[2] << 8 | message_data[3]);
}
break;
case CELL_VOLTAGE_AVG:
if (next_data >= 30) {
system_cellvoltages_mV[1] = (message_data[10] << 8 | message_data[11]) / 10;
battery_capacity_cah = (message_data[4] << 8 | message_data[5]);
}
break;
case SOH:
if (next_data >= 4) {
battery_soh = message_data[3];
}
break;
case SOC:
if (next_data >= 6) {
battery_soc = (message_data[0] << 8 | message_data[1]);
battery_soc_hvmax = (message_data[2] << 8 | message_data[3]);
battery_soc_hvmin = (message_data[4] << 8 | message_data[5]);
}
break;
}
}
break;
default:
break;
@ -699,6 +795,9 @@ void send_can_battery() {
ESP32Can.CANWriteFrame(&BMW_3E4);
ESP32Can.CANWriteFrame(&BMW_37B);
next_data = 0;
ESP32Can.CANWriteFrame(&BMW_6F1_CELL);
BMW_3E5.data.u8[0] = 0xFD; // First 3E5 message byte0 we send is unique, once we sent initial value send this
}
}

View file

@ -529,6 +529,7 @@ String processor(const String& var) {
} else { // > 0
content += "<h4>Battery charging!</h4>";
}
content += "<h4>Automatic contactor closing allowed:</h4>";
content += "<h4>Battery: ";
if (batteryAllowsContactorClosing) {