mirror of
https://github.com/dalathegreat/Battery-Emulator.git
synced 2025-10-05 10:49:42 +02:00
Add cellvoltage reading for BMW i3
This commit is contained in:
parent
36d06e85f2
commit
a7fd4099e1
1 changed files with 42 additions and 13 deletions
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue