diff --git a/Software/src/battery/BYD-ATTO-3-BATTERY.cpp b/Software/src/battery/BYD-ATTO-3-BATTERY.cpp index 24d0125e..799aa511 100644 --- a/Software/src/battery/BYD-ATTO-3-BATTERY.cpp +++ b/Software/src/battery/BYD-ATTO-3-BATTERY.cpp @@ -21,17 +21,17 @@ After battery has been unlocked, you can remove the "USE_ESTIMATED_SOC" from the #define UNKNOWN_POLL_0 0x1FFE //0x64 19 C4 3B #define UNKNOWN_POLL_1 0x1FFC //0x72 1F C4 3B #define POLL_MAX_CHARGE_POWER 0x000A -#define UNKNOWN_POLL_3 0x000B //0x00B1 (177 interesting!) -#define UNKNOWN_POLL_4 0x000E //0x0B27 (2855 interesting!) +#define POLL_CHARGE_TIMES 0x000B // Using Carscanner name for now. Likely a counter for BMS 100% SOC calibration +#define POLL_MAX_DISCHARGE_POWER 0x000E #define POLL_TOTAL_CHARGED_AH 0x000F #define POLL_TOTAL_DISCHARGED_AH 0x0010 #define POLL_TOTAL_CHARGED_KWH 0x0011 #define POLL_TOTAL_DISCHARGED_KWH 0x0012 -#define UNKNOWN_POLL_9 0x0004 //0x0034 (52 interesting!) -#define UNKNOWN_POLL_10 0x002A //0x5B -#define UNKNOWN_POLL_11 0x002E //0x08 (probably module number, or cell number?) -#define UNKNOWN_POLL_12 0x002C //0x43 -#define UNKNOWN_POLL_13 0x0030 //0x01 (probably module number, or cell number?) +#define POLL_TIMES_FULL_POWER 0x0004 // Using Carscanner name for now. Unknown what it means for the moment +#define UNKNOWN_POLL_10 0x002A //0x5B +#define UNKNOWN_POLL_11 0x002E //0x08 (probably module number, or cell number?) +#define UNKNOWN_POLL_12 0x002C //0x43 +#define UNKNOWN_POLL_13 0x0030 //0x01 (probably module number, or cell number?) #define POLL_MODULE_1_LOWEST_MV_NUMBER 0x016C #define POLL_MODULE_1_LOWEST_CELL_MV 0x016D #define POLL_MODULE_1_HIGHEST_MV_NUMBER 0x016E @@ -176,16 +176,16 @@ void BydAttoBattery:: // If using estimated SOC, ramp down max discharge power as SOC decreases. rampdown_power = RAMPDOWN_POWER_ALLOWED * ((battery_estimated_SOC * 0.1) / RAMPDOWN_SOC); - if (rampdown_power < MAXPOWER_DISCHARGE_W) { // Never allow more than MAXPOWER_DISCHARGE_W + if (rampdown_power < BMS_allowed_discharge_power * 100) { // Never allow more than BMS_allowed_discharge_power datalayer_battery->status.max_discharge_power_W = rampdown_power; } else { - datalayer_battery->status.max_discharge_power_W = MAXPOWER_DISCHARGE_W; //TODO: Map from CAN later on + datalayer_battery->status.max_discharge_power_W = BMS_allowed_discharge_power * 100; } } else { - datalayer_battery->status.max_discharge_power_W = MAXPOWER_DISCHARGE_W; //TODO: Map from CAN later on + datalayer_battery->status.max_discharge_power_W = BMS_allowed_discharge_power * 100; } - datalayer_battery->status.max_charge_power_W = BMS_allowed_charge_power * 10; //TODO: Scaling unknown, *10 best guess + datalayer_battery->status.max_charge_power_W = BMS_allowed_charge_power * 100; datalayer_battery->status.cell_max_voltage_mV = BMS_highest_cell_voltage_mV; @@ -288,13 +288,13 @@ void BydAttoBattery:: datalayer_bydatto->unknown0 = BMS_unknown0; datalayer_bydatto->unknown1 = BMS_unknown1; datalayer_bydatto->chargePower = BMS_allowed_charge_power; - datalayer_bydatto->unknown3 = BMS_unknown3; - datalayer_bydatto->unknown4 = BMS_unknown4; + datalayer_bydatto->charge_times = BMS_charge_times; + datalayer_bydatto->dischargePower = BMS_allowed_discharge_power; datalayer_bydatto->total_charged_ah = BMS_total_charged_ah; datalayer_bydatto->total_discharged_ah = BMS_total_discharged_ah; datalayer_bydatto->total_charged_kwh = BMS_total_charged_kwh; datalayer_bydatto->total_discharged_kwh = BMS_total_discharged_kwh; - datalayer_bydatto->unknown9 = BMS_unknown9; + datalayer_bydatto->times_full_power = BMS_times_full_power; datalayer_bydatto->unknown10 = BMS_unknown10; datalayer_bydatto->unknown11 = BMS_unknown11; datalayer_bydatto->unknown12 = BMS_unknown12; @@ -450,11 +450,11 @@ void BydAttoBattery::handle_incoming_can_frame(CAN_frame rx_frame) { case POLL_MAX_CHARGE_POWER: BMS_allowed_charge_power = (rx_frame.data.u8[5] << 8) | rx_frame.data.u8[4]; break; - case UNKNOWN_POLL_3: - BMS_unknown3 = (rx_frame.data.u8[5] << 8) | rx_frame.data.u8[4]; + case POLL_CHARGE_TIMES: + BMS_charge_times = (rx_frame.data.u8[5] << 8) | rx_frame.data.u8[4]; break; - case UNKNOWN_POLL_4: - BMS_unknown4 = (rx_frame.data.u8[5] << 8) | rx_frame.data.u8[4]; + case POLL_MAX_DISCHARGE_POWER: + BMS_allowed_discharge_power = (rx_frame.data.u8[5] << 8) | rx_frame.data.u8[4]; break; case POLL_TOTAL_CHARGED_AH: BMS_total_charged_ah = (rx_frame.data.u8[5] << 8) | rx_frame.data.u8[4]; @@ -468,8 +468,8 @@ void BydAttoBattery::handle_incoming_can_frame(CAN_frame rx_frame) { case POLL_TOTAL_DISCHARGED_KWH: BMS_total_discharged_kwh = (rx_frame.data.u8[5] << 8) | rx_frame.data.u8[4]; break; - case UNKNOWN_POLL_9: - BMS_unknown9 = (rx_frame.data.u8[5] << 8) | rx_frame.data.u8[4]; + case POLL_TIMES_FULL_POWER: + BMS_times_full_power = (rx_frame.data.u8[5] << 8) | rx_frame.data.u8[4]; break; case UNKNOWN_POLL_10: BMS_unknown10 = rx_frame.data.u8[4]; @@ -626,16 +626,16 @@ void BydAttoBattery::transmit_can(unsigned long currentMillis) { case POLL_MAX_CHARGE_POWER: ATTO_3_7E7_POLL.data.u8[2] = (uint8_t)((POLL_MAX_CHARGE_POWER & 0xFF00) >> 8); ATTO_3_7E7_POLL.data.u8[3] = (uint8_t)(POLL_MAX_CHARGE_POWER & 0x00FF); - poll_state = UNKNOWN_POLL_3; + poll_state = POLL_CHARGE_TIMES; break; - case UNKNOWN_POLL_3: - ATTO_3_7E7_POLL.data.u8[2] = (uint8_t)((UNKNOWN_POLL_3 & 0xFF00) >> 8); - ATTO_3_7E7_POLL.data.u8[3] = (uint8_t)(UNKNOWN_POLL_3 & 0x00FF); - poll_state = UNKNOWN_POLL_4; + case POLL_CHARGE_TIMES: + ATTO_3_7E7_POLL.data.u8[2] = (uint8_t)((POLL_CHARGE_TIMES & 0xFF00) >> 8); + ATTO_3_7E7_POLL.data.u8[3] = (uint8_t)(POLL_CHARGE_TIMES & 0x00FF); + poll_state = POLL_MAX_DISCHARGE_POWER; break; - case UNKNOWN_POLL_4: - ATTO_3_7E7_POLL.data.u8[2] = (uint8_t)((UNKNOWN_POLL_4 & 0xFF00) >> 8); - ATTO_3_7E7_POLL.data.u8[3] = (uint8_t)(UNKNOWN_POLL_4 & 0x00FF); + case POLL_MAX_DISCHARGE_POWER: + ATTO_3_7E7_POLL.data.u8[2] = (uint8_t)((POLL_MAX_DISCHARGE_POWER & 0xFF00) >> 8); + ATTO_3_7E7_POLL.data.u8[3] = (uint8_t)(POLL_MAX_DISCHARGE_POWER & 0x00FF); poll_state = POLL_TOTAL_CHARGED_AH; break; case POLL_TOTAL_CHARGED_AH: @@ -656,11 +656,11 @@ void BydAttoBattery::transmit_can(unsigned long currentMillis) { case POLL_TOTAL_DISCHARGED_KWH: ATTO_3_7E7_POLL.data.u8[2] = (uint8_t)((POLL_TOTAL_DISCHARGED_KWH & 0xFF00) >> 8); ATTO_3_7E7_POLL.data.u8[3] = (uint8_t)(POLL_TOTAL_DISCHARGED_KWH & 0x00FF); - poll_state = UNKNOWN_POLL_9; + poll_state = POLL_TIMES_FULL_POWER; break; - case UNKNOWN_POLL_9: - ATTO_3_7E7_POLL.data.u8[2] = (uint8_t)((UNKNOWN_POLL_9 & 0xFF00) >> 8); - ATTO_3_7E7_POLL.data.u8[3] = (uint8_t)(UNKNOWN_POLL_9 & 0x00FF); + case POLL_TIMES_FULL_POWER: + ATTO_3_7E7_POLL.data.u8[2] = (uint8_t)((POLL_TIMES_FULL_POWER & 0xFF00) >> 8); + ATTO_3_7E7_POLL.data.u8[3] = (uint8_t)(POLL_TIMES_FULL_POWER & 0x00FF); poll_state = UNKNOWN_POLL_10; break; case UNKNOWN_POLL_10: diff --git a/Software/src/battery/BYD-ATTO-3-BATTERY.h b/Software/src/battery/BYD-ATTO-3-BATTERY.h index bd2806bb..9a75707b 100644 --- a/Software/src/battery/BYD-ATTO-3-BATTERY.h +++ b/Software/src/battery/BYD-ATTO-3-BATTERY.h @@ -10,8 +10,6 @@ #define USE_ESTIMATED_SOC // If enabled, SOC is estimated from pack voltage. Useful for locked packs. \ // Comment out this only if you know your BMS is unlocked and able to send SOC% -#define MAXPOWER_CHARGE_W 10000 -#define MAXPOWER_DISCHARGE_W 10000 //Uncomment and configure this line, if you want to filter out a broken temperature sensor (1-10) //Make sure you understand risks associated with disabling. Values can be read via "More Battery info" @@ -121,13 +119,13 @@ class BydAttoBattery : public CanBattery { uint32_t BMS_unknown0 = 0; uint32_t BMS_unknown1 = 0; uint16_t BMS_allowed_charge_power = 0; - uint16_t BMS_unknown3 = 0; - uint16_t BMS_unknown4 = 0; + uint16_t BMS_charge_times = 0; + uint16_t BMS_allowed_discharge_power = 0; uint16_t BMS_total_charged_ah = 0; uint16_t BMS_total_discharged_ah = 0; uint16_t BMS_total_charged_kwh = 0; uint16_t BMS_total_discharged_kwh = 0; - uint16_t BMS_unknown9 = 0; + uint16_t BMS_times_full_power = 0; uint8_t BMS_unknown10 = 0; uint8_t BMS_unknown11 = 0; uint8_t BMS_unknown12 = 0; diff --git a/Software/src/battery/BYD-ATTO-3-HTML.h b/Software/src/battery/BYD-ATTO-3-HTML.h index 2a344522..ca021882 100644 --- a/Software/src/battery/BYD-ATTO-3-HTML.h +++ b/Software/src/battery/BYD-ATTO-3-HTML.h @@ -12,33 +12,38 @@ class BydAtto3HtmlRenderer : public BatteryHtmlRenderer { String get_status_html() { String content; + float soc_estimated = static_cast(byd_datalayer->SOC_estimated) * 0.01; + float soc_measured = static_cast(byd_datalayer->SOC_highprec) * 0.1; + float BMS_maxChargePower = static_cast(byd_datalayer->chargePower) * 0.1; + float BMS_maxDischargePower = static_cast(byd_datalayer->dischargePower) * 0.1; static const char* SOCmethod[2] = {"Estimated from voltage", "Measured by BMS"}; + content += "

