From 972ec68157e2783113e7f20dbe90a90553cebb55 Mon Sep 17 00:00:00 2001 From: Jaakko Haakana Date: Tue, 20 May 2025 16:37:29 +0300 Subject: [PATCH] Use base class for Volvo Spa battery --- Software/src/battery/VOLVO-SPA-BATTERY.cpp | 107 ++--------------- Software/src/battery/VOLVO-SPA-BATTERY.h | 126 +++++++++++++++++++-- 2 files changed, 123 insertions(+), 110 deletions(-) diff --git a/Software/src/battery/VOLVO-SPA-BATTERY.cpp b/Software/src/battery/VOLVO-SPA-BATTERY.cpp index 97b3891b..25aeb02f 100644 --- a/Software/src/battery/VOLVO-SPA-BATTERY.cpp +++ b/Software/src/battery/VOLVO-SPA-BATTERY.cpp @@ -1,106 +1,13 @@ #include "../include.h" #ifdef VOLVO_SPA_BATTERY +#include "../communication/can/comm_can.h" #include "../datalayer/datalayer.h" #include "../datalayer/datalayer_extended.h" //For "More battery info" webpage #include "../devboard/utils/events.h" #include "VOLVO-SPA-BATTERY.h" -/* Do not change code below unless you are sure what you are doing */ -static unsigned long previousMillis100 = 0; // will store last time a 100ms CAN Message was send -static unsigned long previousMillis1s = 0; // will store last time a 1s CAN Message was send -static unsigned long previousMillis60s = 0; // will store last time a 60s CAN Message was send - -static float BATT_U = 0; //0x3A -static float MAX_U = 0; //0x3A -static float MIN_U = 0; //0x3A -static float BATT_I = 0; //0x3A -static int32_t CHARGE_ENERGY = 0; //0x1A1 -static uint8_t BATT_ERR_INDICATION = 0; //0x413 -static float BATT_T_MAX = 0; //0x413 -static float BATT_T_MIN = 0; //0x413 -static float BATT_T_AVG = 0; //0x413 -static uint16_t SOC_BMS = 0; //0X37D -static uint16_t SOC_CALC = 0; -static uint16_t CELL_U_MAX = 3700; //0x37D -static uint16_t CELL_U_MIN = 3700; //0x37D -static uint8_t CELL_ID_U_MAX = 0; //0x37D -static uint16_t HvBattPwrLimDchaSoft = 0; //0x369 -static uint16_t HvBattPwrLimDcha1 = 0; //0x175 -static uint16_t HvBattPwrLimDchaSlowAgi = 0; //0x177 -static uint16_t HvBattPwrLimChrgSlowAgi = 0; //0x177 -static uint8_t batteryModuleNumber = 0x10; // First battery module -static uint8_t battery_request_idx = 0; -static uint8_t rxConsecutiveFrames = 0; -static uint16_t min_max_voltage[2]; //contains cell min[0] and max[1] values in mV -static uint8_t cellcounter = 0; -static uint16_t cell_voltages[108]; //array with all the cellvoltages -static bool startedUp = false; -static uint8_t DTC_reset_counter = 0; - -CAN_frame VOLVO_536 = {.FD = false, - .ext_ID = false, - .DLC = 8, - .ID = 0x536, - //.data = {0x00, 0x40, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00}}; //Network manage frame - .data = {0x00, 0x40, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00}}; //Network manage frame - -CAN_frame VOLVO_140_CLOSE = {.FD = false, - .ext_ID = false, - .DLC = 8, - .ID = 0x140, - .data = {0x00, 0x02, 0x00, 0xB7, 0xFF, 0x03, 0xFF, 0x82}}; //Close contactors message - -CAN_frame VOLVO_140_OPEN = {.FD = false, - .ext_ID = false, - .DLC = 8, - .ID = 0x140, - .data = {0x00, 0x02, 0x00, 0x9E, 0xFF, 0x03, 0xFF, 0x82}}; //Open contactor message - -CAN_frame VOLVO_372 = { - .FD = false, - .ext_ID = false, - .DLC = 8, - .ID = 0x372, - .data = {0x00, 0xA6, 0x07, 0x14, 0x04, 0x00, 0x80, 0x00}}; //Ambient Temp -->>VERIFY this data content!!!<<-- -CAN_frame VOLVO_CELL_U_Req = {.FD = false, - .ext_ID = false, - .DLC = 8, - .ID = 0x735, - .data = {0x03, 0x22, 0x4B, 0x00, 0x00, 0x00, 0x00, 0x00}}; //Cell voltage request frame -CAN_frame VOLVO_FlowControl = {.FD = false, - .ext_ID = false, - .DLC = 8, - .ID = 0x735, - .data = {0x30, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00}}; //Flowcontrol -CAN_frame VOLVO_SOH_Req = {.FD = false, - .ext_ID = false, - .DLC = 8, - .ID = 0x735, - .data = {0x03, 0x22, 0x49, 0x6D, 0x00, 0x00, 0x00, 0x00}}; //Battery SOH request frame -CAN_frame VOLVO_BECMsupplyVoltage_Req = { - .FD = false, - .ext_ID = false, - .DLC = 8, - .ID = 0x735, - .data = {0x03, 0x22, 0xF4, 0x42, 0x00, 0x00, 0x00, 0x00}}; //BECM supply voltage request frame -CAN_frame VOLVO_DTC_Erase = {.FD = false, - .ext_ID = false, - .DLC = 8, - .ID = 0x7FF, - .data = {0x04, 0x14, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00}}; //Global DTC erase -CAN_frame VOLVO_BECM_ECUreset = { - .FD = false, - .ext_ID = false, - .DLC = 8, - .ID = 0x735, - .data = {0x02, 0x11, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00}}; //BECM ECU reset command (reboot/powercycle BECM) -CAN_frame VOLVO_DTCreadout = {.FD = false, - .ext_ID = false, - .DLC = 8, - .ID = 0x7FF, - .data = {0x02, 0x19, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}}; //Global DTC readout - -void update_values_battery() { //This function maps all the values fetched via CAN to the correct parameters used for the inverter +void VolvoSpaBattery:: + update_values() { //This function maps all the values fetched via CAN to the correct parameters used for the inverter uint8_t cnt = 0; // Update webserver datalayer @@ -227,7 +134,7 @@ void update_values_battery() { //This function maps all the values fetched via #endif } -void handle_incoming_can_frame_battery(CAN_frame rx_frame) { +void VolvoSpaBattery::handle_incoming_can_frame(CAN_frame rx_frame) { datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; switch (rx_frame.ID) { case 0x3A: @@ -427,7 +334,7 @@ void handle_incoming_can_frame_battery(CAN_frame rx_frame) { } } -void readCellVoltages() { +void VolvoSpaBattery::readCellVoltages() { battery_request_idx = 0; batteryModuleNumber = 0x10; rxConsecutiveFrames = 0; @@ -435,7 +342,7 @@ void readCellVoltages() { transmit_can_frame(&VOLVO_CELL_U_Req, can_config.battery); //Send cell voltage read request for first module } -void transmit_can_battery(unsigned long currentMillis) { +void VolvoSpaBattery::transmit_can(unsigned long currentMillis) { // Send 100ms CAN Message if (currentMillis - previousMillis100 >= INTERVAL_100_MS) { previousMillis100 = currentMillis; @@ -470,7 +377,7 @@ void transmit_can_battery(unsigned long currentMillis) { } } -void setup_battery(void) { // Performs one time setup at startup +void VolvoSpaBattery::setup(void) { // Performs one time setup at startup strncpy(datalayer.system.info.battery_protocol, "Volvo / Polestar 69/78kWh SPA battery", 63); datalayer.system.info.battery_protocol[63] = '\0'; datalayer.battery.info.number_of_cells = 0; // Initializes when all cells have been read diff --git a/Software/src/battery/VOLVO-SPA-BATTERY.h b/Software/src/battery/VOLVO-SPA-BATTERY.h index 61fa51e9..53b777ee 100644 --- a/Software/src/battery/VOLVO-SPA-BATTERY.h +++ b/Software/src/battery/VOLVO-SPA-BATTERY.h @@ -3,16 +3,122 @@ #include #include "../include.h" -#define BATTERY_SELECTED -#define MAX_PACK_VOLTAGE_108S_DV 4540 -#define MIN_PACK_VOLTAGE_108S_DV 2938 -#define MAX_PACK_VOLTAGE_96S_DV 4080 -#define MIN_PACK_VOLTAGE_96S_DV 2620 -#define MAX_CELL_DEVIATION_MV 250 -#define MAX_CELL_VOLTAGE_MV 4260 // Charging is halted if one cell goes above this -#define MIN_CELL_VOLTAGE_MV 2700 // Charging is halted if one cell goes below this +#include "CanBattery.h" -void setup_battery(void); -void transmit_can_frame(CAN_frame* tx_frame, int interface); +#define BATTERY_SELECTED +#define SELECTED_BATTERY_CLASS VolvoSpaBattery + +class VolvoSpaBattery : public CanBattery { + public: + virtual void setup(void); + virtual void handle_incoming_can_frame(CAN_frame rx_frame); + virtual void update_values(); + virtual void transmit_can(unsigned long currentMillis); + + private: + void readCellVoltages(); + + static const int MAX_PACK_VOLTAGE_108S_DV = 4540; + static const int MIN_PACK_VOLTAGE_108S_DV = 2938; + static const int MAX_PACK_VOLTAGE_96S_DV = 4080; + static const int MIN_PACK_VOLTAGE_96S_DV = 2620; + static const int MAX_CELL_DEVIATION_MV = 250; + static const int MAX_CELL_VOLTAGE_MV = 4260; // Charging is halted if one cell goes above this + static const int MIN_CELL_VOLTAGE_MV = 2700; // Charging is halted if one cell goes below this + + unsigned long previousMillis100 = 0; // will store last time a 100ms CAN Message was send + unsigned long previousMillis1s = 0; // will store last time a 1s CAN Message was send + unsigned long previousMillis60s = 0; // will store last time a 60s CAN Message was send + + float BATT_U = 0; //0x3A + float MAX_U = 0; //0x3A + float MIN_U = 0; //0x3A + float BATT_I = 0; //0x3A + int32_t CHARGE_ENERGY = 0; //0x1A1 + uint8_t BATT_ERR_INDICATION = 0; //0x413 + float BATT_T_MAX = 0; //0x413 + float BATT_T_MIN = 0; //0x413 + float BATT_T_AVG = 0; //0x413 + uint16_t SOC_BMS = 0; //0X37D + uint16_t SOC_CALC = 0; + uint16_t CELL_U_MAX = 3700; //0x37D + uint16_t CELL_U_MIN = 3700; //0x37D + uint8_t CELL_ID_U_MAX = 0; //0x37D + uint16_t HvBattPwrLimDchaSoft = 0; //0x369 + uint16_t HvBattPwrLimDcha1 = 0; //0x175 + uint16_t HvBattPwrLimDchaSlowAgi = 0; //0x177 + uint16_t HvBattPwrLimChrgSlowAgi = 0; //0x177 + uint8_t batteryModuleNumber = 0x10; // First battery module + uint8_t battery_request_idx = 0; + uint8_t rxConsecutiveFrames = 0; + uint16_t min_max_voltage[2]; //contains cell min[0] and max[1] values in mV + uint8_t cellcounter = 0; + uint16_t cell_voltages[108]; //array with all the cellvoltages + bool startedUp = false; + uint8_t DTC_reset_counter = 0; + + CAN_frame VOLVO_536 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x536, + //.data = {0x00, 0x40, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00}}; //Network manage frame + .data = {0x00, 0x40, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00}}; //Network manage frame + + CAN_frame VOLVO_140_CLOSE = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x140, + .data = {0x00, 0x02, 0x00, 0xB7, 0xFF, 0x03, 0xFF, 0x82}}; //Close contactors message + + CAN_frame VOLVO_140_OPEN = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x140, + .data = {0x00, 0x02, 0x00, 0x9E, 0xFF, 0x03, 0xFF, 0x82}}; //Open contactor message + + CAN_frame VOLVO_372 = { + .FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x372, + .data = {0x00, 0xA6, 0x07, 0x14, 0x04, 0x00, 0x80, 0x00}}; //Ambient Temp -->>VERIFY this data content!!!<<-- + CAN_frame VOLVO_CELL_U_Req = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x735, + .data = {0x03, 0x22, 0x4B, 0x00, 0x00, 0x00, 0x00, 0x00}}; //Cell voltage request frame + CAN_frame VOLVO_FlowControl = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x735, + .data = {0x30, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00}}; //Flowcontrol + CAN_frame VOLVO_SOH_Req = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x735, + .data = {0x03, 0x22, 0x49, 0x6D, 0x00, 0x00, 0x00, 0x00}}; //Battery SOH request frame + CAN_frame VOLVO_BECMsupplyVoltage_Req = { + .FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x735, + .data = {0x03, 0x22, 0xF4, 0x42, 0x00, 0x00, 0x00, 0x00}}; //BECM supply voltage request frame + CAN_frame VOLVO_DTC_Erase = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x7FF, + .data = {0x04, 0x14, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00}}; //Global DTC erase + CAN_frame VOLVO_BECM_ECUreset = { + .FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x735, + .data = {0x02, 0x11, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00}}; //BECM ECU reset command (reboot/powercycle BECM) + CAN_frame VOLVO_DTCreadout = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x7FF, + .data = {0x02, 0x19, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}}; //Global DTC readout +}; #endif