mirror of
https://github.com/dalathegreat/Battery-Emulator.git
synced 2025-10-06 03:50:13 +02:00
Add cell min/max voltage + max charge/discharge + simple SOH + use real SOC for better resolution
This commit is contained in:
parent
194facd6de
commit
a891257019
1 changed files with 54 additions and 9 deletions
|
@ -266,6 +266,20 @@ CAN_frame_t BMW_5F8 = {.FIR = {.B =
|
||||||
.MsgID = 0x5F8,
|
.MsgID = 0x5F8,
|
||||||
.data = {0x64, 0x01, 0x00, 0x0B, 0x92, 0x03, 0x00, 0x05}};
|
.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_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
|
//The above CAN messages need to be sent towards the battery to keep it alive
|
||||||
|
|
||||||
static uint8_t startup_counter_contactor = 0;
|
static uint8_t startup_counter_contactor = 0;
|
||||||
|
@ -345,6 +359,9 @@ static uint8_t battery_status_diagnosis_powertrain_immediate_multiplexer = 0;
|
||||||
static uint8_t battery_ID2 = 0;
|
static uint8_t battery_ID2 = 0;
|
||||||
static uint8_t battery_cellvoltage_mux = 0;
|
static uint8_t battery_cellvoltage_mux = 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) {
|
static uint8_t calculateCRC(CAN_frame_t rx_frame, uint8_t length, uint8_t initial_value) {
|
||||||
uint8_t crc = initial_value;
|
uint8_t crc = initial_value;
|
||||||
for (uint8_t j = 1; j < length; j++) { //start at 1, since 0 is the CRC
|
for (uint8_t j = 1; j < length; j++) { //start at 1, since 0 is the CRC
|
||||||
|
@ -363,7 +380,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
|
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); //increase Display_SOC range from 0-100 -> 100.00
|
||||||
|
|
||||||
system_battery_voltage_dV = battery_volts; //Unit V+1 (5000 = 500.0V)
|
system_battery_voltage_dV = battery_volts; //Unit V+1 (5000 = 500.0V)
|
||||||
|
|
||||||
|
@ -373,16 +390,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
|
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_SOH_pptt = battery_energy_content_maximum_kWh * 10000 / 27.2;
|
||||||
system_max_charge_power_W = 65000;
|
|
||||||
} else {
|
|
||||||
system_max_charge_power_W = (battery_max_charge_amperage * system_battery_voltage_dV);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((battery_max_discharge_amperage * system_battery_voltage_dV) > 65000) {
|
if (battery_BEV_available_power_longterm_discharge > 65000) {
|
||||||
system_max_discharge_power_W = 65000;
|
system_max_discharge_power_W = 65000;
|
||||||
} else {
|
} 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));
|
battery_power = (system_battery_current_dA * (system_battery_voltage_dV / 100));
|
||||||
|
@ -393,6 +411,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_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*/
|
/* Check if the BMS is still sending CAN messages. If we go 60s without messages we raise an error*/
|
||||||
if (!CANstillAlive) {
|
if (!CANstillAlive) {
|
||||||
set_event(EVENT_CAN_RX_FAILURE, 0);
|
set_event(EVENT_CAN_RX_FAILURE, 0);
|
||||||
|
@ -549,7 +570,28 @@ void receive_can_battery(CAN_frame_t rx_frame) {
|
||||||
case 0x587: //BMS [5s] Services
|
case 0x587: //BMS [5s] Services
|
||||||
battery_ID2 = rx_frame.data.u8[0];
|
battery_ID2 = rx_frame.data.u8[0];
|
||||||
break;
|
break;
|
||||||
case 0x607: //BMS - No use for this message
|
case 0x607: //BMS - messages requested 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++];
|
||||||
|
}
|
||||||
|
|
||||||
|
system_cellvoltages_mV[0] = (message_data[0] << 8 | message_data[1]);
|
||||||
|
system_cellvoltages_mV[1] = (message_data[2] << 8 | message_data[3]);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -699,6 +741,9 @@ void send_can_battery() {
|
||||||
ESP32Can.CANWriteFrame(&BMW_3E4);
|
ESP32Can.CANWriteFrame(&BMW_3E4);
|
||||||
ESP32Can.CANWriteFrame(&BMW_37B);
|
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
|
BMW_3E5.data.u8[0] = 0xFD; // First 3E5 message byte0 we send is unique, once we sent initial value send this
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue