Use base class for Volvo Spa battery

This commit is contained in:
Jaakko Haakana 2025-05-20 16:37:29 +03:00
parent 614b907791
commit 972ec68157
2 changed files with 123 additions and 110 deletions

View file

@ -1,106 +1,13 @@
#include "../include.h" #include "../include.h"
#ifdef VOLVO_SPA_BATTERY #ifdef VOLVO_SPA_BATTERY
#include "../communication/can/comm_can.h"
#include "../datalayer/datalayer.h" #include "../datalayer/datalayer.h"
#include "../datalayer/datalayer_extended.h" //For "More battery info" webpage #include "../datalayer/datalayer_extended.h" //For "More battery info" webpage
#include "../devboard/utils/events.h" #include "../devboard/utils/events.h"
#include "VOLVO-SPA-BATTERY.h" #include "VOLVO-SPA-BATTERY.h"
/* Do not change code below unless you are sure what you are doing */ void VolvoSpaBattery::
static unsigned long previousMillis100 = 0; // will store last time a 100ms CAN Message was send update_values() { //This function maps all the values fetched via CAN to the correct parameters used for the inverter
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
uint8_t cnt = 0; uint8_t cnt = 0;
// Update webserver datalayer // Update webserver datalayer
@ -227,7 +134,7 @@ void update_values_battery() { //This function maps all the values fetched via
#endif #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; datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
switch (rx_frame.ID) { switch (rx_frame.ID) {
case 0x3A: 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; battery_request_idx = 0;
batteryModuleNumber = 0x10; batteryModuleNumber = 0x10;
rxConsecutiveFrames = 0; 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 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 // Send 100ms CAN Message
if (currentMillis - previousMillis100 >= INTERVAL_100_MS) { if (currentMillis - previousMillis100 >= INTERVAL_100_MS) {
previousMillis100 = currentMillis; 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); strncpy(datalayer.system.info.battery_protocol, "Volvo / Polestar 69/78kWh SPA battery", 63);
datalayer.system.info.battery_protocol[63] = '\0'; datalayer.system.info.battery_protocol[63] = '\0';
datalayer.battery.info.number_of_cells = 0; // Initializes when all cells have been read datalayer.battery.info.number_of_cells = 0; // Initializes when all cells have been read

View file

@ -3,16 +3,122 @@
#include <Arduino.h> #include <Arduino.h>
#include "../include.h" #include "../include.h"
#define BATTERY_SELECTED #include "CanBattery.h"
#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
void setup_battery(void); #define BATTERY_SELECTED
void transmit_can_frame(CAN_frame* tx_frame, int interface); #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 #endif