SOC method used: " + String(SOCmethod[byd_datalayer->SOC_method]) + "

"; - content += "

SOC estimated: " + String(byd_datalayer->SOC_estimated) + "

"; - content += "

SOC highprec: " + String(byd_datalayer->SOC_highprec) + "

"; - content += "

SOC OBD2: " + String(byd_datalayer->SOC_polled) + "

"; - content += "

Voltage periodic: " + String(byd_datalayer->voltage_periodic) + "

"; - content += "

Voltage OBD2: " + String(byd_datalayer->voltage_polled) + "

"; - content += "

Temperature sensor 1: " + String(byd_datalayer->battery_temperatures[0]) + "

"; - content += "

Temperature sensor 2: " + String(byd_datalayer->battery_temperatures[1]) + "

"; - content += "

Temperature sensor 3: " + String(byd_datalayer->battery_temperatures[2]) + "

"; - content += "

Temperature sensor 4: " + String(byd_datalayer->battery_temperatures[3]) + "

"; - content += "

Temperature sensor 5: " + String(byd_datalayer->battery_temperatures[4]) + "

"; - content += "

Temperature sensor 6: " + String(byd_datalayer->battery_temperatures[5]) + "

"; - content += "

Temperature sensor 7: " + String(byd_datalayer->battery_temperatures[6]) + "

