refactor for multiple BMS:
reset, aux and status measurement
This commit is contained in:
parent
3ee15518d2
commit
a1cc8bc9a2
@ -63,15 +63,14 @@ typedef struct {
|
||||
|
||||
} Cell_Module;
|
||||
|
||||
uint8_t amsReset();
|
||||
HAL_StatusTypeDef amsReset();
|
||||
|
||||
uint8_t initAMS(SPI_HandleTypeDef* hspi);
|
||||
uint8_t amsWakeUp();
|
||||
HAL_StatusTypeDef initAMS(SPI_HandleTypeDef* hspi);
|
||||
HAL_StatusTypeDef amsWakeUp();
|
||||
|
||||
uint8_t amsCellMeasurement(Cell_Module* module);
|
||||
uint8_t amsConfigCellMeasurement(uint8_t numberofChannels);
|
||||
HAL_StatusTypeDef amsCellMeasurement(Cell_Module* module);
|
||||
|
||||
uint8_t amsAuxAndStatusMeasurement(Cell_Module* module);
|
||||
HAL_StatusTypeDef amsAuxAndStatusMeasurement(Cell_Module * module[static N_BMS]);
|
||||
uint8_t amsConfigAuxMeasurement(uint16_t Channels);
|
||||
|
||||
uint8_t amsConfigGPIO(uint16_t gpios);
|
||||
|
@ -50,7 +50,7 @@ static inline HAL_StatusTypeDef __writeCMD(uint16_t command, uint8_t * args, siz
|
||||
[[gnu::access(read_write, 2, 3), gnu::nonnull(2)]]
|
||||
HAL_StatusTypeDef readCMD(uint16_t command, uint8_t * buffer, size_t buflen);
|
||||
|
||||
uint8_t pollCMD(uint16_t command);
|
||||
HAL_StatusTypeDef pollCMD(uint16_t command);
|
||||
|
||||
|
||||
void mcuAdbmsCSLow();
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "ADBMS_Abstraction.h"
|
||||
#include "ADBMS_CMD_MAKROS.h"
|
||||
#include "ADBMS_LL_Driver.h"
|
||||
#include "config_ADBMS6830.h"
|
||||
#include "swo_log.h"
|
||||
#include <stddef.h>
|
||||
|
||||
@ -15,17 +16,17 @@ extern uint8_t numberofCells;
|
||||
|
||||
#define CHECK_RETURN(x) \
|
||||
{ \
|
||||
uint8_t status = x; \
|
||||
uint8_t status = x; \
|
||||
if (status != 0) \
|
||||
return status; \
|
||||
}
|
||||
|
||||
uint8_t amsReset() {
|
||||
HAL_StatusTypeDef amsReset() {
|
||||
amsWakeUp();
|
||||
readCMD(SRST, CMD_EMPTY_BUFFER, CMD_EMPTY_BUFFER_SIZE);
|
||||
|
||||
uint8_t buffer[CMD_BUFFER_SIZE(SID_GROUP_SIZE)] = {0};
|
||||
CHECK_RETURN(readCMD(RDSID, buffer, CMD_BUFFER_SIZE(SID_GROUP_SIZE)));
|
||||
uint8_t sidbuffer[CMD_BUFFER_SIZE(SID_GROUP_SIZE)] = {};
|
||||
CHECK_RETURN(readCMD(RDSID, sidbuffer, CMD_BUFFER_SIZE(SID_GROUP_SIZE)));
|
||||
|
||||
debug_log(LOG_LEVEL_INFO, "BMS reset complete\n");
|
||||
|
||||
@ -34,7 +35,7 @@ uint8_t amsReset() {
|
||||
for (size_t i = 0; i < N_BMS; i++) {
|
||||
uint64_t id = 0;
|
||||
for (size_t j = 0; j < SID_GROUP_SIZE; j++) {
|
||||
id |= buffer[BUFFER_BMS_OFFSET(i, SID_GROUP_SIZE) + j] << (j * 8);
|
||||
id |= sidbuffer[BUFFER_BMS_OFFSET(i, SID_GROUP_SIZE) + j] << (j * 8);
|
||||
}
|
||||
debug_log_cont(LOG_LEVEL_INFO, "0x%llx ", id);
|
||||
}
|
||||
@ -46,94 +47,110 @@ uint8_t amsReset() {
|
||||
amsStopBalancing();
|
||||
amsConfigOverUnderVoltage(DEFAULT_OV, DEFAULT_UV);
|
||||
|
||||
CHECK_RETURN(writeCMD(CLRFLAG, buffer, 6)); //clear flags,
|
||||
CHECK_RETURN(writeCMD(CLOVUV, buffer, 6)); //OVUV flags
|
||||
CHECK_RETURN(writeCMD(ADCV | ADCV_CONT | ADCV_RD, NULL, 0)); //start continuous cell voltage measurement with redundancy
|
||||
CHECK_RETURN(writeCMD(ADAX | ADAX_CONV_ALL, NULL, 0)); //start aux measurement
|
||||
uint8_t flagsbuffer[CMD_BUFFER_SIZE(6)] = {[0 ... CMD_BUFFER_SIZE(6) - 1] = 0xFF}; //technically not all 6 bytes are used, but it's easier to just set all to 0xFF
|
||||
//see page 27 of the datasheet for the memory map
|
||||
|
||||
CHECK_RETURN(writeCMD(CLRFLAG, flagsbuffer, 6)); //clear flags,
|
||||
CHECK_RETURN(writeCMD(CLOVUV, flagsbuffer, 6)); //OVUV flags
|
||||
CHECK_RETURN(writeCMD(ADCV | ADCV_CONT | ADCV_RD, flagsbuffer, 0)); //start continuous cell voltage measurement with redundancy
|
||||
CHECK_RETURN(writeCMD(ADAX | ADAX_CONV_ALL, flagsbuffer, 0)); //start aux measurement
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t initAMS(SPI_HandleTypeDef* hspi) {
|
||||
HAL_StatusTypeDef initAMS(SPI_HandleTypeDef* hspi) {
|
||||
adbmsDriverInit(hspi);
|
||||
return amsReset();
|
||||
}
|
||||
|
||||
uint8_t amsWakeUp() {
|
||||
HAL_StatusTypeDef amsWakeUp() {
|
||||
uint8_t buffer[CMD_BUFFER_SIZE(CFG_GROUP_A_SIZE)] = {0};
|
||||
return readCMD(RDCFGA, buffer, CMD_BUFFER_SIZE(CFG_GROUP_A_SIZE));
|
||||
}
|
||||
|
||||
uint8_t amsCellMeasurement(Cell_Module* module) {
|
||||
HAL_StatusTypeDef amsCellMeasurement(Cell_Module* module) {
|
||||
#warning check conversion counter to ensure that continous conversion has not been stopped
|
||||
#warning check for OW conditions: ADSV | ADSV_OW_0 / ADSV_OW_1
|
||||
return amsReadCellVoltages(module);
|
||||
}
|
||||
|
||||
uint8_t amsAuxAndStatusMeasurement(Cell_Module* module) {
|
||||
uint8_t rxbuf[AUX_GROUP_A_SIZE] = {};
|
||||
HAL_StatusTypeDef amsAuxAndStatusMeasurement(Cell_Module * module[static N_BMS]) {
|
||||
uint8_t rxbuf[CMD_BUFFER_SIZE(STATUS_GROUP_C_SIZE)] = {};
|
||||
|
||||
CHECK_RETURN(readCMD(RDSTATC, rxbuf, STATUS_GROUP_C_SIZE));
|
||||
|
||||
module->status.CS_FLT = rxbuf[0] | (rxbuf[1] << 8);
|
||||
module->status.CCTS = rxbuf[2] | (rxbuf[3] << 8);
|
||||
module->status.VA_OV = (rxbuf[4] >> 7) & 0x01;
|
||||
module->status.VA_UV = (rxbuf[4] >> 6) & 0x01;
|
||||
module->status.VD_OV = (rxbuf[4] >> 5) & 0x01;
|
||||
module->status.VD_UV = (rxbuf[4] >> 4) & 0x01;
|
||||
module->status.CED = (rxbuf[4] >> 3) & 0x01;
|
||||
module->status.CMED = (rxbuf[4] >> 2) & 0x01;
|
||||
module->status.SED = (rxbuf[4] >> 1) & 0x01;
|
||||
module->status.SMED = (rxbuf[4] >> 0) & 0x01;
|
||||
module->status.VDEL = (rxbuf[5] >> 7) & 0x01;
|
||||
module->status.VDE = (rxbuf[5] >> 6) & 0x01;
|
||||
module->status.COMPARE= (rxbuf[5] >> 5) & 0x01;
|
||||
module->status.SPIFLT = (rxbuf[5] >> 4) & 0x01;
|
||||
module->status.SLEEP = (rxbuf[5] >> 3) & 0x01;
|
||||
module->status.THSD = (rxbuf[5] >> 2) & 0x01;
|
||||
module->status.TMODCHK= (rxbuf[5] >> 1) & 0x01;
|
||||
module->status.OSCCHK = (rxbuf[5] >> 0) & 0x01;
|
||||
|
||||
if (pollCMD(PLAUX) == 0x0) { //TODO: check for SPI fault
|
||||
return 0; // aux ADC data not ready
|
||||
CHECK_RETURN(readCMD(RDSTATC, rxbuf, sizeof rxbuf));
|
||||
for (size_t i = 0; i < N_BMS; i++) {
|
||||
size_t offset = BUFFER_BMS_OFFSET(i, STATUS_GROUP_C_SIZE);
|
||||
module[i]->status.CS_FLT = rxbuf[offset + 0] | (rxbuf[offset + 1] << 8);
|
||||
module[i]->status.CCTS = rxbuf[offset + 2] | (rxbuf[offset + 3] << 8);
|
||||
module[i]->status.VA_OV = (rxbuf[offset + 4] >> 7) & 0x01;
|
||||
module[i]->status.VA_UV = (rxbuf[offset + 4] >> 6) & 0x01;
|
||||
module[i]->status.VD_OV = (rxbuf[offset + 4] >> 5) & 0x01;
|
||||
module[i]->status.VD_UV = (rxbuf[offset + 4] >> 4) & 0x01;
|
||||
module[i]->status.CED = (rxbuf[offset + 4] >> 3) & 0x01;
|
||||
module[i]->status.CMED = (rxbuf[offset + 4] >> 2) & 0x01;
|
||||
module[i]->status.SED = (rxbuf[offset + 4] >> 1) & 0x01;
|
||||
module[i]->status.SMED = (rxbuf[offset + 4] >> 0) & 0x01;
|
||||
module[i]->status.VDEL = (rxbuf[offset + 5] >> 7) & 0x01;
|
||||
module[i]->status.VDE = (rxbuf[offset + 5] >> 6) & 0x01;
|
||||
module[i]->status.COMPARE= (rxbuf[offset + 5] >> 5) & 0x01;
|
||||
module[i]->status.SPIFLT = (rxbuf[offset + 5] >> 4) & 0x01;
|
||||
module[i]->status.SLEEP = (rxbuf[offset + 5] >> 3) & 0x01;
|
||||
module[i]->status.THSD = (rxbuf[offset + 5] >> 2) & 0x01;
|
||||
module[i]->status.TMODCHK= (rxbuf[offset + 5] >> 1) & 0x01;
|
||||
module[i]->status.OSCCHK = (rxbuf[offset + 5] >> 0) & 0x01;
|
||||
}
|
||||
|
||||
CHECK_RETURN(readCMD(RDAUXA, rxbuf, AUX_GROUP_A_SIZE));
|
||||
if (pollCMD(PLAUX) == HAL_BUSY) {
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
module->auxVoltages[0] = mV_from_ADBMS6830(rxbuf[0] | (rxbuf[1] << 8));
|
||||
module->auxVoltages[1] = mV_from_ADBMS6830(rxbuf[2] | (rxbuf[3] << 8));
|
||||
module->auxVoltages[2] = mV_from_ADBMS6830(rxbuf[4] | (rxbuf[5] << 8));
|
||||
CHECK_RETURN(readCMD(RDAUXA, rxbuf, CMD_BUFFER_SIZE(AUX_GROUP_A_SIZE))); //STATUS_GROUP_C_SIZE is the same as AUX_GROUP_A_SIZE, so we can reuse the buffer
|
||||
for (size_t i = 0; i < N_BMS; i++) {
|
||||
size_t offset = BUFFER_BMS_OFFSET(i, AUX_GROUP_A_SIZE);
|
||||
module[i]->auxVoltages[0] = mV_from_ADBMS6830(rxbuf[offset + 0] | (rxbuf[offset + 1] << 8));
|
||||
module[i]->auxVoltages[1] = mV_from_ADBMS6830(rxbuf[offset + 2] | (rxbuf[offset + 3] << 8));
|
||||
module[i]->auxVoltages[2] = mV_from_ADBMS6830(rxbuf[offset + 4] | (rxbuf[offset + 5] << 8));
|
||||
}
|
||||
|
||||
CHECK_RETURN(readCMD(RDAUXB, rxbuf, AUX_GROUP_A_SIZE));
|
||||
CHECK_RETURN(readCMD(RDAUXB, rxbuf, CMD_BUFFER_SIZE(AUX_GROUP_B_SIZE)));
|
||||
for (size_t i = 0; i < N_BMS; i++) {
|
||||
size_t offset = BUFFER_BMS_OFFSET(i, AUX_GROUP_B_SIZE);
|
||||
module[i]->auxVoltages[3] = mV_from_ADBMS6830(rxbuf[offset + 0] | (rxbuf[offset + 1] << 8));
|
||||
module[i]->auxVoltages[4] = mV_from_ADBMS6830(rxbuf[offset + 2] | (rxbuf[offset + 3] << 8));
|
||||
module[i]->auxVoltages[5] = mV_from_ADBMS6830(rxbuf[offset + 4] | (rxbuf[offset + 5] << 8));
|
||||
}
|
||||
|
||||
module->auxVoltages[3] = mV_from_ADBMS6830(rxbuf[0] | (rxbuf[1] << 8));
|
||||
module->auxVoltages[4] = mV_from_ADBMS6830(rxbuf[2] | (rxbuf[3] << 8));
|
||||
module->auxVoltages[5] = mV_from_ADBMS6830(rxbuf[4] | (rxbuf[5] << 8));
|
||||
CHECK_RETURN(readCMD(RDAUXC, rxbuf, CMD_BUFFER_SIZE(AUX_GROUP_C_SIZE)));
|
||||
for (size_t i = 0; i < N_BMS; i++) {
|
||||
size_t offset = BUFFER_BMS_OFFSET(i, AUX_GROUP_C_SIZE);
|
||||
module[i]->auxVoltages[6] = mV_from_ADBMS6830(rxbuf[offset + 0] | (rxbuf[offset + 1] << 8));
|
||||
module[i]->auxVoltages[7] = mV_from_ADBMS6830(rxbuf[offset + 2] | (rxbuf[offset + 3] << 8));
|
||||
module[i]->auxVoltages[8] = mV_from_ADBMS6830(rxbuf[offset + 4] | (rxbuf[offset + 5] << 8));
|
||||
}
|
||||
|
||||
CHECK_RETURN(readCMD(RDAUXC, rxbuf, AUX_GROUP_A_SIZE));
|
||||
CHECK_RETURN(readCMD(RDAUXD, rxbuf, CMD_BUFFER_SIZE(AUX_GROUP_D_SIZE)));
|
||||
for (size_t i = 0; i < N_BMS; i++) {
|
||||
size_t offset = BUFFER_BMS_OFFSET(i, AUX_GROUP_D_SIZE);
|
||||
module[i]->auxVoltages[9] = mV_from_ADBMS6830(rxbuf[offset + 0] | (rxbuf[offset + 1] << 8));
|
||||
}
|
||||
|
||||
module->auxVoltages[6] = mV_from_ADBMS6830(rxbuf[0] | (rxbuf[1] << 8));
|
||||
module->auxVoltages[7] = mV_from_ADBMS6830(rxbuf[2] | (rxbuf[3] << 8));
|
||||
module->auxVoltages[8] = mV_from_ADBMS6830(rxbuf[4] | (rxbuf[5] << 8));
|
||||
CHECK_RETURN(readCMD(RDSTATA, rxbuf, CMD_BUFFER_SIZE(STATUS_GROUP_A_SIZE)));
|
||||
for (size_t i = 0; i < N_BMS; i++) {
|
||||
size_t offset = BUFFER_BMS_OFFSET(i, STATUS_GROUP_A_SIZE);
|
||||
module[i]->internalDieTemp = rxbuf[offset + 2] | (rxbuf[offset + 3] << 8);
|
||||
}
|
||||
|
||||
CHECK_RETURN(readCMD(RDAUXD, rxbuf, AUX_GROUP_A_SIZE));
|
||||
CHECK_RETURN(readCMD(RDSTATB, rxbuf, CMD_BUFFER_SIZE(STATUS_GROUP_B_SIZE)));
|
||||
for (size_t i = 0; i < N_BMS; i++) {
|
||||
size_t offset = BUFFER_BMS_OFFSET(i, STATUS_GROUP_B_SIZE);
|
||||
module[i]->digitalSupplyVoltage = mV_from_ADBMS6830(rxbuf[offset + 0] | (rxbuf[offset + 1] << 8));
|
||||
module[i]->analogSupplyVoltage = mV_from_ADBMS6830(rxbuf[offset + 2] | (rxbuf[offset + 3] << 8));
|
||||
module[i]->refVoltage = mV_from_ADBMS6830(rxbuf[offset + 4] | (rxbuf[offset + 5] << 8));
|
||||
}
|
||||
|
||||
module->auxVoltages[9] = mV_from_ADBMS6830(rxbuf[0] | (rxbuf[1] << 8));
|
||||
CHECK_RETURN(writeCMD(ADAX | ADAX_CONV_ALL, rxbuf, 0)); //start aux conversion for next iteration
|
||||
|
||||
uint8_t rxbuffer[STATUS_GROUP_A_SIZE];
|
||||
|
||||
CHECK_RETURN(readCMD(RDSTATA, rxbuffer, STATUS_GROUP_A_SIZE));
|
||||
|
||||
module->internalDieTemp = rxbuffer[2] | (rxbuffer[3] << 8);
|
||||
|
||||
CHECK_RETURN(readCMD(RDSTATB, rxbuffer, STATUS_GROUP_B_SIZE));
|
||||
module->digitalSupplyVoltage = mV_from_ADBMS6830(rxbuffer[0] | (rxbuffer[1] << 8));
|
||||
module->analogSupplyVoltage = mV_from_ADBMS6830(rxbuffer[2] | (rxbuffer[3] << 8));
|
||||
module->refVoltage = mV_from_ADBMS6830(rxbuffer[4] | (rxbuffer[5] << 8));
|
||||
|
||||
CHECK_RETURN(writeCMD(ADAX | ADAX_CONV_ALL, NULL, 0)); //start aux measurement for next cycle
|
||||
|
||||
return 0;
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
uint8_t amsConfigBalancing(uint32_t channels, uint8_t dutyCycle) {
|
||||
|
@ -331,23 +331,21 @@ HAL_StatusTypeDef readCMD(uint16_t command, uint8_t * buffer, size_t buflen) {
|
||||
}
|
||||
|
||||
//check poll command - no data PEC sent back
|
||||
uint8_t pollCMD(uint16_t command) {
|
||||
uint8_t txbuffer[5] = {};
|
||||
uint8_t rxbuffer[5] = {};
|
||||
HAL_StatusTypeDef pollCMD(uint16_t command) {
|
||||
uint8_t buffer[4 + (N_BMS * 2) + 1] = {}; //poll is only valid after 2 * N_BMS clock cycles (datasheet page 55)
|
||||
//being conservative and adding 1 byte for the poll response
|
||||
|
||||
txbuffer[0] = (command >> 8) & 0xFF;
|
||||
txbuffer[1] = (command)&0xFF;
|
||||
calculateCommandPEC(txbuffer, 4);
|
||||
buffer[0] = (command >> 8) & 0xFF;
|
||||
buffer[1] = (command) & 0xFF;
|
||||
calculateCommandPEC(buffer, 4);
|
||||
|
||||
mcuAdbmsCSLow();
|
||||
uint8_t status = mcuSPITransmitReceive(rxbuffer, txbuffer, 5);
|
||||
HAL_StatusTypeDef status = mcuSPITransmitReceive(buffer, buffer, 4 + (N_BMS * 2) + 1);
|
||||
mcuAdbmsCSHigh();
|
||||
|
||||
if (status != 0) {
|
||||
return status;
|
||||
}
|
||||
if (status != HAL_OK) return status;
|
||||
|
||||
return rxbuffer[4]; //last byte will be poll response
|
||||
return ((buffer[4 + (N_BMS * 2)] & 0x0F) == 0x0) ? HAL_BUSY : HAL_OK; //SDO goes high when data is ready
|
||||
}
|
||||
|
||||
void mcuAdbmsCSLow() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user