refactor: cell voltages, main loop

This commit is contained in:
Kilian Bracher 2025-01-31 18:18:32 +01:00
parent 5d2b8fd09b
commit 7fbd335017
Signed by: k.bracher
SSH Key Fingerprint: SHA256:mXpyZkK7RDiJ7qeHCKJX108woM0cl5TrCvNBJASu6lM
5 changed files with 119 additions and 98 deletions

View File

@ -78,23 +78,13 @@ HAL_StatusTypeDef amsStopBalancing();
HAL_StatusTypeDef amsSelfTest();
uint8_t amsConfigOverUnderVoltage(uint16_t overVoltage, uint16_t underVoltage);
HAL_StatusTypeDef amsConfigOverUnderVoltage(uint16_t overVoltage, uint16_t underVoltage);
uint8_t amsCheckUnderOverVoltage(Cell_Module* module);
uint8_t amsConfigOverVoltage(uint16_t overVoltage);
HAL_StatusTypeDef amsCheckUnderOverVoltage(Cell_Module (*module)[N_BMS]);
uint8_t amscheckOpenCellWire(Cell_Module* module);
HAL_StatusTypeDef amsClearFlag();
HAL_StatusTypeDef amsClearAux();
uint8_t amsClearFlag();
uint8_t amsClearAux();
uint8_t amsClearCells();
uint8_t amsSendWarning();
uint8_t amsSendError();
uint8_t amsClearWarning();
uint8_t amsClearError();
uint8_t amsReadCellVoltages(Cell_Module* module);
HAL_StatusTypeDef amsReadCellVoltages(Cell_Module (*module)[N_BMS]);
#endif /* INC_ADBMS_ABSTRACTION_H_ */

View File

@ -11,6 +11,7 @@
#include "ADBMS_Abstraction.h"
#include "ADBMS_CMD_MAKROS.h"
#include "ADBMS_LL_Driver.h"
#include "config_ADBMS6830.h"
#include <stdbool.h>
@ -25,7 +26,7 @@ typedef enum {
} amsState;
extern amsState currentAMSState;
extern Cell_Module module;
extern Cell_Module modules[N_BMS];
extern uint32_t balancedCells;
extern bool BalancingActive;

View File