"; - content += "

Temperature sensor 8: " + String(byd_datalayer->battery_temperatures[7]) + "

"; - content += "

Temperature sensor 9: " + String(byd_datalayer->battery_temperatures[8]) + "

"; - content += "

Temperature sensor 10: " + String(byd_datalayer->battery_temperatures[9]) + "

"; + content += "

SOC estimated: " + String(soc_estimated) + "%

"; + content += "

SOC measured: " + String(soc_measured) + "%

"; + content += "

SOC OBD2: " + String(byd_datalayer->SOC_polled) + "%

"; + content += "

Voltage periodic: " + String(byd_datalayer->voltage_periodic) + " V

"; + content += "

Voltage OBD2: " + String(byd_datalayer->voltage_polled) + " V

"; + content += "

Temperature sensor 1: " + String(byd_datalayer->battery_temperatures[0]) + " °C

"; + content += "

Temperature sensor 2: " + String(byd_datalayer->battery_temperatures[1]) + " °C

"; + content += "

Temperature sensor 3: " + String(byd_datalayer->battery_temperatures[2]) + " °C

"; + content += "

Temperature sensor 4: " + String(byd_datalayer->battery_temperatures[3]) + " °C

"; + content += "

Temperature sensor 5: " + String(byd_datalayer->battery_temperatures[4]) + " °C

