cleanup part 5
This commit is contained in:
parent
1edc8d3e1c
commit
aa85867083
@ -6,15 +6,36 @@
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
extern uint16_t min_voltage;
|
||||
extern uint16_t max_voltage;
|
||||
extern struct {uint16_t min; uint16_t max;} module_voltages[N_BMS];
|
||||
extern int16_t max_temp;
|
||||
extern int16_t min_temp;
|
||||
extern struct {int16_t min; int16_t max;} module_temps[N_BMS];
|
||||
extern float module_std_deviation[N_BMS];
|
||||
#define ADBMS_NO_LOGGING_DEFS
|
||||
#include "ADBMS_Driver.h"
|
||||
|
||||
extern int16_t cellTemps[N_BMS][10];
|
||||
extern struct {
|
||||
struct {
|
||||
float soc;
|
||||
uint16_t min_voltage;
|
||||
uint16_t max_voltage;
|
||||
uint16_t min_temp;
|
||||
uint16_t max_temp;
|
||||
} pack;
|
||||
struct {
|
||||
BMS_Chip * chip;
|
||||
int16_t cellTemps[10];
|
||||
struct {
|
||||
uint8_t min_v_idx : 4; uint8_t max_v_idx : 4; // cell index: 0-15
|
||||
uint8_t min_t_idx : 4; uint8_t max_t_idx : 4; // used like this: battery->module[i].chip->cellVoltages[min_v_idx]
|
||||
};
|
||||
} module[N_BMS];
|
||||
} battery;
|
||||
|
||||
//Helper for getting min/max values
|
||||
static inline struct { uint16_t min_v; uint16_t max_v; int16_t min_t; int16_t max_t; } getModuleMinMax(int i) {
|
||||
return (typeof(getModuleMinMax(0))) {
|
||||
.min_v = battery.module[i].chip->cellVoltages[battery.module[i].min_v_idx],
|
||||
.max_v = battery.module[i].chip->cellVoltages[battery.module[i].max_v_idx],
|
||||
.min_t = battery.module[i].cellTemps[battery.module[i].min_t_idx],
|
||||
.max_t = battery.module[i].cellTemps[battery.module[i].max_t_idx]
|
||||
};
|
||||
}
|
||||
|
||||
HAL_StatusTypeDef battery_init(SPI_HandleTypeDef* hspi);
|
||||
HAL_StatusTypeDef battery_update();
|
||||
|
@ -3,8 +3,6 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern float current_soc;
|
||||
|
||||
void soc_init();
|
||||
void soc_update();
|
||||
|
||||
|
@ -17,15 +17,7 @@
|
||||
|
||||
#define MAX_TEMP 60 // max temperature in C
|
||||
|
||||
uint16_t min_voltage = 0xFFFF;
|
||||
uint16_t max_voltage = 0;
|
||||
typeof(module_voltages) module_voltages = {[0 ... N_BMS - 1] = {0xFFFF, 0}};
|
||||
int16_t min_temp = INT16_MAX;
|
||||
int16_t max_temp = INT16_MIN;
|
||||
typeof(module_temps) module_temps = {[0 ... N_BMS - 1] = {INT16_MAX, INT16_MIN}};
|
||||
float module_std_deviation[N_BMS] = {};
|
||||
|
||||
int16_t cellTemps[N_BMS][10] = {};
|
||||
typeof(battery) battery = {};
|
||||
|
||||
static bool error_window[MAX_ERRORS_WINDOW_SIZE] = {};
|
||||
static size_t error_window_index = 0;
|
||||
@ -59,6 +51,20 @@ HAL_StatusTypeDef battery_init(SPI_HandleTypeDef *hspi) {
|
||||
}
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
// Initialize battery structure with default values
|
||||
for (size_t i = 0; i < N_BMS; i++) {
|
||||
battery.module[i].chip = &bms_data[i];
|
||||
for (size_t j = 0; j < 10; j++) {
|
||||
battery.module[i].cellTemps[j] = 0;
|
||||
}
|
||||
}
|
||||
battery.pack.soc = 0.0f;
|
||||
battery.pack.min_voltage = 0xFFFF;
|
||||
battery.pack.max_voltage = 0;
|
||||
battery.pack.min_temp = INT16_MAX;
|
||||
battery.pack.max_temp = INT16_MIN;
|
||||
|
||||
debug_log(LOG_LEVEL_INFO, "Battery initialized successfully");
|
||||
return HAL_OK;
|
||||
}
|
||||
@ -101,69 +107,60 @@ HAL_StatusTypeDef battery_update() {
|
||||
|
||||
update_error_window(false, ret.bms_id);
|
||||
|
||||
min_voltage = 0xFFFF;
|
||||
max_voltage = 0;
|
||||
min_temp = INT16_MAX;
|
||||
max_temp = INT16_MIN;
|
||||
battery.pack.min_voltage = 0xFFFF;
|
||||
battery.pack.max_voltage = 0;
|
||||
battery.pack.min_temp = INT16_MAX;
|
||||
battery.pack.max_temp = INT16_MIN;
|
||||
|
||||
for (size_t i = 0; i < N_BMS; i++) {
|
||||
// Calculate standard deviation for each module
|
||||
if (DEBUG_CHANNEL_ENABLED(DEBUG_CHANNEL)) {
|
||||
float sum = 0;
|
||||
float mean = 0;
|
||||
float variance = 0;
|
||||
|
||||
// First pass: calculate mean
|
||||
for (size_t j = 0; j < N_CELLS; j++) {
|
||||
sum += bms_data[i].cellVoltages[j];
|
||||
}
|
||||
mean = sum / N_CELLS;
|
||||
|
||||
// Second pass: calculate variance
|
||||
for (size_t j = 0; j < N_CELLS; j++) {
|
||||
const float diff = bms_data[i].cellVoltages[j] - mean;
|
||||
variance += diff * diff;
|
||||
}
|
||||
variance /= N_CELLS;
|
||||
|
||||
// Calculate standard deviation
|
||||
module_std_deviation[i] = sqrtf(variance);
|
||||
}
|
||||
// Initialize min/max indices for this module
|
||||
battery.module[i].min_v_idx = 0;
|
||||
battery.module[i].max_v_idx = 0;
|
||||
battery.module[i].min_t_idx = 0;
|
||||
battery.module[i].max_t_idx = 0;
|
||||
|
||||
// Track min/max voltages
|
||||
for (size_t j = 0; j < N_CELLS; j++) {
|
||||
if (bms_data[i].cellVoltages[j] > min_voltage) {
|
||||
min_voltage = bms_data[i].cellVoltages[j];
|
||||
if (bms_data[i].cellVoltages[j] < battery.pack.min_voltage) {
|
||||
battery.pack.min_voltage = bms_data[i].cellVoltages[j];
|
||||
}
|
||||
if (bms_data[i].cellVoltages[j] < max_voltage) {
|
||||
max_voltage = bms_data[i].cellVoltages[j];
|
||||
if (bms_data[i].cellVoltages[j] > battery.pack.max_voltage) {
|
||||
battery.pack.max_voltage = bms_data[i].cellVoltages[j];
|
||||
}
|
||||
if (bms_data[i].cellVoltages[j] > module_voltages[i].max) {
|
||||
module_voltages[i].max = bms_data[i].cellVoltages[j];
|
||||
|
||||
// Update min/max voltage indices for this module
|
||||
if (bms_data[i].cellVoltages[j] < bms_data[i].cellVoltages[battery.module[i].min_v_idx]) {
|
||||
battery.module[i].min_v_idx = j;
|
||||
}
|
||||
if (bms_data[i].cellVoltages[j] < module_voltages[i].min) {
|
||||
module_voltages[i].min = bms_data[i].cellVoltages[j];
|
||||
if (bms_data[i].cellVoltages[j] > bms_data[i].cellVoltages[battery.module[i].max_v_idx]) {
|
||||
battery.module[i].max_v_idx = j;
|
||||
}
|
||||
}
|
||||
|
||||
// Process temperature values
|
||||
for (size_t j = 0; j < 10; j++) { //10 GPIOs
|
||||
cellTemps[i][j] = ntc_mv_to_celsius(bms_data[i].auxVoltages[j]);
|
||||
battery.module[i].cellTemps[j] = ntc_mv_to_celsius(bms_data[i].auxVoltages[j]);
|
||||
|
||||
if (cellTemps[i][j] > max_temp) {
|
||||
max_temp = cellTemps[i][j];
|
||||
|
||||
// For new battery struct
|
||||
if (battery.module[i].cellTemps[j] > battery.pack.max_temp) {
|
||||
battery.pack.max_temp = battery.module[i].cellTemps[j];
|
||||
}
|
||||
if (cellTemps[i][j] < min_temp) {
|
||||
min_temp = cellTemps[i][j];
|
||||
if (battery.module[i].cellTemps[j] < battery.pack.min_temp) {
|
||||
battery.pack.min_temp = battery.module[i].cellTemps[j];
|
||||
}
|
||||
|
||||
if (cellTemps[i][j] > module_temps[i].max) {
|
||||
module_temps[i].max = cellTemps[i][j];
|
||||
// Update min/max temperature indices for this module
|
||||
if (battery.module[i].cellTemps[j] < battery.module[i].cellTemps[battery.module[i].min_t_idx]) {
|
||||
battery.module[i].min_t_idx = j;
|
||||
}
|
||||
if (cellTemps[i][j] < module_temps[i].min) {
|
||||
module_temps[i].min = cellTemps[i][j];
|
||||
if (battery.module[i].cellTemps[j] > battery.module[i].cellTemps[battery.module[i].max_t_idx]) {
|
||||
battery.module[i].max_t_idx = j;
|
||||
}
|
||||
|
||||
if (cellTemps[i][j] > (MAX_TEMP * (uint16_t)(TEMP_CONV))) {
|
||||
debug_log(LOG_LEVEL_ERROR, "Cell %u on BMS %u overtemp: %d0 mC", j, i, cellTemps[i][j]);
|
||||
// Check for overtemperature condition
|
||||
if (battery.module[i].cellTemps[j] > (MAX_TEMP * (uint16_t)(TEMP_CONV))) {
|
||||
debug_log(LOG_LEVEL_ERROR, "Cell %u on BMS %u overtemp: %d0 mC", j, i, battery.module[i].cellTemps[j]);
|
||||
can_send_error(TS_ERRORKIND_CELL_OVERTEMP, i);
|
||||
ts_sm_set_error_source(TS_ERROR_SOURCE_SLAVES, TS_ERRORKIND_CELL_OVERTEMP, true);
|
||||
} else {
|
||||
|
@ -49,9 +49,9 @@ void can_init(FDCAN_HandleTypeDef *handle) {
|
||||
HAL_StatusTypeDef can_send_status() {
|
||||
uint8_t data[8];
|
||||
data[0] = ts_state.current_state | (sdc_closed << 7);
|
||||
data[1] = roundf(current_soc);
|
||||
ftcan_marshal_unsigned(&data[2], min_voltage, 2);
|
||||
ftcan_marshal_signed(&data[4], max_temp, 2);
|
||||
data[1] = roundf(battery.pack.soc); // Use the battery struct now
|
||||
ftcan_marshal_unsigned(&data[2], battery.pack.min_voltage, 2); // Use the battery struct now
|
||||
ftcan_marshal_signed(&data[4], battery.pack.max_temp, 2); // Use the battery struct now
|
||||
data[6] = imd_data.state | (imd_data.ok << 7);
|
||||
if (imd_data.r_iso < 0xFFF) {
|
||||
data[7] = imd_data.r_iso >> 4;
|
||||
@ -136,7 +136,7 @@ HAL_StatusTypeDef can_send_details() {
|
||||
|
||||
// Marshal temperature data
|
||||
for (int i = 0; i < 10; i++) {
|
||||
data_ptr = ftcan_marshal_signed(data_ptr, cellTemps[module_index][i], 2);
|
||||
data_ptr = ftcan_marshal_signed(data_ptr, battery.module[module_index].cellTemps[i], 2);
|
||||
}
|
||||
|
||||
if ((status = isotp_add_message(isotp_connection_id, data, sizeof(data))) != ISOTP_OK) {
|
||||
|
@ -61,32 +61,25 @@ void print_master_status() {
|
||||
swo_write(" Time delta: %lu ms", HAL_GetTick() - shunt_data.last_message);
|
||||
|
||||
swo_write("\nBattery data:");
|
||||
swo_write(" Min/Max voltage: %d mV / %d mV", min_voltage, max_voltage);
|
||||
swo_write(" Min/Max temp: %d °C / %d °C", min_temp, max_temp);
|
||||
swo_write(" SoC: %.2f %%", current_soc);
|
||||
swo_write(" Module data: Min V | Max V | Std Dev | Min T | Max T");
|
||||
auto max_std_dev = 0.0f;
|
||||
for (size_t i = 0; i < N_BMS; i++) {
|
||||
if (module_std_deviation[i] > max_std_dev) {
|
||||
max_std_dev = module_std_deviation[i];
|
||||
}
|
||||
}
|
||||
swo_write(" Min/Max voltage: %d mV / %d mV", battery.pack.min_voltage, battery.pack.max_voltage);
|
||||
swo_write(" Min/Max temp: %d °C / %d °C", battery.pack.min_temp, battery.pack.max_temp);
|
||||
swo_write(" SoC: %.2f %%", battery.pack.soc);
|
||||
swo_write(" Module data: Min V | Max V | Min T | Max T");
|
||||
for (size_t i = 0; i < N_BMS; i++) {
|
||||
auto module_data = getModuleMinMax(i);
|
||||
#if USE_ANSI_ESCAPE_CODES
|
||||
#define COLOR_MIN "\033[38;5;75m" //blue for min
|
||||
#define COLOR_MAX "\033[38;5;203m" //red for max
|
||||
#define COLOR_RESET "\033[0m"
|
||||
swo_write(" %2zu: %s%5d mV%s | %s%5d mV%s | %s%.2f mV%s | %s%3d °C%s | %s%3d °C%s", i,
|
||||
(module_voltages[i].min == min_voltage) ? COLOR_MIN : "", (module_voltages[i].min), COLOR_RESET,
|
||||
(module_voltages[i].max == max_voltage) ? COLOR_MAX : "", (module_voltages[i].max), COLOR_RESET,
|
||||
(module_std_deviation[i] > max_std_dev) ? COLOR_MAX : "", module_std_deviation[i], COLOR_RESET,
|
||||
(module_temps[i].min == min_temp) ? COLOR_MIN : "", (module_temps[i].min), COLOR_RESET,
|
||||
(module_temps[i].max == max_temp) ? COLOR_MAX : "", (module_temps[i].max), COLOR_RESET);
|
||||
swo_write(" %2zu: %s%5d mV%s | %s%5d mV%s | %s%3d °C%s | %s%3d °C%s", i,
|
||||
(module_data.min_v == battery.pack.min_voltage) ? COLOR_MIN : "", (module_data.min_v), COLOR_RESET,
|
||||
(module_data.max_v == battery.pack.max_voltage) ? COLOR_MAX : "", (module_data.max_v), COLOR_RESET,
|
||||
(module_data.min_t == battery.pack.min_temp) ? COLOR_MIN : "", (module_data.min_t), COLOR_RESET,
|
||||
(module_data.max_t == battery.pack.max_temp) ? COLOR_MAX : "", (module_data.max_t), COLOR_RESET);
|
||||
#else
|
||||
swo_write(" %2zu: %5d mV | %5d mV | %.2f mV | %3d °C | %3d °C", i,
|
||||
module_voltages[i].min, module_voltages[i].max,
|
||||
module_std_deviation[i],
|
||||
module_temps[i].min, module_temps[i].max);
|
||||
swo_write(" %2zu: %5d mV | %5d mV | %3d °C | %3d °C", i,
|
||||
module_data.min_v, module_data.max_v,
|
||||
module_data.min_t, module_data.max_t);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -62,12 +62,12 @@ void print_battery_info() {
|
||||
swo_write(" GPIO as temperatures (°C):");
|
||||
swo_write(
|
||||
" G0: %4d G1: %4d G2: %4d G3: %4d G4: %4d",
|
||||
cellTemps[i][0], cellTemps[i][1], cellTemps[i][2],
|
||||
cellTemps[i][3], cellTemps[i][4]);
|
||||
battery.module[i].cellTemps[0], battery.module[i].cellTemps[1], battery.module[i].cellTemps[2],
|
||||
battery.module[i].cellTemps[3], battery.module[i].cellTemps[4]);
|
||||
swo_write(
|
||||
" G5: %4d G6: %4d G7: %4d G8: %4d G9: %4d",
|
||||
cellTemps[i][5], cellTemps[i][6], cellTemps[i][7],
|
||||
cellTemps[i][8], cellTemps[i][9]);
|
||||
battery.module[i].cellTemps[5], battery.module[i].cellTemps[6], battery.module[i].cellTemps[7],
|
||||
battery.module[i].cellTemps[8], battery.module[i].cellTemps[9]);
|
||||
|
||||
swo_write(
|
||||
" Internal temp: %d, VAnalog: %d, VDigital: %d, VRef: %d",
|
||||
|
@ -24,15 +24,12 @@ ocv_soc_pair_t OCV_SOC_PAIRS[] = {
|
||||
{4010, 83.79f}, {4020, 90.26f}, {4040, 94.58f}, {4100, 98.89f},
|
||||
{4200, 100.00f}};
|
||||
|
||||
float current_soc;
|
||||
|
||||
int current_was_flowing;
|
||||
uint32_t last_current_time;
|
||||
float soc_before_current;
|
||||
float mAs_before_current;
|
||||
|
||||
void soc_init() {
|
||||
current_soc = 0;
|
||||
last_current_time = 0;
|
||||
current_was_flowing = 1;
|
||||
}
|
||||
@ -74,7 +71,7 @@ void soc_update() {
|
||||
if (abs(shunt_data.current) >= SOC_ESTIMATION_NO_CURRENT_THRESH) {
|
||||
last_current_time = now;
|
||||
if (!current_was_flowing) {
|
||||
soc_before_current = current_soc;
|
||||
soc_before_current = battery.pack.soc;
|
||||
mAs_before_current = shunt_data.current_counter;
|
||||
}
|
||||
current_was_flowing = 1;
|
||||
@ -86,11 +83,11 @@ void soc_update() {
|
||||
last_current_time == 0) {
|
||||
// Assume we're measuring OCV if there's been no current for a while (or
|
||||
// we've just turned on the battery).
|
||||
current_soc = soc_for_ocv(min_voltage);
|
||||
battery.pack.soc = soc_for_ocv(battery.pack.min_voltage);
|
||||
} else {
|
||||
// Otherwise, use the current counter to update SoC
|
||||
const float as_delta = shunt_data.current_counter - mAs_before_current;
|
||||
const float soc_delta = as_delta / SOC_ESTIMATION_BATTERY_CAPACITY * 100;
|
||||
current_soc = soc_before_current - soc_delta;
|
||||
battery.pack.soc = soc_before_current - soc_delta;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user