From 07a4ad7abccc57c230cd5f4ed191ceeb5a74a554 Mon Sep 17 00:00:00 2001 From: Marijn van Galen Date: Tue, 25 Mar 2025 19:18:20 +0100 Subject: [PATCH] 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. --- Software/src/battery/MEB-BATTERY.cpp | 21 ++++++++++++++++++- Software/src/battery/MEB-BATTERY.h | 1 + Software/src/battery/TESLA-BATTERY.cpp | 12 +++++------ Software/src/datalayer/datalayer.h | 3 +++ Software/src/datalayer/datalayer_extended.h | 2 -- Software/src/devboard/mqtt/mqtt.cpp | 11 ++++++++++ .../webserver/advanced_battery_html.cpp | 8 +++++-- 7 files changed, 47 insertions(+), 11 deletions(-) diff --git a/Software/src/battery/MEB-BATTERY.cpp b/Software/src/battery/MEB-BATTERY.cpp index 551bf4f3..82591887 100644 --- a/Software/src/battery/MEB-BATTERY.cpp +++ b/Software/src/battery/MEB-BATTERY.cpp @@ -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: diff --git a/Software/src/battery/MEB-BATTERY.h b/Software/src/battery/MEB-BATTERY.h index b80e37e5..dcf6e447 100644 --- a/Software/src/battery/MEB-BATTERY.h +++ b/Software/src/battery/MEB-BATTERY.h @@ -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 diff --git a/Software/src/battery/TESLA-BATTERY.cpp b/Software/src/battery/TESLA-BATTERY.cpp index 78457eec..ee8b7f7f 100644 --- a/Software/src/battery/TESLA-BATTERY.cpp +++ b/Software/src/battery/TESLA-BATTERY.cpp @@ -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] "" diff --git a/Software/src/datalayer/datalayer.h b/Software/src/datalayer/datalayer.h index a1218d27..6122c8f9 100644 --- a/Software/src/datalayer/datalayer.h +++ b/Software/src/datalayer/datalayer.h @@ -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 */ diff --git a/Software/src/datalayer/datalayer_extended.h b/Software/src/datalayer/datalayer_extended.h index aee34879..5578c8b0 100644 --- a/Software/src/datalayer/datalayer_extended.h +++ b/Software/src/datalayer/datalayer_extended.h @@ -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; diff --git a/Software/src/devboard/mqtt/mqtt.cpp b/Software/src/devboard/mqtt/mqtt.cpp index 608c3ccc..71ac9fbc 100644 --- a/Software/src/devboard/mqtt/mqtt.cpp +++ b/Software/src/devboard/mqtt/mqtt.cpp @@ -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 order_events; diff --git a/Software/src/devboard/webserver/advanced_battery_html.cpp b/Software/src/devboard/webserver/advanced_battery_html.cpp index 0f1e6b1e..5d85380e 100644 --- a/Software/src/devboard/webserver/advanced_battery_html.cpp +++ b/Software/src/devboard/webserver/advanced_battery_html.cpp @@ -506,8 +506,8 @@ String advanced_battery_processor(const String& var) { float energy_buffer_m1 = static_cast(datalayer_extended.tesla.battery_energy_buffer_m1) * 0.01; float expected_energy_remaining_m1 = static_cast(datalayer_extended.tesla.battery_expected_energy_remaining_m1) * 0.02; - float total_discharge = static_cast(datalayer_extended.tesla.battery_total_discharge); - float total_charge = static_cast(datalayer_extended.tesla.battery_total_charge); + float total_discharge = static_cast(datalayer.battery.status.total_discharged_battery_Wh) * 0.001; + float total_charge = static_cast(datalayer.battery.status.total_charged_battery_Wh) * 0.001; float packMass = static_cast(datalayer_extended.tesla.battery_packMass); float platformMaxBusVoltage = static_cast(datalayer_extended.tesla.battery_platformMaxBusVoltage) * 0.1 + 375; @@ -1186,6 +1186,10 @@ String advanced_battery_processor(const String& var) { } content += " °C"; } + content += + "

Total charged: " + String(datalayer.battery.status.total_charged_battery_Wh / 1000.0, 1) + " kWh

"; + content += "

Total discharged: " + String(datalayer.battery.status.total_discharged_battery_Wh / 1000.0, 1) + + " kWh

"; #endif //MEB_BATTERY #ifdef RENAULT_ZOE_GEN2_BATTERY