@ -16,7 +16,7 @@ extern uint8_t numberofCells;
#define CHECK_RETURN(x) \
{ \
uint8_t status = x; \
HAL_StatusTypeDef status = x; \
if (status != 0) \
return status; \
}
@ -205,90 +205,114 @@ HAL_StatusTypeDef amsStopBalancing() { return writeCMD(MUTE, CMD_EMPTY_BUFFER, 0
HAL_StatusTypeDef amsSelfTest() { return 0; }
uint8_t amsConfigOverUnderVoltage(uint16_t overVoltage, uint16_t underVoltage) {
uint8_t buffer[CFG_GROUP_A_SIZE] = {};
HAL_StatusTypeDef amsConfigOverUnderVoltage(uint16_t overVoltage, uint16_t underVoltage) {
uint8_t buffer[CMD_BUFFER_SIZE(CFG_GROUP_B_SIZE)] = {};
if (underVoltage & 0xF000 || overVoltage & 0xF000) { // only 12 bits allowed
return 1;
return HAL_ERROR;
}
CHECK_RETURN(readCMD(RDCFGB, buffer, CFG_GROUP_A_SIZE));
debug_log(LOG_LEVEL_INFO, "Configuring OV/UV thresholds to %f/%f", mV_from_ADBMS6830(overVoltage), mV_from_ADBMS6830(underVoltage));
CHECK_RETURN(readCMD(RDCFGB, buffer, CFG_GROUP_B_SIZE));
for (size_t i = 0; i < N_BMS; i++) {
size_t offset = BUFFER_BMS_OFFSET(i, CFG_GROUP_B_SIZE);
//UV
buffer[0] = (uint8_t) (underVoltage & 0xFF);
buffer[1] &= 0xF0;
buffer[1] |= (uint8_t) ((underVoltage >> 8) & 0x0F);
buffer[offset + 0] = (uint8_t)(underVoltage & 0xFF);
buffer[offset + 1] &= 0xF0;
buffer[offset + 1] |= (uint8_t)((underVoltage >> 8) & 0x0F);
//OV
buffer[1] &= 0x0F;
buffer[1] |= (uint8_t) (overVoltage << 4);
buffer[2] = (uint8_t) (overVoltage >> 4);
return writeCMD(WRCFGB, buffer, CFG_GROUP_A_SIZE);
}
uint8_t amsCheckUnderOverVoltage(Cell_Module* module) {
uint8_t regbuffer[STATUS_GROUP_D_SIZE];
uint32_t ov_uv_data = 0;
CHECK_RETURN(readCMD(RDSTATD, regbuffer, STATUS_GROUP_D_SIZE));
ov_uv_data = (regbuffer[0] << 0) | (regbuffer[1] << 8) |
(regbuffer[2] << 16) | (regbuffer[3] << 24);
module->overVoltage = 0;
module->underVoltage = 0;
for (size_t i = 0; i < numberofCells; i++) { // ov/uv flags are 1-bit flags for each cell C0UV, C0OV, C1UV, C1OV, ...
module->underVoltage |= (ov_uv_data >> (i * 2)) & 0x01;
module->overVoltage |= (ov_uv_data >> (i * 2 + 1)) & 0x01;
buffer[offset + 1] &= 0x0F;
buffer[offset + 1] |= (uint8_t)(overVoltage << 4);
buffer[offset + 2] = (uint8_t)(overVoltage >> 4);
}
return 0;
return writeCMD(WRCFGB, buffer, CFG_GROUP_B_SIZE);
}
uint8_t amsClearFlag() {
uint8_t buffer[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
HAL_StatusTypeDef amsCheckUnderOverVoltage(Cell_Module (*module)[N_BMS]) {
uint8_t regbuffer[CMD_BUFFER_SIZE(STATUS_GROUP_D_SIZE)] = {};
CHECK_RETURN(readCMD(RDSTATD, regbuffer, STATUS_GROUP_D_SIZE));
for (size_t i = 0; i < N_BMS; i++) {
size_t offset = BUFFER_BMS_OFFSET(i, STATUS_GROUP_D_SIZE);
uint32_t ov_uv_data = 0;
ov_uv_data = (regbuffer[offset + 0] << 0) | (regbuffer[offset + 1] << 8) |
(regbuffer[offset + 2] << 16) | (regbuffer[offset + 3] << 24);
module[i]->overVoltage = 0;
module[i]->underVoltage = 0;
for (size_t j = 0; j < numberofCells; j++) { // ov/uv flags are 1-bit flags for each cell C0UV, C0OV, C1UV, C1OV, ...
module[i]->underVoltage |= (ov_uv_data >> (j * 2)) & 0x01;
module[i]->overVoltage |= (ov_uv_data >> (j * 2 + 1)) & 0x01;
}
}
return HAL_OK;
}
HAL_StatusTypeDef amsClearFlag() {
uint8_t buffer[CMD_BUFFER_SIZE(6)] = {[0 ... CMD_BUFFER_SIZE(6) - 1] = 0xFF};
return writeCMD(CLRFLAG, buffer, 6);
}
uint8_t amsClearAux() {
uint8_t buffer[6];
return writeCMD(CLRAUX, buffer, 0);
HAL_StatusTypeDef amsClearAux() {
return writeCMD(CLRAUX, CMD_EMPTY_BUFFER, 0);
}
uint8_t amsClearCells() {
uint8_t buffer[6];
return writeCMD(CLRCELL, buffer, 0);
}
HAL_StatusTypeDef amsReadCellVoltages(Cell_Module (*module)[N_BMS]) {
uint8_t rxbuffer[CMD_BUFFER_SIZE(CV_GROUP_A_SIZE)] = {};
uint8_t amsReadCellVoltages(Cell_Module* module) {
uint8_t rxbuffer[CV_GROUP_A_SIZE];
CHECK_RETURN(readCMD(RDCVA, rxbuffer, CV_GROUP_A_SIZE));
module->cellVoltages[0] = mV_from_ADBMS6830(rxbuffer[0] | (rxbuffer[1] << 8));
module->cellVoltages[1] = mV_from_ADBMS6830(rxbuffer[2] | (rxbuffer[3] << 8));
module->cellVoltages[2] = mV_from_ADBMS6830(rxbuffer[4] | (rxbuffer[5] << 8));
for (size_t i = 0; i < N_BMS; i++) {
size_t offset = BUFFER_BMS_OFFSET(i, CV_GROUP_A_SIZE);
module[i]->cellVoltages[0] = mV_from_ADBMS6830(rxbuffer[offset + 0] | (rxbuffer[offset + 1] << 8));
module[i]->cellVoltages[1] = mV_from_ADBMS6830(rxbuffer[offset + 2] | (rxbuffer[offset + 3] << 8));
module[i]->cellVoltages[2] = mV_from_ADBMS6830(rxbuffer[offset + 4] | (rxbuffer[offset + 5] << 8));
}
CHECK_RETURN(readCMD(RDCVB, rxbuffer, CV_GROUP_A_SIZE));
module->cellVoltages[3] = mV_from_ADBMS6830(rxbuffer[0] | (rxbuffer[1] << 8));
module->cellVoltages[4] = mV_from_ADBMS6830(rxbuffer[2] | (rxbuffer[3] << 8));
module->cellVoltages[5] = mV_from_ADBMS6830(rxbuffer[4] | (rxbuffer[5] << 8));
for (size_t i = 0; i < N_BMS; i++) {
size_t offset = BUFFER_BMS_OFFSET(i, CV_GROUP_A_SIZE);
module[i]->cellVoltages[3] = mV_from_ADBMS6830(rxbuffer[offset + 0] | (rxbuffer[offset + 1] << 8));
module[i]->cellVoltages[4] = mV_from_ADBMS6830(rxbuffer[offset + 2] | (rxbuffer[offset + 3] << 8));
module[i]->cellVoltages[5] = mV_from_ADBMS6830(rxbuffer[offset + 4] | (rxbuffer[offset + 5] << 8));
}
CHECK_RETURN(readCMD(RDCVC, rxbuffer, CV_GROUP_A_SIZE));
module->cellVoltages[6] = mV_from_ADBMS6830(rxbuffer[0] | (rxbuffer[1] << 8));
module->cellVoltages[7] = mV_from_ADBMS6830(rxbuffer[2] | (rxbuffer[3] << 8));
module->cellVoltages[8] = mV_from_ADBMS6830(rxbuffer[4] | (rxbuffer[5] << 8));
for (size_t i = 0; i < N_BMS; i++) {
size_t offset = BUFFER_BMS_OFFSET(i, CV_GROUP_A_SIZE);
module[i]->cellVoltages[6] = mV_from_ADBMS6830(rxbuffer[offset + 0] | (rxbuffer[offset + 1] << 8));
module[i]->cellVoltages[7] = mV_from_ADBMS6830(rxbuffer[offset + 2] | (rxbuffer[offset + 3] << 8));
module[i]->cellVoltages[8] = mV_from_ADBMS6830(rxbuffer[offset + 4] | (rxbuffer[offset + 5] << 8));
}
CHECK_RETURN(readCMD(RDCVD, rxbuffer, CV_GROUP_A_SIZE));
module->cellVoltages[9] = mV_from_ADBMS6830(rxbuffer[0] | (rxbuffer[1] << 8));
module->cellVoltages[10] = mV_from_ADBMS6830(rxbuffer[2] | (rxbuffer[3] << 8));
module->cellVoltages[11] = mV_from_ADBMS6830(rxbuffer[4] | (rxbuffer[5] << 8));
for (size_t i = 0; i < N_BMS; i++) {
size_t offset = BUFFER_BMS_OFFSET(i, CV_GROUP_A_SIZE);
module[i]->cellVoltages[9] = mV_from_ADBMS6830(rxbuffer[offset + 0] | (rxbuffer[offset + 1] << 8));
module[i]->cellVoltages[10] = mV_from_ADBMS6830(rxbuffer[offset + 2] | (rxbuffer[offset + 3] << 8));
module[i]->cellVoltages[11] = mV_from_ADBMS6830(rxbuffer[offset + 4] | (rxbuffer[offset + 5] << 8));
}
CHECK_RETURN(readCMD(RDCVE, rxbuffer, CV_GROUP_A_SIZE));
module->cellVoltages[12] = mV_from_ADBMS6830(rxbuffer[0] | (rxbuffer[1] << 8));
module->cellVoltages[13] = mV_from_ADBMS6830(rxbuffer[2] | (rxbuffer[3] << 8));
module->cellVoltages[14] = mV_from_ADBMS6830(rxbuffer[4] | (rxbuffer[5] << 8));
for (size_t i = 0; i < N_BMS; i++) {
size_t offset = BUFFER_BMS_OFFSET(i, CV_GROUP_A_SIZE);
module[i]->cellVoltages[12] = mV_from_ADBMS6830(rxbuffer[offset + 0] | (rxbuffer[offset + 1] << 8));
module[i]->cellVoltages[13] = mV_from_ADBMS6830(rxbuffer[offset + 2] | (rxbuffer[offset + 3] << 8));
module[i]->cellVoltages[14] = mV_from_ADBMS6830(rxbuffer[offset + 4] | (rxbuffer[offset + 5] << 8));
}
CHECK_RETURN(readCMD(RDCVF, rxbuffer, CV_GROUP_A_SIZE));
module->cellVoltages[15] = mV_from_ADBMS6830(rxbuffer[0] | (rxbuffer[1] << 8));
for (size_t i = 0; i < N_BMS; i++) {
size_t offset = BUFFER_BMS_OFFSET(i, CV_GROUP_A_SIZE);
module[i]->cellVoltages[15] = mV_from_ADBMS6830(rxbuffer[offset + 0] | (rxbuffer[offset + 1] << 8));
}
return 0;
return HAL_OK;
}

View File

@ -20,7 +20,6 @@
#warning ask about the timeout value
SPI_HandleTypeDef* adbmsspi;
uint8_t command_queue[N_BMS][12] = {0};
uint8_t adbmsDriverInit(SPI_HandleTypeDef* hspi) {
mcuAdbmsCSLow();
@ -180,8 +179,6 @@ static uint8_t calculateDataPEC(uint8_t* data, uint8_t datalen) {
data[datalen - 2] = (currentpec >> 8) & 0xFF;
data[datalen - 1] = currentpec & 0xFF;
volatile uint8_t result = pec10_calc(true, datalen, data);
return 0;
} else {
return 1;

View File

@ -15,7 +15,7 @@
#include <stdint.h>
#include <string.h>
Cell_Module module = {};
Cell_Module modules[N_BMS] = {};
uint32_t balancedCells = 0;
bool balancingActive = false;
@ -41,15 +41,25 @@ void AMS_Init(SPI_HandleTypeDef* hspi) {
pollingTimes = (struct pollingTimes) {HAL_GetTick(), HAL_GetTick()};
}
#define any(x) ({ \
bool any = false; \
for (size_t i = 0; i < N_BMS; i++) { \
Cell_Module module = modules[i]; \
any |= (x); \
} \
any; \
})
uint8_t AMS_Idle_Loop() {
if (!amsWakeUp()) {
//error_data.data_kind = SEK_INTERNAL_BMS_TIMEOUT; //we don't receive data for the wakeup command
//set_error_source(ERROR_SOURCE_INTERNAL); //so we can't tell if we timed out
}
packetChecksumFails += amsAuxAndStatusMeasurement(&module);
packetChecksumFails += amsAuxAndStatusMeasurement(&modules);
if (module.status.SLEEP) {
if (any(module.status.SLEEP)) {
deviceSleeps++;
if (deviceSleeps > MAX_DEVICE_SLEEP) {
set_error_source(SEK_INTERNAL_BMS_TIMEOUT);
@ -58,14 +68,17 @@ uint8_t AMS_Idle_Loop() {
}
}
if (module.status.CS_FLT || module.status.SPIFLT || module.status.CMED ||
module.status.SMED || module.status.VDE || module.status.VDEL ||
module.status.OSCCHK || module.status.TMODCHK) {
//ftcan_marshal_unsigned(&error_data[SEK_INTERNAL_BMS_FAULT].data[0], module.status.CS_FLT, 2);
const uint8_t* ptr = ((uint8_t*)&module.status) + 4; //skip conversion counter
if (any(module.status.CS_FLT || module.status.SPIFLT || module.status.CMED || module.status.SMED ||
module.status.VDE || module.status.VDEL || module.status.OSCCHK || module.status.TMODCHK)) {
// TODO: handle errors
// ftcan_marshal_unsigned(&error_data[SEK_INTERNAL_BMS_FAULT].data[0], module.status.CS_FLT, 2);
/* const uint8_t* ptr = ((uint8_t*)&modules.status) + 4; //skip conversion counter
error_data[SEK_INTERNAL_BMS_FAULT].data[2] = ptr[1];
error_data[SEK_INTERNAL_BMS_FAULT].data[3] = ptr[0];
set_error_source(SEK_INTERNAL_BMS_FAULT);
set_error_source(SEK_INTERNAL_BMS_FAULT); */
// Fault bits are latched -- clear them so we can check again next
// iteration.
amsClearFlag();
@ -73,8 +86,8 @@ uint8_t AMS_Idle_Loop() {
clear_error_source(SEK_INTERNAL_BMS_FAULT);
}
packetChecksumFails += amsCellMeasurement(&module);
packetChecksumFails += amsCheckUnderOverVoltage(&module);
packetChecksumFails += amsCellMeasurement(&modules);
packetChecksumFails += amsCheckUnderOverVoltage(&modules);
if (packetChecksumFails > MAX_PACKET_CHECKSUM_FAILS) {
set_error_source(SEK_INTERNAL_BMS_CHECKSUM_FAIL);
@ -85,12 +98,12 @@ uint8_t AMS_Idle_Loop() {
bool overvolt = false;
bool undervolt = false;
for (size_t i = 0; i < numberofCells; i++) {
if (module.cellVoltages[i] < 2500) {
if (any(module.cellVoltages[i] < 2500)) {
undervolt = true;
error_data[SEK_UNDERVOLT].data[0] = i;
uint8_t* ptr = &error_data[SEK_UNDERVOLT].data[1];
//ftcan_marshal_unsigned(ptr, module.cellVoltages[i], 2);
} else if (module.cellVoltages[i] > 4200) {
} else if (any(module.cellVoltages[i] > 4200)) {
overvolt = true;
error_data[SEK_OVERVOLT].data[0] = i;
uint8_t* ptr = &error_data[SEK_OVERVOLT].data[1];
@ -98,7 +111,7 @@ uint8_t AMS_Idle_Loop() {
}
}
if (module.internalDieTemp > 28000 || module.status.THSD) { //TODO: change to correct value
if (any(module.internalDieTemp > 28000 || module.status.THSD)) { //TODO: change to correct value
//ftcan_marshal_unsigned(&error_data[SEK_INTERNAL_BMS_OVERTEMP].data[0], module.internalDieTemp, 2);
set_error_source(SEK_INTERNAL_BMS_OVERTEMP);
@ -120,9 +133,5 @@ uint8_t AMS_Idle_Loop() {
mcuDelay(10);
if ((module.overVoltage | module.underVoltage)) {
}
return 0;
}