"; + content += "

Temperature sensor 6: " + String(byd_datalayer->battery_temperatures[5]) + " °C

"; + content += "

Temperature sensor 7: " + String(byd_datalayer->battery_temperatures[6]) + " °C

"; + content += "

Temperature sensor 8: " + String(byd_datalayer->battery_temperatures[7]) + " °C

"; + content += "

Temperature sensor 9: " + String(byd_datalayer->battery_temperatures[8]) + " °C

"; + content += "

Temperature sensor 10: " + String(byd_datalayer->battery_temperatures[9]) + " °C

"; + content += "

Max discharge power: " + String(BMS_maxDischargePower) + " kW

"; + content += "

Max charge (regen) power: " + String(BMS_maxChargePower) + " kW

"; + content += "

Total charged: " + String(byd_datalayer->total_charged_kwh) + " kWh

"; + content += "

Total discharged: " + String(byd_datalayer->total_discharged_kwh) + " kWh

"; + content += "

Total charged: " + String(byd_datalayer->total_charged_ah) + " Ah

"; + content += "

Total discharged: " + String(byd_datalayer->total_discharged_ah) + " Ah

"; + content += "

Charge times: " + String(byd_datalayer->charge_times) + "

"; + content += "

Times of full power: " + String(byd_datalayer->times_full_power) + "

"; content += "

Unknown0: " + String(byd_datalayer->unknown0) + "

"; content += "

Unknown1: " + String(byd_datalayer->unknown1) + "

"; - content += "

Charge power raw: " + String(byd_datalayer->chargePower) + "

"; - content += "

Unknown3: " + String(byd_datalayer->unknown3) + "

"; - content += "

Unknown4: " + String(byd_datalayer->unknown4) + "

"; - content += "

Total charged Ah: " + String(byd_datalayer->total_charged_ah) + "

"; - content += "

Total discharged Ah: " + String(byd_datalayer->total_discharged_ah) + "

"; - content += "

Total charged kWh: " + String(byd_datalayer->total_charged_kwh) + "

"; - content += "

Total discharged kWh: " + String(byd_datalayer->total_discharged_kwh) + "

"; - content += "

Unknown9: " + String(byd_datalayer->unknown9) + "

"; content += "

Unknown10: " + String(byd_datalayer->unknown10) + "

"; content += "

Unknown11: " + String(byd_datalayer->unknown11) + "

"; content += "

Unknown12: " + String(byd_datalayer->unknown12) + "

"; diff --git a/Software/src/datalayer/datalayer_extended.h b/Software/src/datalayer/datalayer_extended.h index a758d400..06e0d459 100644 --- a/Software/src/datalayer/datalayer_extended.h +++ b/Software/src/datalayer/datalayer_extended.h @@ -125,13 +125,13 @@ typedef struct { uint32_t unknown0 = 0; uint32_t unknown1 = 0; uint16_t chargePower = 0; - uint16_t unknown3 = 0; - uint16_t unknown4 = 0; + uint16_t charge_times = 0; + uint16_t dischargePower = 0; uint16_t total_charged_ah = 0; uint16_t total_discharged_ah = 0; uint16_t total_charged_kwh = 0; uint16_t total_discharged_kwh = 0; - uint16_t unknown9 = 0; + uint16_t times_full_power = 0; uint8_t unknown10 = 0; uint8_t unknown11 = 0; uint8_t unknown12 = 0;