Compare commits
10 Commits
1322a7e8b0
...
e45c1c2878
Author | SHA1 | Date | |
---|---|---|---|
e45c1c2878 | |||
48a06b87ae | |||
44c012082b | |||
11a2121fd8 | |||
6145508e8b | |||
c9c9ac06d3 | |||
c7be10b37f | |||
4dda2084a3 | |||
ae54db62e0 | |||
8a82ad4cee |
1
AMS_Master_Code/.vscode/launch.json
vendored
1
AMS_Master_Code/.vscode/launch.json
vendored
@ -40,7 +40,6 @@
|
|||||||
"request": "attach",
|
"request": "attach",
|
||||||
"type": "cortex-debug",
|
"type": "cortex-debug",
|
||||||
"servertype": "openocd",
|
"servertype": "openocd",
|
||||||
"preLaunchTask": "Build STM",
|
|
||||||
"device": "stm32h7a3xxq.s",
|
"device": "stm32h7a3xxq.s",
|
||||||
"configFiles": [
|
"configFiles": [
|
||||||
"openocd.cfg"
|
"openocd.cfg"
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#define USE_CALC
|
#define USE_CALC
|
||||||
|
|
||||||
@ -18,10 +19,10 @@
|
|||||||
// With R_T/R_0 and R_0 = R_T@25C
|
// With R_T/R_0 and R_0 = R_T@25C
|
||||||
// R_T/R_0 = 1 / V_REF / ADC - 1
|
// R_T/R_0 = 1 / V_REF / ADC - 1
|
||||||
|
|
||||||
|
[[gnu::optimize("fast-math")]]
|
||||||
static inline uint16_t ntc_mv_to_celsius(int16_t adc) {
|
static inline uint16_t ntc_mv_to_celsius(int16_t adc) {
|
||||||
float log_ohms = logf(1/((VREF/adc)-1));
|
float log_ohms = logf(1 / ((VREF / adc) - 1));
|
||||||
return (uint16_t) (TEMP_CONV / (NTC_A1 + NTC_B1 * log_ohms + NTC_C1 * log_ohms * log_ohms + NTC_D1 * log_ohms * log_ohms * log_ohms) - CELSIUS_TO_KELVIN_SCALED);
|
return (uint16_t) (TEMP_CONV / (NTC_A1 + NTC_B1 * log_ohms + NTC_C1 * log_ohms * log_ohms + NTC_D1 * log_ohms * log_ohms * log_ohms) - CELSIUS_TO_KELVIN_SCALED);
|
||||||
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
// Lookup Table coming soon; not really needed but fun?
|
// Lookup Table coming soon; not really needed but fun?
|
||||||
|
@ -4,13 +4,17 @@
|
|||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
|
||||||
#define N_BMS 1
|
#define N_BMS 1
|
||||||
#define ADBMS_SPI_TIMEOUT 100 // Timeout in ms
|
#define N_CELLS 16
|
||||||
|
#define ADBMS_MAX_CHIP_TEMP 110 // max temperature of ADBMS6830B (not battery) in C
|
||||||
|
#define ADBMS_SPI_TIMEOUT 50 // Timeout in ms
|
||||||
|
|
||||||
[[maybe_unused]] static inline void mcuAdbmsCSLow() {
|
[[maybe_unused, gnu::always_inline]]
|
||||||
|
static inline void mcuAdbmsCSLow() {
|
||||||
HAL_GPIO_WritePin(AMS_CS_GPIO_Port, AMS_CS_Pin, GPIO_PIN_RESET);
|
HAL_GPIO_WritePin(AMS_CS_GPIO_Port, AMS_CS_Pin, GPIO_PIN_RESET);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[maybe_unused]] static inline void mcuAdbmsCSHigh() {
|
[[maybe_unused, gnu::always_inline]]
|
||||||
|
static inline void mcuAdbmsCSHigh() {
|
||||||
HAL_GPIO_WritePin(AMS_CS_GPIO_Port, AMS_CS_Pin, GPIO_PIN_SET);
|
HAL_GPIO_WritePin(AMS_CS_GPIO_Port, AMS_CS_Pin, GPIO_PIN_SET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,8 +93,7 @@ static inline void __swo_print(unsigned int channel, const char *str) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[[maybe_unused]]
|
static inline void debug_clear_console() {
|
||||||
static void debug_clear_console() {
|
|
||||||
for (int i = 0; i < LOG_LEVEL_NOISY; i++) {
|
for (int i = 0; i < LOG_LEVEL_NOISY; i++) {
|
||||||
#if USE_ANSI_ESCAPE_CODES
|
#if USE_ANSI_ESCAPE_CODES
|
||||||
__swo_print(i, "\033[2J\033[;H"); // clear screen
|
__swo_print(i, "\033[2J\033[;H"); // clear screen
|
||||||
@ -104,44 +103,58 @@ static void debug_clear_console() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define debug_log(level, msg, ...) \
|
[[gnu::format(printf, 2, 3)]]
|
||||||
do { \
|
static inline void debug_log(enum log_level_t level, const char *msg, ...) {
|
||||||
if (DEBUG_CHANNEL_ENABLED(level)) { \
|
if (!DEBUG_CHANNEL_ENABLED(level)) {
|
||||||
char __swo_buffer[MAX_MESSAGE_LENGTH]; \
|
return;
|
||||||
size_t len = \
|
}
|
||||||
snprintf(__swo_buffer, sizeof(__swo_buffer), msg, ##__VA_ARGS__); \
|
|
||||||
__swo_putc('\n', level); \
|
char __swo_buffer[MAX_MESSAGE_LENGTH];
|
||||||
/* Print timestamp if enabled */ \
|
va_list args;
|
||||||
if (PRINT_TIMESTAMP) { \
|
va_start(args, msg);
|
||||||
char __time_buffer[16]; \
|
size_t len = vsnprintf(__swo_buffer, sizeof(__swo_buffer), msg, args);
|
||||||
if (USE_ANSI_ESCAPE_CODES) { \
|
va_end(args);
|
||||||
snprintf(__time_buffer, sizeof(__time_buffer), \
|
|
||||||
"\033[90m[%lu]\033[0m ", HAL_GetTick()); \
|
__swo_putc('\n', level);
|
||||||
} else { \
|
|
||||||
snprintf(__time_buffer, sizeof(__time_buffer), "[%lu] ", \
|
/* Print timestamp if enabled */
|
||||||
HAL_GetTick()); \
|
if (PRINT_TIMESTAMP) {
|
||||||
} \
|
char __time_buffer[16];
|
||||||
__swo_print(level, __time_buffer); \
|
if (USE_ANSI_ESCAPE_CODES) {
|
||||||
} \
|
snprintf(__time_buffer, sizeof(__time_buffer),
|
||||||
__swo_print(level, log_level_names[level]); \
|
"\033[90m[%lu]\033[0m ", HAL_GetTick());
|
||||||
__swo_print(level, __swo_buffer); \
|
} else {
|
||||||
if (len >= sizeof(__swo_buffer)) { \
|
snprintf(__time_buffer, sizeof(__time_buffer), "[%lu] ",
|
||||||
__swo_print(level, " [message length exceeded] "); \
|
HAL_GetTick());
|
||||||
} \
|
}
|
||||||
} \
|
__swo_print(level, __time_buffer);
|
||||||
} while (0)
|
}
|
||||||
|
|
||||||
|
__swo_print(level, log_level_names[level]);
|
||||||
|
__swo_print(level, __swo_buffer);
|
||||||
|
|
||||||
|
if (len >= sizeof(__swo_buffer)) {
|
||||||
|
__swo_print(level, " [message length exceeded] ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#define debug_log_cont(level, msg, ...) \
|
[[gnu::format(printf, 2, 3)]]
|
||||||
do { \
|
static inline void debug_log_cont(enum log_level_t level, const char *msg, ...) {
|
||||||
if (DEBUG_CHANNEL_ENABLED(level)) { \
|
if (!DEBUG_CHANNEL_ENABLED(level)) {
|
||||||
char __swo_buffer[MAX_MESSAGE_LENGTH]; \
|
return;
|
||||||
size_t len = \
|
}
|
||||||
snprintf(__swo_buffer, sizeof(__swo_buffer), msg, ##__VA_ARGS__); \
|
|
||||||
__swo_print(level, __swo_buffer); \
|
char __swo_buffer[MAX_MESSAGE_LENGTH];
|
||||||
if (len >= sizeof(__swo_buffer)) { \
|
va_list args;
|
||||||
__swo_print(level, " [message length exceeded] "); \
|
va_start(args, msg);
|
||||||
} \
|
size_t len = vsnprintf(__swo_buffer, sizeof(__swo_buffer), msg, args);
|
||||||
} \
|
va_end(args);
|
||||||
} while (0)
|
|
||||||
|
__swo_print(level, __swo_buffer);
|
||||||
|
|
||||||
|
if (len >= sizeof(__swo_buffer)) {
|
||||||
|
__swo_print(level, " [message length exceeded] ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* __SWO_LOG_H */
|
#endif /* __SWO_LOG_H */
|
||||||
|
@ -8,10 +8,7 @@
|
|||||||
#ifndef INC_ADBMS_ABSTRACTION_H_
|
#ifndef INC_ADBMS_ABSTRACTION_H_
|
||||||
#define INC_ADBMS_ABSTRACTION_H_
|
#define INC_ADBMS_ABSTRACTION_H_
|
||||||
|
|
||||||
#include "ADBMS_CMD_MAKROS.h"
|
|
||||||
#include "ADBMS_Driver.h"
|
#include "ADBMS_Driver.h"
|
||||||
#include "ADBMS_LL_Driver.h"
|
|
||||||
#include "main.h"
|
|
||||||
|
|
||||||
#define mV_from_ADBMS6830(x) (((((int16_t)(x))) * 0.150) + 1500)
|
#define mV_from_ADBMS6830(x) (((((int16_t)(x))) * 0.150) + 1500)
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ typedef struct {
|
|||||||
uint32_t bmsID;
|
uint32_t bmsID;
|
||||||
|
|
||||||
struct ADBMS6830_Internal_Status status;
|
struct ADBMS6830_Internal_Status status;
|
||||||
uint16_t internalDieTemp;
|
int16_t internalDieTemp;
|
||||||
uint16_t analogSupplyVoltage;
|
uint16_t analogSupplyVoltage;
|
||||||
uint16_t digitalSupplyVoltage;
|
uint16_t digitalSupplyVoltage;
|
||||||
uint16_t sumOfCellMeasurements;
|
uint16_t sumOfCellMeasurements;
|
||||||
|
@ -30,6 +30,4 @@ extern Cell_Module modules[N_BMS];
|
|||||||
extern uint32_t balancedCells;
|
extern uint32_t balancedCells;
|
||||||
extern bool BalancingActive;
|
extern bool BalancingActive;
|
||||||
|
|
||||||
extern uint8_t numberofCells;
|
|
||||||
|
|
||||||
#endif /* INC_AMS_HIGHLEVEL_H_ */
|
#endif /* INC_AMS_HIGHLEVEL_H_ */
|
||||||
|
@ -9,9 +9,7 @@
|
|||||||
#define ADBMS_LL_DRIVER_H_
|
#define ADBMS_LL_DRIVER_H_
|
||||||
|
|
||||||
#include "config_ADBMS6830.h"
|
#include "config_ADBMS6830.h"
|
||||||
#include "stm32h7xx_hal.h"
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#define TARGET_STM32
|
|
||||||
|
|
||||||
|
|
||||||
uint8_t adbmsDriverInit(SPI_HandleTypeDef* hspi);
|
uint8_t adbmsDriverInit(SPI_HandleTypeDef* hspi);
|
||||||
|
@ -13,8 +13,6 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include "NTC.h"
|
#include "NTC.h"
|
||||||
|
|
||||||
extern uint8_t numberofCells;
|
|
||||||
|
|
||||||
static const char* const HAL_Statuses[] = {"HAL_OK", "HAL_ERROR", "HAL_BUSY", "HAL_TIMEOUT"};
|
static const char* const HAL_Statuses[] = {"HAL_OK", "HAL_ERROR", "HAL_BUSY", "HAL_TIMEOUT"};
|
||||||
|
|
||||||
#define CHECK_RETURN(x) \
|
#define CHECK_RETURN(x) \
|
||||||
@ -91,8 +89,7 @@ HAL_StatusTypeDef initAMS(SPI_HandleTypeDef* hspi) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
HAL_StatusTypeDef amsWakeUp() {
|
HAL_StatusTypeDef amsWakeUp() {
|
||||||
uint8_t buffer[CMD_BUFFER_SIZE(CFG_GROUP_A_SIZE)] = {0};
|
return __pollCMD(PLADC, 100); //wake up ADBMS6830, wait for T_wake = 200 us (100 cycles at 500 kHz)
|
||||||
return readCMD(RDCFGA, buffer, CFG_GROUP_A_SIZE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HAL_StatusTypeDef amsCellMeasurement(Cell_Module (*module)[N_BMS]) {
|
HAL_StatusTypeDef amsCellMeasurement(Cell_Module (*module)[N_BMS]) {
|
||||||
@ -264,8 +261,7 @@ HAL_StatusTypeDef amsCheckUnderOverVoltage(Cell_Module (*module)[N_BMS]) {
|
|||||||
(*module)[i].overVoltage = 0;
|
(*module)[i].overVoltage = 0;
|
||||||
(*module)[i].underVoltage = 0;
|
(*module)[i].underVoltage = 0;
|
||||||
|
|
||||||
for (size_t j = 0; j < numberofCells;
|
for (size_t j = 0; j < N_CELLS; j++) { // ov/uv flags are 1-bit flags for each cell C0UV, C0OV, C1UV, C1OV, ...
|
||||||
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].underVoltage |= (ov_uv_data >> (j * 2)) & 0x01;
|
||||||
(*module)[i].overVoltage |= (ov_uv_data >> (j * 2 + 1)) & 0x01;
|
(*module)[i].overVoltage |= (ov_uv_data >> (j * 2 + 1)) & 0x01;
|
||||||
}
|
}
|
||||||
|
@ -18,8 +18,6 @@ Cell_Module modules[N_BMS] = {};
|
|||||||
uint32_t balancedCells = 0;
|
uint32_t balancedCells = 0;
|
||||||
bool balancingActive = false;
|
bool balancingActive = false;
|
||||||
|
|
||||||
uint8_t numberofCells = 16;
|
|
||||||
|
|
||||||
uint8_t packetChecksumFails = 0;
|
uint8_t packetChecksumFails = 0;
|
||||||
#define MAX_PACKET_CHECKSUM_FAILS 5
|
#define MAX_PACKET_CHECKSUM_FAILS 5
|
||||||
|
|
||||||
@ -37,7 +35,7 @@ static constexpr ADBMS_DetailedStatus NO_ERROR = {ADBMS_NO_ERROR};
|
|||||||
|
|
||||||
ADBMS_DetailedStatus AMS_Init(SPI_HandleTypeDef* hspi) {
|
ADBMS_DetailedStatus AMS_Init(SPI_HandleTypeDef* hspi) {
|
||||||
debug_log(LOG_LEVEL_INFO, "ADBMS6830B HAL - configured for %d controllers and %d cells per controller...", N_BMS,
|
debug_log(LOG_LEVEL_INFO, "ADBMS6830B HAL - configured for %d controllers and %d cells per controller...", N_BMS,
|
||||||
numberofCells);
|
N_CELLS);
|
||||||
if (initAMS(hspi) != HAL_OK) {
|
if (initAMS(hspi) != HAL_OK) {
|
||||||
debug_log(LOG_LEVEL_ERROR, "ADBMS6830B HAL - initialization failed");
|
debug_log(LOG_LEVEL_ERROR, "ADBMS6830B HAL - initialization failed");
|
||||||
return (ADBMS_DetailedStatus){ADBMS_INTERNAL_BMS_FAULT, -1};
|
return (ADBMS_DetailedStatus){ADBMS_INTERNAL_BMS_FAULT, -1};
|
||||||
@ -106,8 +104,7 @@ ADBMS_DetailedStatus AMS_Idle_Loop() {
|
|||||||
return (ADBMS_DetailedStatus){ADBMS_UNDERVOLT, match - 1};
|
return (ADBMS_DetailedStatus){ADBMS_UNDERVOLT, match - 1};
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: replace with the correct threshold for the internal die temperature
|
if ((match = any(module.internalDieTemp > ADBMS_MAX_CHIP_TEMP || module.status.THSD))) {
|
||||||
if ((match = any(module.internalDieTemp > 28000 || module.status.THSD))) {
|
|
||||||
return (ADBMS_DetailedStatus){ADBMS_INTERNAL_BMS_OVERTEMP, match - 1};
|
return (ADBMS_DetailedStatus){ADBMS_INTERNAL_BMS_OVERTEMP, match - 1};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,13 @@
|
|||||||
#define INITIAL_COMMAND_PEC 0x0010
|
#define INITIAL_COMMAND_PEC 0x0010
|
||||||
#define INITIAL_DATA_PEC 0x0010
|
#define INITIAL_DATA_PEC 0x0010
|
||||||
|
|
||||||
|
// CRC polynomial constants
|
||||||
|
#define CRC15_POLY 0xC599
|
||||||
|
#define CRC10_POLY 0x8F
|
||||||
|
#define CRC15_REMAINDER_MASK 0x4000
|
||||||
|
#define CRC10_REMAINDER_MASK 0x200
|
||||||
|
#define CRC10_RESULT_MASK 0x3FF
|
||||||
|
|
||||||
SPI_HandleTypeDef* adbmsspi;
|
SPI_HandleTypeDef* adbmsspi;
|
||||||
|
|
||||||
uint8_t adbmsDriverInit(SPI_HandleTypeDef* hspi) {
|
uint8_t adbmsDriverInit(SPI_HandleTypeDef* hspi) {
|
||||||
@ -49,8 +56,8 @@ static uint16_t computeCRC15(const uint8_t* data, size_t length) {
|
|||||||
for (size_t i = 0; i < length; i++) {
|
for (size_t i = 0; i < length; i++) {
|
||||||
remainder ^= (data[i] << 7);
|
remainder ^= (data[i] << 7);
|
||||||
for (int b = 0; b < 8; b++) {
|
for (int b = 0; b < 8; b++) {
|
||||||
if (remainder & 0x4000) {
|
if (remainder & CRC15_REMAINDER_MASK) {
|
||||||
remainder = (uint16_t)((remainder << 1) ^ 0xC599);
|
remainder = (uint16_t)((remainder << 1) ^ CRC15_POLY);
|
||||||
} else {
|
} else {
|
||||||
remainder <<= 1;
|
remainder <<= 1;
|
||||||
}
|
}
|
||||||
@ -81,13 +88,12 @@ static uint8_t checkCommandPEC(uint8_t* data, uint8_t datalen) {
|
|||||||
|
|
||||||
static uint16_t computeCRC10(const uint8_t* data, size_t length, bool rx_cmd) {
|
static uint16_t computeCRC10(const uint8_t* data, size_t length, bool rx_cmd) {
|
||||||
uint16_t remainder = INITIAL_DATA_PEC;
|
uint16_t remainder = INITIAL_DATA_PEC;
|
||||||
const uint16_t poly = 0x8F;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < length; i++) {
|
for (size_t i = 0; i < length; i++) {
|
||||||
remainder ^= (uint16_t)(data[i] << 2);
|
remainder ^= (uint16_t)(data[i] << 2);
|
||||||
for (int b = 0; b < 8; b++) {
|
for (int b = 0; b < 8; b++) {
|
||||||
if (remainder & 0x200) {
|
if (remainder & CRC10_REMAINDER_MASK) {
|
||||||
remainder = (uint16_t)((remainder << 1) ^ poly);
|
remainder = (uint16_t)((remainder << 1) ^ CRC10_POLY);
|
||||||
} else {
|
} else {
|
||||||
remainder <<= 1;
|
remainder <<= 1;
|
||||||
}
|
}
|
||||||
@ -98,14 +104,14 @@ static uint16_t computeCRC10(const uint8_t* data, size_t length, bool rx_cmd) {
|
|||||||
if (rx_cmd) {
|
if (rx_cmd) {
|
||||||
remainder ^= (uint16_t)((data[length] & 0xFC) << 2);
|
remainder ^= (uint16_t)((data[length] & 0xFC) << 2);
|
||||||
for (int b = 0; b < 6; b++) {
|
for (int b = 0; b < 6; b++) {
|
||||||
if (remainder & 0x200) {
|
if (remainder & CRC10_REMAINDER_MASK) {
|
||||||
remainder = (uint16_t)((remainder << 1) ^ poly);
|
remainder = (uint16_t)((remainder << 1) ^ CRC10_POLY);
|
||||||
} else {
|
} else {
|
||||||
remainder <<= 1;
|
remainder <<= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (uint16_t)(remainder & 0x3FF);
|
return (uint16_t)(remainder & CRC10_RESULT_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t calculateDataPEC(uint8_t* data, uint8_t datalen) {
|
static uint8_t calculateDataPEC(uint8_t* data, uint8_t datalen) {
|
||||||
@ -242,10 +248,27 @@ HAL_StatusTypeDef ___readCMD(uint16_t command, uint8_t * buffer, size_t arglen)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (arglen == 0) {
|
||||||
|
return HAL_OK; //no data to check
|
||||||
|
}
|
||||||
|
|
||||||
//check data PEC
|
//check data PEC
|
||||||
for (size_t i = 0; i < N_BMS; i++) {
|
for (size_t i = 0; i < N_BMS; i++) {
|
||||||
size_t offset = BUFFER_BMS_OFFSET(i, arglen);
|
size_t offset = BUFFER_BMS_OFFSET(i, arglen);
|
||||||
if (checkDataPEC(&buffer[offset], arglen + 2) != 0) {
|
if (checkDataPEC(&buffer[offset], arglen + 2) != 0) {
|
||||||
|
debug_log(LOG_LEVEL_ERROR, "Invalid data PEC when reading BMS %d", i);
|
||||||
|
debug_log(LOG_LEVEL_ERROR, "Received: ");
|
||||||
|
for (size_t j = 0; j < arglen + 2; j++) {
|
||||||
|
debug_log_cont(LOG_LEVEL_ERROR, "%02X ", buffer[offset + j]);
|
||||||
|
}
|
||||||
|
debug_log_cont(LOG_LEVEL_ERROR, "| %02X %02X ", buffer[offset + arglen], buffer[offset + arglen + 1]); //print out the DPEC
|
||||||
|
debug_log(LOG_LEVEL_ERROR, " DATA ^");
|
||||||
|
//print out spaces until start of DPEC
|
||||||
|
for (size_t j = 0; j < arglen - 1; j++) {
|
||||||
|
debug_log_cont(LOG_LEVEL_ERROR, (arglen < 2) ? "" : "^^^");
|
||||||
|
}
|
||||||
|
debug_log_cont(LOG_LEVEL_ERROR, "^^ ");
|
||||||
|
debug_log_cont(LOG_LEVEL_ERROR, " PEC ^");
|
||||||
return HAL_ERROR;
|
return HAL_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -271,5 +294,5 @@ HAL_StatusTypeDef __pollCMD(uint16_t command, uint8_t waitTime) {
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ((buffer[4 + (N_BMS * 2)] & 0x0F) == 0x0) ? HAL_BUSY : HAL_OK; //SDO goes high when data is ready
|
return ((buffer[sizeof buffer] & 0x0F) == 0x0) ? HAL_BUSY : HAL_OK; //SDO goes high when data is ready
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user