Add (dis)charged_energy_Wh to datalayer and mqtt. (#1003)

- Add (dis)charged_energy_Wh to datalayer and mqtt.
- MEB: report (dis)charged_energy_Wh
- MEB: Fix SOH calculation.
- TESLA: also use the total_(dis)charged_battery_Wh in generic datalayer.
This commit is contained in:
Marijn van Galen 2025-03-25 19:18:20 +01:00 committed by GitHub
parent 02d2e518ba
commit 07a4ad7abc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 47 additions and 11 deletions

View file

@ -185,6 +185,8 @@ static uint8_t seconds = 0;
static uint32_t first_can_msg = 0;
static uint32_t last_can_msg_timestamp = 0;
static bool hv_requested = false;
static int32_t kwh_charge = 0;
static int32_t kwh_discharge = 0;
#define TIME_YEAR 2024
#define TIME_MONTH 8
@ -559,7 +561,7 @@ void update_values_battery() { //This function maps all the values fetched via
else if (datalayer.battery.info.number_of_cells <= 96)
Wh_max = 82442 * 0.9025;
if (BMS_capacity_ah > 0)
datalayer.battery.status.soh_pptt = 10000 * datalayer.battery.info.total_capacity_Wh / Wh_max;
datalayer.battery.status.soh_pptt = 10000 * datalayer.battery.info.total_capacity_Wh / (Wh_max * 1.02564);
}
datalayer.battery.status.remaining_capacity_Wh = usable_energy_amount_Wh * 5;
@ -1169,6 +1171,18 @@ void handle_incoming_can_frame_battery(CAN_frame rx_frame) {
case PID_MIN_DISCHARGE_VOLTAGE:
battery_min_discharge_voltage = ((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]);
break;
case PID_ENERGY_COUNTERS:
// int32_t ah_discharge = ((rx_frame.data.u8[5] << 24) | (rx_frame.data.u8[6] << 16) | (rx_frame.data.u8[7] << 8) |rx_frame.data.u8[8]);
// int32_t ah_charge = ((rx_frame.data.u8[9] << 24) | (rx_frame.data.u8[10] << 16) | (rx_frame.data.u8[11] << 8) |rx_frame.data.u8[12]);
kwh_charge = ((rx_frame.data.u8[13] << 24) | (rx_frame.data.u8[14] << 16) | (rx_frame.data.u8[15] << 8) |
rx_frame.data.u8[16]);
kwh_discharge = ((rx_frame.data.u8[17] << 24) | (rx_frame.data.u8[18] << 16) | (rx_frame.data.u8[19] << 8) |
rx_frame.data.u8[20]);
// logging.printf("ah_dis:%.3f ah_ch:%.3f kwh_dis:%.3f kwh_ch:%.3f\n", ah_discharge*0.00182044545, ah_charge*0.00182044545,
// kwh_discharge*0.00011650853, kwh_charge*0.00011650853);
datalayer.battery.status.total_discharged_battery_Wh = kwh_discharge * 0.11650853;
datalayer.battery.status.total_charged_battery_Wh = kwh_charge * 0.11650853;
break;
case PID_ALLOWED_CHARGE_POWER:
battery_allowed_charge_power = ((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]);
break;
@ -1854,6 +1868,11 @@ void transmit_can_battery() {
case PID_MIN_DISCHARGE_VOLTAGE:
MEB_POLLING_FRAME.data.u8[2] = (uint8_t)(PID_MIN_DISCHARGE_VOLTAGE >> 8);
MEB_POLLING_FRAME.data.u8[3] = (uint8_t)PID_MIN_DISCHARGE_VOLTAGE;
poll_pid = PID_ENERGY_COUNTERS;
break;
case PID_ENERGY_COUNTERS:
MEB_POLLING_FRAME.data.u8[2] = (uint8_t)(PID_ENERGY_COUNTERS >> 8);
MEB_POLLING_FRAME.data.u8[3] = (uint8_t)PID_ENERGY_COUNTERS;
poll_pid = PID_ALLOWED_CHARGE_POWER;
break;
case PID_ALLOWED_CHARGE_POWER:

View file

@ -21,6 +21,7 @@
#define PID_MIN_TEMP 0x1E0F
#define PID_MAX_CHARGE_VOLTAGE 0x5171
#define PID_MIN_DISCHARGE_VOLTAGE 0x5170
#define PID_ENERGY_COUNTERS 0x1E32
#define PID_ALLOWED_CHARGE_POWER 0x1E1B
#define PID_ALLOWED_DISCHARGE_POWER 0x1E1C
#define PID_CELLVOLTAGE_CELL_1 0x1E40

View file

@ -907,8 +907,8 @@ void update_values_battery() { //This function maps all the values fetched via
datalayer_extended.tesla.battery_full_charge_complete = battery_full_charge_complete;
datalayer_extended.tesla.battery_fully_charged = battery_fully_charged;
//0x3D2
datalayer_extended.tesla.battery_total_discharge = battery_total_discharge;
datalayer_extended.tesla.battery_total_charge = battery_total_charge;
datalayer.battery.status.total_discharged_battery_Wh = battery_total_discharge;
datalayer.battery.status.total_charged_battery_Wh = battery_total_charge;
//0x392
datalayer_extended.tesla.battery_moduleType = battery_moduleType;
datalayer_extended.tesla.battery_packMass = battery_packMass;
@ -1311,11 +1311,11 @@ void handle_incoming_can_frame_battery(CAN_frame rx_frame) {
break;
case 0x3D2: //TotalChargeDischarge:
battery_total_discharge = ((rx_frame.data.u8[3] << 24) | (rx_frame.data.u8[2] << 16) |
(rx_frame.data.u8[1] << 8) | rx_frame.data.u8[0]) *
0.001; //0|32@1+ (0.001,0) [0|4294970] "kWh"
(rx_frame.data.u8[1] << 8) | rx_frame.data.u8[0]);
//0|32@1+ (0.001,0) [0|4294970] "kWh"
battery_total_charge = ((rx_frame.data.u8[7] << 24) | (rx_frame.data.u8[6] << 16) | (rx_frame.data.u8[5] << 8) |
rx_frame.data.u8[4]) *
0.001; //32|32@1+ (0.001,0) [0|4294970] "kWh"
rx_frame.data.u8[4]);
//32|32@1+ (0.001,0) [0|4294970] "kWh"
break;
case 0x332: //min/max hist values //BattBrickMinMax:
mux = (rx_frame.data.u8[0] & 0x03); //BattBrickMultiplexer M : 0|2@1+ (1,0) [0|0] ""

View file

@ -45,6 +45,9 @@ typedef struct {
*/
uint32_t reported_remaining_capacity_Wh;
int32_t total_charged_battery_Wh = 0;
int32_t total_discharged_battery_Wh = 0;
/** Maximum allowed battery discharge power in Watts. Set by battery */
uint32_t max_discharge_power_W = 0;
/** Maximum allowed battery charge power in Watts. Set by battery */

View file

@ -321,8 +321,6 @@ typedef struct {
uint16_t battery_expected_energy_remaining_m1 = 0;
bool battery_full_charge_complete = false;
bool battery_fully_charged = false;
uint16_t battery_total_discharge = 0;
uint16_t battery_total_charge = 0;
uint16_t battery_BrickVoltageMax = 0;
uint16_t battery_BrickVoltageMin = 0;
uint8_t battery_BrickVoltageMaxNum = 0;

View file

@ -81,6 +81,10 @@ SensorConfig sensorConfigTemplate[] = {
{"remaining_capacity_real", "Battery Remaining Capacity (real)", "", "Wh", "energy"},
{"max_discharge_power", "Battery Max Discharge Power", "", "W", "power"},
{"max_charge_power", "Battery Max Charge Power", "", "W", "power"},
#if defined(MEB_BATTERY) || defined(TESLA_BATTERY)
{"charged_energy", "Battery Charged Energy", "", "Wh", "energy"},
{"discharged_energy", "Battery Discharged Energy", "", "Wh", "energy"},
#endif
{"bms_status", "BMS Status", "", "", ""},
{"pause_status", "Pause Status", "", "", ""}};
@ -179,6 +183,13 @@ void set_battery_attributes(JsonDocument& doc, const DATALAYER_BATTERY_TYPE& bat
doc["remaining_capacity" + suffix] = ((float)battery.status.reported_remaining_capacity_Wh);
doc["max_discharge_power" + suffix] = ((float)battery.status.max_discharge_power_W);
doc["max_charge_power" + suffix] = ((float)battery.status.max_charge_power_W);
#if defined(MEB_BATTERY) || defined(TESLA_BATTERY)
if (datalayer.battery.status.total_charged_battery_Wh != 0 &&
datalayer.battery.status.total_discharged_battery_Wh != 0) {
doc["charged_energy" + suffix] = ((float)datalayer.battery.status.total_charged_battery_Wh);
doc["discharged_energy" + suffix] = ((float)datalayer.battery.status.total_discharged_battery_Wh);
}
#endif
}
static std::vector<EventData> order_events;

View file

@ -506,8 +506,8 @@ String advanced_battery_processor(const String& var) {
float energy_buffer_m1 = static_cast<float>(datalayer_extended.tesla.battery_energy_buffer_m1) * 0.01;
float expected_energy_remaining_m1 =
static_cast<float>(datalayer_extended.tesla.battery_expected_energy_remaining_m1) * 0.02;
float total_discharge = static_cast<float>(datalayer_extended.tesla.battery_total_discharge);
float total_charge = static_cast<float>(datalayer_extended.tesla.battery_total_charge);
float total_discharge = static_cast<float>(datalayer.battery.status.total_discharged_battery_Wh) * 0.001;
float total_charge = static_cast<float>(datalayer.battery.status.total_charged_battery_Wh) * 0.001;
float packMass = static_cast<float>(datalayer_extended.tesla.battery_packMass);
float platformMaxBusVoltage =
static_cast<float>(datalayer_extended.tesla.battery_platformMaxBusVoltage) * 0.1 + 375;
@ -1186,6 +1186,10 @@ String advanced_battery_processor(const String& var) {
}
content += " &deg;C</h4>";
}
content +=
"<h4>Total charged: " + String(datalayer.battery.status.total_charged_battery_Wh / 1000.0, 1) + " kWh</h4>";
content += "<h4>Total discharged: " + String(datalayer.battery.status.total_discharged_battery_Wh / 1000.0, 1) +
" kWh</h4>";
#endif //MEB_BATTERY
#ifdef RENAULT_ZOE_GEN2_BATTERY