mirror of
https://github.com/dalathegreat/Battery-Emulator.git
synced 2025-10-03 01:39:30 +02:00
Compare commits
3 commits
ff71cadcb2
...
f5e71945df
Author | SHA1 | Date | |
---|---|---|---|
![]() |
f5e71945df | ||
![]() |
437f05525a | ||
![]() |
380497ad04 |
2 changed files with 78 additions and 29 deletions
|
@ -21,16 +21,12 @@ void FordMachEBattery::update_values() {
|
|||
|
||||
datalayer.battery.status.max_charge_power_W;
|
||||
|
||||
datalayer.battery.status.cell_max_voltage_mV;
|
||||
|
||||
datalayer.battery.status.cell_min_voltage_mV;
|
||||
|
||||
maximum_cellvoltage_mV = datalayer.battery.status.cell_voltages_mV[0];
|
||||
minimum_cellvoltage_mV = datalayer.battery.status.cell_voltages_mV[0];
|
||||
|
||||
// Loop through the array to find min and max cellvoltages, ignoring 0 values
|
||||
for (uint8_t i = 0; i < MAX_AMOUNT_CELLS; i++) {
|
||||
if (datalayer.battery.status.cell_voltages_mV[i] != 0) { // Ignore unavailable values
|
||||
if (datalayer.battery.status.cell_voltages_mV[i] > 1000) { // Ignore unavailable values
|
||||
if (datalayer.battery.status.cell_voltages_mV[i] < minimum_cellvoltage_mV) {
|
||||
minimum_cellvoltage_mV = datalayer.battery.status.cell_voltages_mV[i];
|
||||
}
|
||||
|
@ -40,6 +36,10 @@ void FordMachEBattery::update_values() {
|
|||
}
|
||||
}
|
||||
|
||||
datalayer.battery.status.cell_max_voltage_mV = maximum_cellvoltage_mV;
|
||||
|
||||
datalayer.battery.status.cell_min_voltage_mV = minimum_cellvoltage_mV;
|
||||
|
||||
// Initialize highest and lowest to the first element
|
||||
maximum_temperature = cell_temperature[0];
|
||||
minimum_temperature = cell_temperature[0];
|
||||
|
@ -119,28 +119,31 @@ void FordMachEBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
|||
case 0x4a2: {
|
||||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
|
||||
// Calculate starting cell index: (CAN_ID - 0x490) * 5 (Ends at 0x4A2)
|
||||
const uint8_t start_index = (rx_frame.ID - 0x490) * 5;
|
||||
|
||||
// Each CAN message contains 5 cellvoltages
|
||||
// Process 5 cells per message
|
||||
for (uint8_t i = 0; i < 5; i++) {
|
||||
const uint8_t byte_offset = i * 3;
|
||||
uint16_t voltage = 0;
|
||||
|
||||
if (i % 2 == 0) {
|
||||
// Even indices: bytes 0,1 | 3,4 | 6,7
|
||||
datalayer.battery.status.cell_voltages_mV[start_index + i] =
|
||||
(((rx_frame.data.u8[byte_offset] << 4) | (rx_frame.data.u8[byte_offset + 1] >> 4)) + 1000);
|
||||
} else {
|
||||
// Odd indices: bytes 1,2 | 4,5
|
||||
datalayer.battery.status.cell_voltages_mV[start_index + i] =
|
||||
((((rx_frame.data.u8[byte_offset] & 0x0F) << 8) | rx_frame.data.u8[byte_offset + 1]) + 1000);
|
||||
if (i == 0) {
|
||||
voltage = (rx_frame.data.u8[0] << 4) | (rx_frame.data.u8[1] >> 4);
|
||||
} else if (i == 1) {
|
||||
voltage = ((rx_frame.data.u8[1] & 0x0F) << 8) | rx_frame.data.u8[2];
|
||||
} else if (i == 2) {
|
||||
voltage = (rx_frame.data.u8[3] << 4) | (rx_frame.data.u8[4] >> 4);
|
||||
} else if (i == 3) {
|
||||
voltage = ((rx_frame.data.u8[4] & 0x0F) << 8) | rx_frame.data.u8[5];
|
||||
} else if (i == 4) {
|
||||
voltage = (rx_frame.data.u8[6] << 4) | (rx_frame.data.u8[7] >> 4);
|
||||
}
|
||||
|
||||
datalayer.battery.status.cell_voltages_mV[start_index + i] = voltage + 1000;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x4a3: //1s
|
||||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
datalayer.battery.status.cell_voltages_mV[95] = (rx_frame.data.u8[0] << 4) | (rx_frame.data.u8[1] >> 4);
|
||||
datalayer.battery.status.cell_voltages_mV[95] = ((rx_frame.data.u8[0] << 4) | (rx_frame.data.u8[1] >> 4)) + 1000;
|
||||
//Celltemperatures
|
||||
cell_temperature[0] = ((rx_frame.data.u8[2] - 40) / 2);
|
||||
cell_temperature[1] = ((rx_frame.data.u8[2] - 40) / 2);
|
||||
|
@ -171,8 +174,8 @@ void FordMachEBattery::transmit_can(unsigned long currentMillis) {
|
|||
if (currentMillis - previousMillis10 >= INTERVAL_10_MS) {
|
||||
previousMillis10 = currentMillis;
|
||||
|
||||
transmit_can_frame(&FORD_217);
|
||||
transmit_can_frame(&FORD_442);
|
||||
//transmit_can_frame(&FORD_217); Not needed for contactor closing
|
||||
//transmit_can_frame(&FORD_442); Not needed for contactor closing
|
||||
}
|
||||
|
||||
// Send 30ms CAN Message
|
||||
|
@ -203,19 +206,29 @@ void FordMachEBattery::transmit_can(unsigned long currentMillis) {
|
|||
|
||||
//TODO: handle FORD_4C properly very odd looping
|
||||
|
||||
transmit_can_frame(&FORD_77);
|
||||
transmit_can_frame(&FORD_7D);
|
||||
transmit_can_frame(&FORD_167);
|
||||
transmit_can_frame(&FORD_48F); //Only sent in AC charging logs!
|
||||
transmit_can_frame(&FORD_204);
|
||||
transmit_can_frame(&FORD_4B0);
|
||||
transmit_can_frame(&FORD_47);
|
||||
transmit_can_frame(&FORD_230);
|
||||
transmit_can_frame(&FORD_415);
|
||||
transmit_can_frame(&FORD_4C);
|
||||
counter_8_30ms = (counter_8_30ms + 1) % 8; // cycles 0-7 (8 values before wrap)
|
||||
|
||||
// Byte 6: counts up by 2 each step (0, 2, 4, 6, 8, 10, 12, 14)
|
||||
FORD_200.data.u8[6] = counter_8_30ms * 2;
|
||||
|
||||
// Byte 7: counts down by 2 each step, maintaining byte6 + byte7 = 0x7F
|
||||
FORD_200.data.u8[7] = 0x7F - (counter_8_30ms * 2);
|
||||
|
||||
//transmit_can_frame(&FORD_77); Not needed for contactor closing
|
||||
//transmit_can_frame(&FORD_7D); Not needed for contactor closing
|
||||
//transmit_can_frame(&FORD_167); Not needed for contactor closing
|
||||
//transmit_can_frame(&FORD_48F); //Only sent in AC charging logs! Not needed for contactor closing
|
||||
//transmit_can_frame(&FORD_204); Not needed for contactor closing
|
||||
//transmit_can_frame(&FORD_4B0); Not needed for contactor closing
|
||||
//transmit_can_frame(&FORD_47); Not needed for contactor closing
|
||||
//transmit_can_frame(&FORD_230); Not needed for contactor closing
|
||||
//transmit_can_frame(&FORD_415); Not needed for contactor closing
|
||||
//transmit_can_frame(&FORD_4C); Not needed for contactor closing
|
||||
transmit_can_frame(&FORD_7E);
|
||||
transmit_can_frame(&FORD_48);
|
||||
transmit_can_frame(&FORD_165);
|
||||
transmit_can_frame(&FORD_7F);
|
||||
transmit_can_frame(&FORD_200);
|
||||
}
|
||||
// Send 50ms CAN Message
|
||||
if (currentMillis - previousMillis50 >= INTERVAL_50_MS) {
|
||||
|
@ -240,6 +253,11 @@ void FordMachEBattery::transmit_can(unsigned long currentMillis) {
|
|||
&FORD_5A); //This message actually has checksum/counter, but it seems to close contactors without those
|
||||
transmit_can_frame(&FORD_166);
|
||||
transmit_can_frame(&FORD_175);
|
||||
transmit_can_frame(&FORD_178);
|
||||
transmit_can_frame(&FORD_203);
|
||||
transmit_can_frame(
|
||||
&FORD_176); //This message actually has checksum/counter, but it seems to close contactors without those
|
||||
transmit_can_frame(&FORD_185);
|
||||
}
|
||||
// Send 1s CAN Message
|
||||
if (currentMillis - previousMillis1000 >= INTERVAL_1_S) {
|
||||
|
|
|
@ -34,6 +34,7 @@ class FordMachEBattery : public CanBattery {
|
|||
uint16_t minimum_cellvoltage_mV = 3700;
|
||||
|
||||
uint8_t counter_30ms = 0;
|
||||
uint8_t counter_8_30ms = 0;
|
||||
|
||||
CAN_frame FORD_47 = {.FD = false,
|
||||
.ext_ID = false,
|
||||
|
@ -70,6 +71,11 @@ class FordMachEBattery : public CanBattery {
|
|||
.DLC = 8,
|
||||
.ID = 0x07E,
|
||||
.data = {0x00, 0x00, 0x3E, 0x80, 0x00, 0x04, 0x00, 0x00}};
|
||||
CAN_frame FORD_7F = {.FD = false,
|
||||
.ext_ID = false,
|
||||
.DLC = 8,
|
||||
.ID = 0x07F,
|
||||
.data = {0x00, 0x00, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00}};
|
||||
CAN_frame FORD_156 = {.FD = false,
|
||||
.ext_ID = false,
|
||||
.DLC = 8,
|
||||
|
@ -95,11 +101,36 @@ class FordMachEBattery : public CanBattery {
|
|||
.DLC = 8,
|
||||
.ID = 0x175,
|
||||
.data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
|
||||
CAN_frame FORD_176 = {.FD = false,
|
||||
.ext_ID = false,
|
||||
.DLC = 8,
|
||||
.ID = 0x176,
|
||||
.data = {0x00, 0x0E, 0xF0, 0x10, 0x00, 0x00, 0x00, 0x00}};
|
||||
CAN_frame FORD_178 = {.FD = false, //Static content
|
||||
.ext_ID = false,
|
||||
.DLC = 8,
|
||||
.ID = 0x175,
|
||||
.data = {0x01, 0xB6, 0x02, 0x00, 0x4E, 0x46, 0xC6, 0x17}};
|
||||
CAN_frame FORD_12F = {.FD = false,
|
||||
.ext_ID = false,
|
||||
.DLC = 8,
|
||||
.ID = 0x12F,
|
||||
.data = {0x0A, 0xF8, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}};
|
||||
CAN_frame FORD_185 = {.FD = false,
|
||||
.ext_ID = false,
|
||||
.DLC = 8,
|
||||
.ID = 0x185,
|
||||
.data = {0x03, 0x4E, 0x75, 0x32, 0x00, 0x00, 0x00, 0x00}};
|
||||
CAN_frame FORD_200 = {.FD = false,
|
||||
.ext_ID = false,
|
||||
.DLC = 8,
|
||||
.ID = 0x200,
|
||||
.data = {0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x70}};
|
||||
CAN_frame FORD_203 = {.FD = false,
|
||||
.ext_ID = false,
|
||||
.DLC = 8,
|
||||
.ID = 0x203,
|
||||
.data = {0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
|
||||
CAN_frame FORD_204 = {.FD = false,
|
||||
.ext_ID = false,
|
||||
.DLC = 8,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue