mirror of
https://github.com/dalathegreat/Battery-Emulator.git
synced 2025-10-05 10:49:42 +02:00
Using max discharge power from BMS, correction of scaling and mapping unknown values
This commit is contained in:
parent
dbf2def0e2
commit
45c084614b
4 changed files with 66 additions and 63 deletions
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -12,33 +12,38 @@ class BydAtto3HtmlRenderer : public BatteryHtmlRenderer {
|
|||
String get_status_html() {
|
||||
String content;
|
||||
|
||||
float soc_estimated = static_cast<float>(byd_datalayer->SOC_estimated) * 0.01;
|
||||
float soc_measured = static_cast<float>(byd_datalayer->SOC_highprec) * 0.1;
|
||||
float BMS_maxChargePower = static_cast<float>(byd_datalayer->chargePower) * 0.1;
|
||||
float BMS_maxDischargePower = static_cast<float>(byd_datalayer->dischargePower) * 0.1;
|
||||
static const char* SOCmethod[2] = {"Estimated from voltage", "Measured by BMS"};
|
||||
|
||||
content += "<h4>SOC method used: " + String(SOCmethod[byd_datalayer->SOC_method]) + "</h4>";
|
||||
content += "<h4>SOC estimated: " + String(byd_datalayer->SOC_estimated) + "</h4>";
|
||||
content += "<h4>SOC highprec: " + String(byd_datalayer->SOC_highprec) + "</h4>";
|
||||
content += "<h4>SOC OBD2: " + String(byd_datalayer->SOC_polled) + "</h4>";
|
||||
content += "<h4>Voltage periodic: " + String(byd_datalayer->voltage_periodic) + "</h4>";
|
||||
content += "<h4>Voltage OBD2: " + String(byd_datalayer->voltage_polled) + "</h4>";
|
||||
content += "<h4>Temperature sensor 1: " + String(byd_datalayer->battery_temperatures[0]) + "</h4>";
|
||||
content += "<h4>Temperature sensor 2: " + String(byd_datalayer->battery_temperatures[1]) + "</h4>";
|
||||
content += "<h4>Temperature sensor 3: " + String(byd_datalayer->battery_temperatures[2]) + "</h4>";
|
||||
content += "<h4>Temperature sensor 4: " + String(byd_datalayer->battery_temperatures[3]) + "</h4>";
|
||||
content += "<h4>Temperature sensor 5: " + String(byd_datalayer->battery_temperatures[4]) + "</h4>";
|
||||
content += "<h4>Temperature sensor 6: " + String(byd_datalayer->battery_temperatures[5]) + "</h4>";
|
||||
content += "<h4>Temperature sensor 7: " + String(byd_datalayer->battery_temperatures[6]) + "</h4>";
|
||||
content += "<h4>Temperature sensor 8: " + String(byd_datalayer->battery_temperatures[7]) + "</h4>";
|
||||
content += "<h4>Temperature sensor 9: " + String(byd_datalayer->battery_temperatures[8]) + "</h4>";
|
||||
content += "<h4>Temperature sensor 10: " + String(byd_datalayer->battery_temperatures[9]) + "</h4>";
|
||||
content += "<h4>SOC estimated: " + String(soc_estimated) + "%</h4>";
|
||||
content += "<h4>SOC measured: " + String(soc_measured) + "%</h4>";
|
||||
content += "<h4>SOC OBD2: " + String(byd_datalayer->SOC_polled) + "%</h4>";
|
||||
content += "<h4>Voltage periodic: " + String(byd_datalayer->voltage_periodic) + " V</h4>";
|
||||
content += "<h4>Voltage OBD2: " + String(byd_datalayer->voltage_polled) + " V</h4>";
|
||||
content += "<h4>Temperature sensor 1: " + String(byd_datalayer->battery_temperatures[0]) + " °C</h4>";
|
||||
content += "<h4>Temperature sensor 2: " + String(byd_datalayer->battery_temperatures[1]) + " °C</h4>";
|
||||
content += "<h4>Temperature sensor 3: " + String(byd_datalayer->battery_temperatures[2]) + " °C</h4>";
|
||||
content += "<h4>Temperature sensor 4: " + String(byd_datalayer->battery_temperatures[3]) + " °C</h4>";
|
||||
content += "<h4>Temperature sensor 5: " + String(byd_datalayer->battery_temperatures[4]) + " °C</h4>";
|
||||
content += "<h4>Temperature sensor 6: " + String(byd_datalayer->battery_temperatures[5]) + " °C</h4>";
|
||||
content += "<h4>Temperature sensor 7: " + String(byd_datalayer->battery_temperatures[6]) + " °C</h4>";
|
||||
content += "<h4>Temperature sensor 8: " + String(byd_datalayer->battery_temperatures[7]) + " °C</h4>";
|
||||
content += "<h4>Temperature sensor 9: " + String(byd_datalayer->battery_temperatures[8]) + " °C</h4>";
|
||||
content += "<h4>Temperature sensor 10: " + String(byd_datalayer->battery_temperatures[9]) + " °C</h4>";
|
||||
content += "<h4>Max discharge power: " + String(BMS_maxDischargePower) + " kW</h4>";
|
||||
content += "<h4>Max charge (regen) power: " + String(BMS_maxChargePower) + " kW</h4>";
|
||||
content += "<h4>Total charged: " + String(byd_datalayer->total_charged_kwh) + " kWh</h4>";
|
||||
content += "<h4>Total discharged: " + String(byd_datalayer->total_discharged_kwh) + " kWh</h4>";
|
||||
content += "<h4>Total charged: " + String(byd_datalayer->total_charged_ah) + " Ah</h4>";
|
||||
content += "<h4>Total discharged: " + String(byd_datalayer->total_discharged_ah) + " Ah</h4>";
|
||||
content += "<h4>Charge times: " + String(byd_datalayer->charge_times) + "</h4>";
|
||||
content += "<h4>Times of full power: " + String(byd_datalayer->times_full_power) + "</h4>";
|
||||
content += "<h4>Unknown0: " + String(byd_datalayer->unknown0) + "</h4>";
|
||||
content += "<h4>Unknown1: " + String(byd_datalayer->unknown1) + "</h4>";
|
||||
content += "<h4>Charge power raw: " + String(byd_datalayer->chargePower) + "</h4>";
|
||||
content += "<h4>Unknown3: " + String(byd_datalayer->unknown3) + "</h4>";
|
||||
content += "<h4>Unknown4: " + String(byd_datalayer->unknown4) + "</h4>";
|
||||
content += "<h4>Total charged Ah: " + String(byd_datalayer->total_charged_ah) + "</h4>";
|
||||
content += "<h4>Total discharged Ah: " + String(byd_datalayer->total_discharged_ah) + "</h4>";
|
||||
content += "<h4>Total charged kWh: " + String(byd_datalayer->total_charged_kwh) + "</h4>";
|
||||
content += "<h4>Total discharged kWh: " + String(byd_datalayer->total_discharged_kwh) + "</h4>";
|
||||
content += "<h4>Unknown9: " + String(byd_datalayer->unknown9) + "</h4>";
|
||||
content += "<h4>Unknown10: " + String(byd_datalayer->unknown10) + "</h4>";
|
||||
content += "<h4>Unknown11: " + String(byd_datalayer->unknown11) + "</h4>";
|
||||
content += "<h4>Unknown12: " + String(byd_datalayer->unknown12) + "</h4>";
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue