mirror of
https://github.com/dalathegreat/Battery-Emulator.git
synced 2025-10-03 09:49:32 +02:00
Add initial support for 50/75kWh vans
This commit is contained in:
parent
805b3e10d2
commit
e38b6286c7
2 changed files with 130 additions and 30 deletions
|
@ -12,6 +12,7 @@ This integration is still ongoing. Here is what still needs to be done in order
|
||||||
/* Do not change code below unless you are sure what you are doing */
|
/* Do not change code below unless you are sure what you are doing */
|
||||||
void EcmpBattery::update_values() {
|
void EcmpBattery::update_values() {
|
||||||
|
|
||||||
|
if (!MysteryVan) { //Normal eCMP platform
|
||||||
datalayer.battery.status.real_soc = battery_soc * 10;
|
datalayer.battery.status.real_soc = battery_soc * 10;
|
||||||
|
|
||||||
datalayer.battery.status.soh_pptt;
|
datalayer.battery.status.soh_pptt;
|
||||||
|
@ -50,6 +51,47 @@ void EcmpBattery::update_values() {
|
||||||
|
|
||||||
datalayer.battery.status.cell_min_voltage_mV = min_cell_mv_value;
|
datalayer.battery.status.cell_min_voltage_mV = min_cell_mv_value;
|
||||||
datalayer.battery.status.cell_max_voltage_mV = max_cell_mv_value;
|
datalayer.battery.status.cell_max_voltage_mV = max_cell_mv_value;
|
||||||
|
} else { //Some variant of the 50/75kWh battery that is not using the eCMP CAN mappings.
|
||||||
|
// For these batteries we need to use the OBD2 PID polled values
|
||||||
|
datalayer.battery.status.real_soc = battery_soc * 10; //TTOD, calculate based on cap remaining?
|
||||||
|
|
||||||
|
datalayer.battery.status.soh_pptt;
|
||||||
|
|
||||||
|
if (pid_pack_voltage != NOT_SAMPLED_YET) {
|
||||||
|
datalayer.battery.status.voltage_dV = pid_pack_voltage;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pid_current != NOT_SAMPLED_YET) {
|
||||||
|
datalayer.battery.status.current_dA = (int16_t)(pid_current / 100);
|
||||||
|
|
||||||
|
datalayer.battery.status.active_power_W =
|
||||||
|
(uint16_t)((pid_current / 1000.0f) * (datalayer.battery.status.voltage_dV / 10.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pid_max_charge_10s != NOT_SAMPLED_YET) {
|
||||||
|
datalayer.battery.status.max_charge_power_W = pid_max_charge_10s;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pid_max_discharge_10s != NOT_SAMPLED_YET) {
|
||||||
|
datalayer.battery.status.max_discharge_power_W = pid_max_discharge_10s;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pid_lowest_temperature != NOT_SAMPLED_YET) {
|
||||||
|
datalayer.battery.status.temperature_min_dC = pid_lowest_temperature * 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pid_highest_temperature != NOT_SAMPLED_YET) {
|
||||||
|
datalayer.battery.status.temperature_max_dC = pid_highest_temperature * 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pid_high_cell_voltage != NOT_SAMPLED_YET) {
|
||||||
|
datalayer.battery.status.cell_max_voltage_mV = pid_high_cell_voltage;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pid_low_cell_voltage != NOT_SAMPLED_YET) {
|
||||||
|
datalayer.battery.status.cell_min_voltage_mV = pid_low_cell_voltage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Update extended datalayer (More Battery Info page)
|
// Update extended datalayer (More Battery Info page)
|
||||||
datalayer_extended.stellantisECMP.MainConnectorState = battery_MainConnectorState;
|
datalayer_extended.stellantisECMP.MainConnectorState = battery_MainConnectorState;
|
||||||
|
@ -145,9 +187,58 @@ void EcmpBattery::update_values() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void EcmpBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
void EcmpBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
||||||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
|
||||||
switch (rx_frame.ID) {
|
switch (rx_frame.ID) {
|
||||||
|
case 0x2D4: //MysteryVan 50/75kWh platform
|
||||||
|
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||||
|
MysteryVan = true;
|
||||||
|
break;
|
||||||
|
case 0x3B4: //MysteryVan 50/75kWh platform
|
||||||
|
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||||
|
break;
|
||||||
|
case 0x2F4: //MysteryVan 50/75kWh platform
|
||||||
|
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||||
|
break;
|
||||||
|
case 0x3F4: //MysteryVan 50/75kWh platform
|
||||||
|
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||||
|
break;
|
||||||
|
case 0x554: //MysteryVan 50/75kWh platform
|
||||||
|
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||||
|
break;
|
||||||
|
case 0x373: //MysteryVan 50/75kWh platform
|
||||||
|
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||||
|
break;
|
||||||
|
case 0x4F4: //MysteryVan 50/75kWh platform
|
||||||
|
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||||
|
break;
|
||||||
|
case 0x414: //MysteryVan 50/75kWh platform
|
||||||
|
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||||
|
break;
|
||||||
|
case 0x353: //MysteryVan 50/75kWh platform
|
||||||
|
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||||
|
break;
|
||||||
|
case 0x474: //MysteryVan 50/75kWh platform
|
||||||
|
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||||
|
break;
|
||||||
|
case 0x574: //MysteryVan 50/75kWh platform
|
||||||
|
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||||
|
break;
|
||||||
|
case 0x583: //MysteryVan 50/75kWh platform
|
||||||
|
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||||
|
break;
|
||||||
|
case 0x314: //MysteryVan 50/75kWh platform
|
||||||
|
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||||
|
break;
|
||||||
|
case 0x254: //MysteryVan 50/75kWh platform
|
||||||
|
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||||
|
break;
|
||||||
|
case 0x2B4: //MysteryVan 50/75kWh platform
|
||||||
|
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||||
|
break;
|
||||||
|
case 0x4D4: //MysteryVan 50/75kWh platform
|
||||||
|
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||||
|
break;
|
||||||
case 0x125: //Common
|
case 0x125: //Common
|
||||||
|
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||||
battery_soc = (rx_frame.data.u8[0] << 2) |
|
battery_soc = (rx_frame.data.u8[0] << 2) |
|
||||||
(rx_frame.data.u8[1] >> 6); // Byte1, bit 7 length 10 (0x3FE when abnormal) (0-1000 ppt)
|
(rx_frame.data.u8[1] >> 6); // Byte1, bit 7 length 10 (0x3FE when abnormal) (0-1000 ppt)
|
||||||
battery_MainConnectorState = ((rx_frame.data.u8[2] & 0x18) >>
|
battery_MainConnectorState = ((rx_frame.data.u8[2] & 0x18) >>
|
||||||
|
@ -157,6 +248,7 @@ void EcmpBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
||||||
battery_current = (((rx_frame.data.u8[4] & 0x0F) << 8) | rx_frame.data.u8[5]) - 600; // TODO: Test
|
battery_current = (((rx_frame.data.u8[4] & 0x0F) << 8) | rx_frame.data.u8[5]) - 600; // TODO: Test
|
||||||
break;
|
break;
|
||||||
case 0x127: //DFM specific
|
case 0x127: //DFM specific
|
||||||
|
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||||
battery_AllowedMaxChargeCurrent =
|
battery_AllowedMaxChargeCurrent =
|
||||||
(rx_frame.data.u8[0] << 2) |
|
(rx_frame.data.u8[0] << 2) |
|
||||||
((rx_frame.data.u8[1] & 0xC0) >> 6); //Byte 1, bit 7, length 10 (0-600A) [0x3FF if invalid]
|
((rx_frame.data.u8[1] & 0xC0) >> 6); //Byte 1, bit 7, length 10 (0-600A) [0x3FF if invalid]
|
||||||
|
@ -165,12 +257,15 @@ void EcmpBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
||||||
(rx_frame.data.u8[3] >> 4); //Byte 2, bit 5, length 10 (0-600A) [0x3FF if invalid]
|
(rx_frame.data.u8[3] >> 4); //Byte 2, bit 5, length 10 (0-600A) [0x3FF if invalid]
|
||||||
break;
|
break;
|
||||||
case 0x129: //PSA specific
|
case 0x129: //PSA specific
|
||||||
|
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||||
break;
|
break;
|
||||||
case 0x31B:
|
case 0x31B:
|
||||||
|
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||||
battery_InterlockOpen = ((rx_frame.data.u8[1] & 0x10) >> 4); //Best guess, seems to work?
|
battery_InterlockOpen = ((rx_frame.data.u8[1] & 0x10) >> 4); //Best guess, seems to work?
|
||||||
//TODO: frame7 contains checksum, we can use this to check for CAN message corruption
|
//TODO: frame7 contains checksum, we can use this to check for CAN message corruption
|
||||||
break;
|
break;
|
||||||
case 0x358: //Common
|
case 0x358: //Common
|
||||||
|
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||||
battery_highestTemperature = rx_frame.data.u8[6] - 40;
|
battery_highestTemperature = rx_frame.data.u8[6] - 40;
|
||||||
battery_lowestTemperature = rx_frame.data.u8[7] - 40;
|
battery_lowestTemperature = rx_frame.data.u8[7] - 40;
|
||||||
break;
|
break;
|
||||||
|
@ -185,11 +280,13 @@ void EcmpBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
||||||
case 0x494:
|
case 0x494:
|
||||||
break;
|
break;
|
||||||
case 0x594:
|
case 0x594:
|
||||||
|
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||||
battery_insulation_failure_diag = ((rx_frame.data.u8[6] & 0xE0) >> 5); //Unsure if this is right position
|
battery_insulation_failure_diag = ((rx_frame.data.u8[6] & 0xE0) >> 5); //Unsure if this is right position
|
||||||
//byte pos 6, bit pos 7, signal lenth 3
|
//byte pos 6, bit pos 7, signal lenth 3
|
||||||
//0 = no failure, 1 = symmetric failure, 4 = invalid value , forbidden value 5-7
|
//0 = no failure, 1 = symmetric failure, 4 = invalid value , forbidden value 5-7
|
||||||
break;
|
break;
|
||||||
case 0x6D0: //Common
|
case 0x6D0: //Common
|
||||||
|
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||||
battery_insulationResistanceKOhm =
|
battery_insulationResistanceKOhm =
|
||||||
(rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3]; //Byte 2, bit 7, length 16 (0-60000 kOhm)
|
(rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3]; //Byte 2, bit 7, length 16 (0-60000 kOhm)
|
||||||
break;
|
break;
|
||||||
|
@ -198,6 +295,7 @@ void EcmpBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
||||||
case 0x6D2:
|
case 0x6D2:
|
||||||
break;
|
break;
|
||||||
case 0x6D3:
|
case 0x6D3:
|
||||||
|
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||||
cellvoltages[0] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1];
|
cellvoltages[0] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1];
|
||||||
cellvoltages[1] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3];
|
cellvoltages[1] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3];
|
||||||
cellvoltages[2] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
|
cellvoltages[2] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
|
||||||
|
@ -374,6 +472,7 @@ void EcmpBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
||||||
memcpy(datalayer.battery.status.cell_voltages_mV, cellvoltages, 108 * sizeof(uint16_t));
|
memcpy(datalayer.battery.status.cell_voltages_mV, cellvoltages, 108 * sizeof(uint16_t));
|
||||||
break;
|
break;
|
||||||
case 0x694: // Poll reply
|
case 0x694: // Poll reply
|
||||||
|
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||||
|
|
||||||
// Handle user requested functionality first if ongoing
|
// Handle user requested functionality first if ongoing
|
||||||
if (datalayer_extended.stellantisECMP.UserRequestDisableIsoMonitoring) {
|
if (datalayer_extended.stellantisECMP.UserRequestDisableIsoMonitoring) {
|
||||||
|
|
|
@ -38,6 +38,7 @@ class EcmpBattery : public CanBattery {
|
||||||
static const int COMPLETED_STATE = 0;
|
static const int COMPLETED_STATE = 0;
|
||||||
bool battery_RelayOpenRequest = false;
|
bool battery_RelayOpenRequest = false;
|
||||||
bool battery_InterlockOpen = false;
|
bool battery_InterlockOpen = false;
|
||||||
|
bool MysteryVan = false;
|
||||||
uint8_t ContactorResetStatemachine = 0;
|
uint8_t ContactorResetStatemachine = 0;
|
||||||
uint8_t CollisionResetStatemachine = 0;
|
uint8_t CollisionResetStatemachine = 0;
|
||||||
uint8_t IsolationResetStatemachine = 0;
|
uint8_t IsolationResetStatemachine = 0;
|
||||||
|
@ -80,8 +81,8 @@ class EcmpBattery : public CanBattery {
|
||||||
uint8_t pid_coldest_module = NOT_SAMPLED_YET;
|
uint8_t pid_coldest_module = NOT_SAMPLED_YET;
|
||||||
uint8_t pid_lowest_temperature = NOT_SAMPLED_YET;
|
uint8_t pid_lowest_temperature = NOT_SAMPLED_YET;
|
||||||
uint8_t pid_average_temperature = NOT_SAMPLED_YET;
|
uint8_t pid_average_temperature = NOT_SAMPLED_YET;
|
||||||
uint8_t pid_highest_temperature = NOT_SAMPLED_YET;
|
int8_t pid_highest_temperature = NOT_SAMPLED_YET;
|
||||||
uint8_t pid_hottest_module = NOT_SAMPLED_YET;
|
int8_t pid_hottest_module = NOT_SAMPLED_YET;
|
||||||
uint16_t pid_avg_cell_voltage = NOT_SAMPLED_YET;
|
uint16_t pid_avg_cell_voltage = NOT_SAMPLED_YET;
|
||||||
int32_t pid_current = NOT_SAMPLED_YET;
|
int32_t pid_current = NOT_SAMPLED_YET;
|
||||||
uint32_t pid_insulation_res_neg = NOT_SAMPLED_YET;
|
uint32_t pid_insulation_res_neg = NOT_SAMPLED_YET;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue