V1.4
This commit is contained in:
parent
e7b5054e02
commit
a4a856eb31
4
Core/Inc/ADBMS_Abstraction.h
Normal file → Executable file
4
Core/Inc/ADBMS_Abstraction.h
Normal file → Executable file
@ -46,8 +46,8 @@ struct ADBMS6830_Internal_Status {
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
float cellVoltages[MAXIMUM_CELL_VOLTAGES];
|
||||
float auxVoltages[MAXIMUM_AUX_VOLTAGES];
|
||||
int16_t cellVoltages[MAXIMUM_CELL_VOLTAGES];
|
||||
int16_t auxVoltages[MAXIMUM_AUX_VOLTAGES];
|
||||
|
||||
struct ADBMS6830_Internal_Status status;
|
||||
uint16 internalDieTemp;
|
||||
|
0
Core/Inc/ADBMS_CMD_MAKROS.h
Normal file → Executable file
0
Core/Inc/ADBMS_CMD_MAKROS.h
Normal file → Executable file
4
Core/Inc/ADBMS_LL_Driver.h
Normal file → Executable file
4
Core/Inc/ADBMS_LL_Driver.h
Normal file → Executable file
@ -27,8 +27,8 @@ uint8 calculateDataPEC(uint8* data, uint8 datalen);
|
||||
uint16 updateDataPEC(uint16 currentPEC, uint8 din);
|
||||
uint8 checkDataPEC(uint8* data, uint8 datalen);
|
||||
|
||||
uint8 writeCMD(uint16 command, uint8* args, uint8 arglen);
|
||||
uint8 readCMD(uint16 command, uint8* buffer, uint8 buflen);
|
||||
[[gnu::access(read_only, 2, 3)]] uint8 writeCMD(uint16 command, const uint8* args, uint8 arglen);
|
||||
[[gnu::access(write_only, 2, 3)]] uint8 readCMD(uint16 command, uint8* buffer, uint8 buflen);
|
||||
uint8 pollCMD(uint16 command);
|
||||
|
||||
void mcuAdbmsCSLow();
|
||||
|
17
Core/Inc/AMS_HighLevel.h
Normal file → Executable file
17
Core/Inc/AMS_HighLevel.h
Normal file → Executable file
@ -12,11 +12,8 @@
|
||||
#include "ADBMS_CMD_MAKROS.h"
|
||||
#include "ADBMS_LL_Driver.h"
|
||||
#include "can.h"
|
||||
#include "TMP1075.h"
|
||||
#include "can-halal.h"
|
||||
#include "errors.h"
|
||||
#include "stm32f3xx_hal.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef enum {
|
||||
AMSDEACTIVE,
|
||||
@ -31,11 +28,7 @@ typedef enum {
|
||||
extern amsState currentAMSState;
|
||||
extern Cell_Module module;
|
||||
extern uint32_t balancedCells;
|
||||
extern uint8_t BalancingActive;
|
||||
extern uint8_t stateofcharge;
|
||||
|
||||
extern uint8_t amserrorcode;
|
||||
extern uint8_t amswarningcode;
|
||||
extern bool BalancingActive;
|
||||
|
||||
extern uint8_t numberofCells;
|
||||
extern uint8_t numberofAux;
|
||||
@ -50,8 +43,4 @@ uint8_t AMS_Error_Loop();
|
||||
uint8_t AMS_Charging_Loop();
|
||||
uint8_t AMS_Discharging_Loop();
|
||||
|
||||
uint8_t writeWarningLog(uint8_t warningCode);
|
||||
uint8_t writeErrorLog(uint8_t errorCode);
|
||||
uint8_t integrateCurrent();
|
||||
|
||||
#endif /* INC_AMS_HIGHLEVEL_H_ */
|
||||
|
@ -1,3 +1,10 @@
|
||||
/*
|
||||
* PWM_control.h
|
||||
*
|
||||
* Created on: 07.07.2024
|
||||
* Author: Hamza
|
||||
*/
|
||||
|
||||
#ifndef INC_PWM_CONTROL_H
|
||||
#define INC_PWM_CONTROL_H
|
||||
|
||||
|
@ -1,3 +1,10 @@
|
||||
/*
|
||||
* can.h
|
||||
*
|
||||
* Created on: 07.07.2024
|
||||
* Author: Hamza
|
||||
*/
|
||||
|
||||
#ifndef INC_CAN_H
|
||||
#define INC_CAN_H
|
||||
|
||||
|
@ -1,3 +1,10 @@
|
||||
/*
|
||||
* state_machine.h
|
||||
*
|
||||
* Created on: 07.07.2024
|
||||
* Author: Hamza
|
||||
*/
|
||||
|
||||
#ifndef INC_STATE_MACHINE_H
|
||||
#define INC_STATE_MACHINE_H
|
||||
|
||||
@ -8,17 +15,12 @@
|
||||
#include "errors.h"
|
||||
#include "PWM_control.h"
|
||||
#include "TMP1075.h"
|
||||
#include <math.h>
|
||||
|
||||
// Minimum vehicle side voltage to exit precharge
|
||||
#define MIN_VEHICLE_SIDE_VOLTAGE 150000 // mV
|
||||
// Time to wait after reaching 95% of battery voltage before exiting precharge
|
||||
// Set this to 1000 in scruti to demonstrate the voltage on the multimeter
|
||||
#define PRECHARGE_DURATION 3000 // ms
|
||||
// Time to wait for discharge
|
||||
#define DISCHARGE_DURATION 3000 // ms
|
||||
// Time to wait after there is no more error condition before exiting TS_ERROR
|
||||
#define NO_ERROR_TIME 1000 // ms
|
||||
// Time to wait for charger voltage before going to TS_ERROR
|
||||
#define MAX_CHARGING_CHECK_DURATION 2000 // ms
|
||||
// Time to wait between closing relays
|
||||
@ -91,5 +93,6 @@ void sm_handle_ams_in(const uint8 *data);
|
||||
void sm_check_errors();
|
||||
void sm_set_error(ErrorKind error_kind, bool is_errored);
|
||||
void sm_test_cycle_states();
|
||||
void sm_error_source();
|
||||
|
||||
#endif /* "INC_STATE_MACHINE_H" */
|
16
Core/Src/ADBMS_Abstraction.c
Normal file → Executable file
16
Core/Src/ADBMS_Abstraction.c
Normal file → Executable file
@ -28,7 +28,7 @@ uint8 amsReset() {
|
||||
amsStopBalancing();
|
||||
amsConfigOverUnderVoltage(DEFAULT_OV, DEFAULT_UV);
|
||||
|
||||
uint8 buffer[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||
const uint8 buffer[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||
|
||||
CHECK_RETURN(writeCMD(CLRFLAG, buffer, 6)); //clear flags,
|
||||
CHECK_RETURN(writeCMD(CLOVUV, buffer, 6)); //OVUV flags
|
||||
@ -131,8 +131,8 @@ uint8 amsAuxAndStatusMeasurement(Cell_Module* module) {
|
||||
uint8 amsConfigBalancing(uint32 channels, uint8 dutyCycle) {
|
||||
uint8 buffer_a[PWM_GROUP_A_SIZE] = {};
|
||||
uint8 buffer_b[PWM_GROUP_B_SIZE] = {};
|
||||
CHECK_RETURN(readCMD(RDPWMA, buffer_a, CFG_GROUP_A_SIZE));
|
||||
CHECK_RETURN(readCMD(RDPWMB, buffer_b, CFG_GROUP_B_SIZE));
|
||||
CHECK_RETURN(readCMD(RDPWMA, buffer_a, PWM_GROUP_A_SIZE));
|
||||
CHECK_RETURN(readCMD(RDPWMB, buffer_b, PWM_GROUP_B_SIZE));
|
||||
|
||||
if (dutyCycle > 0x0F) { // there are only 4 bits for duty cycle
|
||||
return 1;
|
||||
@ -150,8 +150,8 @@ uint8 amsConfigBalancing(uint32 channels, uint8 dutyCycle) {
|
||||
}
|
||||
}
|
||||
|
||||
CHECK_RETURN(writeCMD(WRPWMA, buffer_a, CFG_GROUP_A_SIZE));
|
||||
CHECK_RETURN(writeCMD(WRPWMB, buffer_b, CFG_GROUP_B_SIZE));
|
||||
CHECK_RETURN(writeCMD(WRPWMA, buffer_a, PWM_GROUP_A_SIZE));
|
||||
CHECK_RETURN(writeCMD(WRPWMB, buffer_b, PWM_GROUP_B_SIZE));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -203,13 +203,11 @@ uint8 amsCheckUnderOverVoltage(Cell_Module* module) {
|
||||
}
|
||||
|
||||
uint8 amsClearAux() {
|
||||
uint8 buffer[6];
|
||||
return writeCMD(CLRAUX, buffer, 0);
|
||||
return writeCMD(CLRAUX, NULL, 0);
|
||||
}
|
||||
|
||||
uint8 amsClearCells() {
|
||||
uint8 buffer[6];
|
||||
return writeCMD(CLRCELL, buffer, 0);
|
||||
return writeCMD(CLRCELL, NULL, 0);
|
||||
}
|
||||
|
||||
uint8 amsReadCellVoltages(Cell_Module* module) {
|
||||
|
82
Core/Src/ADBMS_LL_Driver.c
Normal file → Executable file
82
Core/Src/ADBMS_LL_Driver.c
Normal file → Executable file
@ -6,11 +6,11 @@
|
||||
*/
|
||||
|
||||
#include "ADBMS_LL_Driver.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#define INITIAL_COMMAND_PEC 0x0010
|
||||
#define INITIAL_DATA_PEC 0x0010
|
||||
#define ADBMS_SPI_TIMEOUT 100 // Timeout in ms
|
||||
#warning ask about the timeout value
|
||||
|
||||
SPI_HandleTypeDef* adbmsspi;
|
||||
|
||||
@ -31,7 +31,7 @@ uint8 calculateCommandPEC(uint8_t* data, uint8_t datalen) {
|
||||
if (datalen >= 3) {
|
||||
for (int i = 0; i < (datalen - 2); i++) {
|
||||
for (int n = 0; n < 8; n++) {
|
||||
uint8 din = data[i] << (n);
|
||||
const uint8 din = data[i] << (n);
|
||||
currentpec = updateCommandPEC(currentpec, din);
|
||||
}
|
||||
}
|
||||
@ -53,13 +53,13 @@ uint8 checkCommandPEC(uint8* data, uint8 datalen) {
|
||||
|
||||
for (int i = 0; i < (datalen - 2); i++) {
|
||||
for (int n = 0; n < 8; n++) {
|
||||
uint8 din = data[i] << (n);
|
||||
const uint8 din = data[i] << (n);
|
||||
currentpec = updateCommandPEC(currentpec, din);
|
||||
}
|
||||
}
|
||||
|
||||
uint8 pechigh = (currentpec >> 7) & 0xFF;
|
||||
uint8 peclow = (currentpec << 1) & 0xFF;
|
||||
const uint8 pechigh = (currentpec >> 7) & 0xFF;
|
||||
const uint8 peclow = (currentpec << 1) & 0xFF;
|
||||
|
||||
if ((pechigh == data[datalen - 2]) && (peclow == data[datalen - 1])) {
|
||||
return 0;
|
||||
@ -70,13 +70,13 @@ uint8 checkCommandPEC(uint8* data, uint8 datalen) {
|
||||
|
||||
uint16 updateCommandPEC(uint16 currentPEC, uint8 din) {
|
||||
din = (din >> 7) & 0x01;
|
||||
uint8 in0 = din ^ ((currentPEC >> 14) & 0x01);
|
||||
uint8 in3 = in0 ^ ((currentPEC >> 2) & 0x01);
|
||||
uint8 in4 = in0 ^ ((currentPEC >> 3) & 0x01);
|
||||
uint8 in7 = in0 ^ ((currentPEC >> 6) & 0x01);
|
||||
uint8 in8 = in0 ^ ((currentPEC >> 7) & 0x01);
|
||||
uint8 in10 = in0 ^ ((currentPEC >> 9) & 0x01);
|
||||
uint8 in14 = in0 ^ ((currentPEC >> 13) & 0x01);
|
||||
const uint8 in0 = din ^ ((currentPEC >> 14) & 0x01);
|
||||
const uint8 in3 = in0 ^ ((currentPEC >> 2) & 0x01);
|
||||
const uint8 in4 = in0 ^ ((currentPEC >> 3) & 0x01);
|
||||
const uint8 in7 = in0 ^ ((currentPEC >> 6) & 0x01);
|
||||
const uint8 in8 = in0 ^ ((currentPEC >> 7) & 0x01);
|
||||
const uint8 in10 = in0 ^ ((currentPEC >> 9) & 0x01);
|
||||
const uint8 in14 = in0 ^ ((currentPEC >> 13) & 0x01);
|
||||
|
||||
uint16 newPEC = 0;
|
||||
|
||||
@ -103,9 +103,9 @@ uint16 updateCommandPEC(uint16 currentPEC, uint8 din) {
|
||||
//CRC-10
|
||||
//x^10 + x^7 + x^3 + x^2 + x + 1
|
||||
|
||||
uint16_t pec10_calc(bool rx_cmd, int len, uint8_t* data) {
|
||||
uint16_t remainder = 16; /* PEC_SEED; 0000010000 */
|
||||
uint16_t polynom = 0x8F; /* x10 + x7 + x3 + x2 + x + 1 <- the CRC15 polynomial
|
||||
uint16_t pec10_calc(bool rx_cmd, int len, const uint8_t* data) {
|
||||
uint16_t remainder = 16; /* PEC_SEED; 0000010000 */
|
||||
const uint16_t polynom = 0x8F; /* x10 + x7 + x3 + x2 + x + 1 <- the CRC15 polynomial
|
||||
100 1000 1111 48F */
|
||||
|
||||
/* Perform modulo-2 division, a byte at a time. */
|
||||
@ -149,16 +149,13 @@ crc F_CRC_CalculaCheckSum(uint8_t const AF_Datos[], uint16_t VF_nBytes);
|
||||
uint8 calculateDataPEC(uint8_t* data, uint8_t datalen) {
|
||||
|
||||
if (datalen >= 3) {
|
||||
|
||||
|
||||
crc currentpec = pec10_calc(true, datalen - 2, data) & 0x3FF; // mask to 10 bits
|
||||
const crc currentpec = pec10_calc(true, datalen - 2, data) & 0x3FF; // mask to 10 bits
|
||||
|
||||
// memory layout is [[zeroes], PEC[9:8]], [PEC[7:0]]
|
||||
data[datalen - 2] = (currentpec >> 8) & 0xFF;
|
||||
data[datalen - 1] = currentpec & 0xFF;
|
||||
|
||||
volatile uint8 result = pec10_calc(true, datalen, data);
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
@ -170,7 +167,7 @@ uint8 checkDataPEC(uint8* data, uint8 len) {
|
||||
return 255;
|
||||
}
|
||||
|
||||
crc currentpec = F_CRC_CalculaCheckSum(data, len);
|
||||
const crc currentpec = F_CRC_CalculaCheckSum(data, len);
|
||||
|
||||
return (currentpec == 0) ? 0 : 1;
|
||||
}
|
||||
@ -212,10 +209,10 @@ crc F_CRC_CalculaCheckSum(uint8_t const AF_Datos[], uint16_t VF_nBytes) {
|
||||
|
||||
uint16 updateDataPEC(uint16 currentPEC, uint8 din) {
|
||||
din = (din >> 7) & 0x01;
|
||||
uint8 in0 = din ^ ((currentPEC >> 9) & 0x01);
|
||||
uint8 in2 = in0 ^ ((currentPEC >> 1) & 0x01);
|
||||
uint8 in3 = in0 ^ ((currentPEC >> 2) & 0x01);
|
||||
uint8 in7 = in0 ^ ((currentPEC >> 6) & 0x01);
|
||||
const uint8 in0 = din ^ ((currentPEC >> 9) & 0x01);
|
||||
const uint8 in2 = in0 ^ ((currentPEC >> 1) & 0x01);
|
||||
const uint8 in3 = in0 ^ ((currentPEC >> 2) & 0x01);
|
||||
const uint8 in7 = in0 ^ ((currentPEC >> 6) & 0x01);
|
||||
|
||||
uint16 newPEC = 0;
|
||||
|
||||
@ -232,7 +229,7 @@ uint16 updateDataPEC(uint16 currentPEC, uint8 din) {
|
||||
return newPEC;
|
||||
}
|
||||
|
||||
uint8 writeCMD(uint16 command, uint8* args, uint8 arglen) {
|
||||
uint8 writeCMD(uint16 command, const uint8 * args, uint8 arglen) {
|
||||
uint8 ret;
|
||||
if (arglen > 0) {
|
||||
uint8 buffer[6 + arglen]; //command + PEC (2 bytes) + data + DPEC (2 bytes)
|
||||
@ -266,23 +263,9 @@ uint8 writeCMD(uint16 command, uint8* args, uint8 arglen) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define ITER_COUNT 50
|
||||
static uint8_t count = 0;
|
||||
static bool isOn = false;
|
||||
|
||||
uint8 readCMD(uint16 command, uint8* buffer, uint8 buflen) {
|
||||
if (count == ITER_COUNT) {
|
||||
HAL_GPIO_WritePin(STATUS_LED_B_GPIO_Port, STATUS_LED_B_Pin, isOn ? GPIO_PIN_SET : GPIO_PIN_RESET);
|
||||
|
||||
count = 0;
|
||||
isOn = !isOn;
|
||||
} else {
|
||||
count++;
|
||||
}
|
||||
|
||||
|
||||
uint8 txbuffer[6 + buflen] = {};
|
||||
uint8 rxbuffer[6 + buflen] = {};
|
||||
uint8 readCMD(uint16 command, uint8 * buffer, uint8 buflen) {
|
||||
uint8 txbuffer[6 + buflen];
|
||||
uint8 rxbuffer[6 + buflen];
|
||||
|
||||
txbuffer[0] = (command >> 8) & 0xFF;
|
||||
txbuffer[1] = (command)&0xFF;
|
||||
@ -335,25 +318,22 @@ void mcuAdbmsCSHigh() {
|
||||
}
|
||||
|
||||
uint8 mcuSPITransmit(uint8* buffer, uint8 buffersize) {
|
||||
HAL_StatusTypeDef status;
|
||||
uint8 rxbuf[buffersize];
|
||||
status = HAL_SPI_TransmitReceive(adbmsspi, buffer, rxbuf, buffersize,
|
||||
ADBMS_SPI_TIMEOUT);
|
||||
uint8 rxbuf[buffersize];
|
||||
const HAL_StatusTypeDef status = HAL_SPI_TransmitReceive(adbmsspi, buffer, rxbuf, buffersize,
|
||||
ADBMS_SPI_TIMEOUT);
|
||||
__HAL_SPI_CLEAR_OVRFLAG(adbmsspi);
|
||||
return status;
|
||||
}
|
||||
|
||||
uint8 mcuSPIReceive(uint8* buffer, uint8 buffersize) {
|
||||
HAL_StatusTypeDef status;
|
||||
status = HAL_SPI_Receive(adbmsspi, buffer, buffersize, ADBMS_SPI_TIMEOUT);
|
||||
const HAL_StatusTypeDef status = HAL_SPI_Receive(adbmsspi, buffer, buffersize, ADBMS_SPI_TIMEOUT);
|
||||
return status;
|
||||
}
|
||||
|
||||
uint8 mcuSPITransmitReceive(uint8* rxbuffer, uint8* txbuffer,
|
||||
uint8 buffersize) {
|
||||
HAL_StatusTypeDef status;
|
||||
status = HAL_SPI_TransmitReceive(adbmsspi, txbuffer, rxbuffer, buffersize,
|
||||
ADBMS_SPI_TIMEOUT);
|
||||
const HAL_StatusTypeDef status = HAL_SPI_TransmitReceive(adbmsspi, txbuffer, rxbuffer, buffersize,
|
||||
ADBMS_SPI_TIMEOUT);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
159
Core/Src/AMS_HighLevel.c
Normal file → Executable file
159
Core/Src/AMS_HighLevel.c
Normal file → Executable file
@ -6,29 +6,21 @@
|
||||
*/
|
||||
|
||||
#include "AMS_HighLevel.h"
|
||||
|
||||
#include "ADBMS_Abstraction.h"
|
||||
#include "ADBMS_LL_Driver.h"
|
||||
#include "TMP1075.h"
|
||||
#include "can-halal.h"
|
||||
#include "errors.h"
|
||||
#include "stm32f3xx_hal.h"
|
||||
|
||||
Cell_Module module = {};
|
||||
uint32_t balancedCells = 0;
|
||||
uint8_t BalancingActive = 0;
|
||||
uint8_t stateofcharge = 100;
|
||||
int64_t currentintegrator = 0;
|
||||
uint32_t lastticks = 0;
|
||||
uint32_t currenttick = 0;
|
||||
uint8_t eepromconfigured = 0;
|
||||
|
||||
uint8_t internalbalancingalgo = 1;
|
||||
uint16_t startbalancingthreshold = 41000;
|
||||
uint16_t stopbalancingthreshold = 30000;
|
||||
uint16_t balancingvoltagedelta = 10;
|
||||
bool balancingActive = false;
|
||||
|
||||
uint16_t amsuv = 0;
|
||||
uint16_t amsov = 0;
|
||||
|
||||
uint8_t amserrorcode = 0;
|
||||
uint8_t amswarningcode = 0;
|
||||
|
||||
uint8_t numberofCells = 16;
|
||||
uint8_t numberofCells = 13;
|
||||
uint8_t numberofAux = 0;
|
||||
|
||||
uint8_t packetChecksumFails = 0;
|
||||
@ -48,18 +40,9 @@ struct pollingTimes {
|
||||
struct pollingTimes pollingTimes = {0, 0};
|
||||
|
||||
void AMS_Init(SPI_HandleTypeDef* hspi) {
|
||||
if (eepromconfigured == 1) {
|
||||
/*amsov = eepromcellovervoltage>>4;
|
||||
amsuv = (eepromcellundervoltage-1)>>4;
|
||||
numberofCells = eepromnumofcells;
|
||||
numberofAux = eepromnumofaux;
|
||||
initAMS(hspi, eepromnumofcells, eepromnumofaux);*/
|
||||
amsConfigOverUnderVoltage(amsov, amsuv);
|
||||
} else {
|
||||
initAMS(hspi, numberofCells, numberofAux);
|
||||
amsov = DEFAULT_OV;
|
||||
amsuv = DEFAULT_UV;
|
||||
}
|
||||
initAMS(hspi, numberofCells, numberofAux);
|
||||
amsov = DEFAULT_OV;
|
||||
amsuv = DEFAULT_UV;
|
||||
|
||||
pollingTimes = (struct pollingTimes) {HAL_GetTick(), HAL_GetTick()};
|
||||
|
||||
@ -83,10 +66,8 @@ void AMS_Loop() {
|
||||
case AMSDISCHARGING:
|
||||
break;
|
||||
case AMSWARNING:
|
||||
writeWarningLog(0x01);
|
||||
break;
|
||||
case AMSERROR:
|
||||
writeErrorLog(amserrorcode);
|
||||
break;
|
||||
}
|
||||
lastAMSState = currentAMSState;
|
||||
@ -117,8 +98,8 @@ void AMS_Loop() {
|
||||
|
||||
uint8_t AMS_Idle_Loop() {
|
||||
if (!amsWakeUp()) {
|
||||
//error_data.data_kind = SEK_INTERNAL_BMS_TIMEOUT;
|
||||
//set_error_source(ERROR_SOURCE_INTERNAL);
|
||||
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);
|
||||
@ -147,15 +128,12 @@ uint8_t AMS_Idle_Loop() {
|
||||
|
||||
packetChecksumFails += amsCellMeasurement(&module);
|
||||
packetChecksumFails += amsCheckUnderOverVoltage(&module);
|
||||
packetChecksumFails += integrateCurrent();
|
||||
|
||||
if (packetChecksumFails > MAX_PACKET_CHECKSUM_FAILS) {
|
||||
error_data.data_kind = SEK_INTERNAL_BMS_CHECKSUM_FAIL;
|
||||
set_error_source(ERROR_SOURCE_INTERNAL);
|
||||
}
|
||||
|
||||
tmp1075_measure();
|
||||
|
||||
int any_voltage_error = 0;
|
||||
for (size_t i = 0; i < numberofCells; i++) {
|
||||
if (module.cellVoltages[i] < 2500) {
|
||||
@ -190,27 +168,16 @@ uint8_t AMS_Idle_Loop() {
|
||||
}
|
||||
|
||||
mcuDelay(10);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t AMS_Warning_Loop() {
|
||||
|
||||
amsWakeUp();
|
||||
amsConfigOverUnderVoltage(amsov, amsuv);
|
||||
amsClearAux();
|
||||
amsCellMeasurement(&module);
|
||||
amsAuxAndStatusMeasurement(&module);
|
||||
amsCheckUnderOverVoltage(&module);
|
||||
|
||||
if (!(module.overVoltage | module.underVoltage)) {
|
||||
currentAMSState = AMSIDLE;
|
||||
// amsClearWarning();
|
||||
if ((module.overVoltage | module.underVoltage)) {
|
||||
|
||||
}
|
||||
amsStopBalancing();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t AMS_Warning_Loop() { return 0; }
|
||||
|
||||
uint8_t AMS_Error_Loop() { return 0; }
|
||||
|
||||
uint8_t AMS_Charging_Loop() { return 0; }
|
||||
@ -218,96 +185,6 @@ uint8_t AMS_Charging_Loop() { return 0; }
|
||||
uint8_t AMS_Discharging_Loop() { return 0; }
|
||||
|
||||
uint8_t AMS_Balancing_Loop() {
|
||||
uint8_t balancingdone = 1;
|
||||
if ((eepromconfigured == 1) && (internalbalancingalgo == 1) &&
|
||||
(module.internalDieTemp <
|
||||
28000 /*Thermal Protection 93°C*/)) // If the EEPROM is configured and
|
||||
// the internal Balancing Algorithm
|
||||
// should be used
|
||||
{
|
||||
uint16_t highestcellvoltage = module.cellVoltages[0];
|
||||
uint16_t lowestcellvoltage = module.cellVoltages[0];
|
||||
uint8_t highestcell = 0;
|
||||
uint8_t lowestcell = 0;
|
||||
|
||||
for (uint8_t n = 0; n < numberofCells; n++) {
|
||||
if (module.cellVoltages[n] > highestcellvoltage) {
|
||||
highestcellvoltage = module.cellVoltages[n];
|
||||
highestcell = n;
|
||||
}
|
||||
if (module.cellVoltages[n] < lowestcellvoltage) {
|
||||
lowestcellvoltage = module.cellVoltages[n];
|
||||
lowestcell = n;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentAMSState ==
|
||||
AMSCHARGING) // Balancing is only Active if the BMS is in Charging Mode
|
||||
{
|
||||
|
||||
uint32_t channelstobalance = 0;
|
||||
|
||||
if (highestcellvoltage > startbalancingthreshold) {
|
||||
for (uint8_t n = 0; n < numberofCells; n++) {
|
||||
if (module.cellVoltages[n] > stopbalancingthreshold) {
|
||||
uint16_t dv = module.cellVoltages[n] - lowestcellvoltage;
|
||||
if (dv > (balancingvoltagedelta * 1000)) {
|
||||
balancingdone = 0;
|
||||
channelstobalance |= 1 << n;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
amsConfigBalancing(channelstobalance, 0x0F);
|
||||
amsStartBalancing(100);
|
||||
}
|
||||
|
||||
else if (currentAMSState == AMSIDLEBALANCING) {
|
||||
|
||||
uint32_t channelstobalance = 0;
|
||||
|
||||
if (lowestcellvoltage <
|
||||
stopbalancingthreshold) // If under Voltage of one Cell is reached
|
||||
{
|
||||
amsStopBalancing();
|
||||
balancingdone = 1;
|
||||
} else // otherwise continue with regular Balancing Algorithm
|
||||
{
|
||||
for (uint8_t n = 0; n < numberofCells; n++) {
|
||||
uint16_t dv = module.cellVoltages[n] - lowestcellvoltage;
|
||||
if (dv > balancingvoltagedelta) {
|
||||
balancingdone = 0;
|
||||
channelstobalance |= 1 << n;
|
||||
}
|
||||
}
|
||||
|
||||
amsConfigBalancing(channelstobalance, 0x0F);
|
||||
amsStartBalancing(100);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
amsStopBalancing();
|
||||
balancingdone = 1;
|
||||
}
|
||||
return balancingdone;
|
||||
}
|
||||
|
||||
uint8_t writeWarningLog(uint8_t warningCode) {
|
||||
// eepromWriteWarningLog(warningCode);
|
||||
return 0;
|
||||
}
|
||||
uint8_t writeErrorLog(uint8_t errorCode) {
|
||||
// eepromWriteErrorLog(errorCode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t integrateCurrent() {
|
||||
lastticks = currenttick;
|
||||
currenttick = HAL_GetTick();
|
||||
if (currenttick < lastticks) {
|
||||
currentintegrator += (module.auxVoltages[0] - module.auxVoltages[2]) *
|
||||
(currenttick - lastticks);
|
||||
}
|
||||
//TODO: implement
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,3 +1,10 @@
|
||||
/*
|
||||
* PWM_control.h
|
||||
*
|
||||
* Created on: 07.07.2024
|
||||
* Author: Hamza
|
||||
*/
|
||||
|
||||
#include "PWM_control.h"
|
||||
#include "state_machine.h"
|
||||
#include "stm32f3xx_hal.h"
|
||||
|
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* can.c
|
||||
* Created on: Mai 23, 2024
|
||||
* can.h
|
||||
*
|
||||
* Created on: 07.07.2024
|
||||
* Author: Hamza
|
||||
*/
|
||||
|
||||
@ -71,7 +72,7 @@ void can_handle_send_status() {
|
||||
data[5] = ((CURRENT_MEASUREMENT >> 8));
|
||||
data[6] = ((CURRENT_MEASUREMENT & 0x00F0) | (highest_temp >> 12));
|
||||
data[7] = ((highest_temp) >> 4);
|
||||
|
||||
//data[7] = state.error_source;
|
||||
ftcan_transmit(CAN_ID_OUT, data, sizeof(data));
|
||||
/*
|
||||
int8_t id_lowest_temp = -1;
|
||||
|
@ -134,7 +134,9 @@ int main(void)
|
||||
AMS_Init(&hspi1);
|
||||
can_init(&hcan);
|
||||
PWM_control_init(&htim3, &htim2, &htim15);
|
||||
HAL_Delay(10);
|
||||
//AMS_Loop();
|
||||
//int ttrgrtd = 2000 + HAL_GetTick();
|
||||
//while (ttrgrtd > HAL_GetTick());
|
||||
/* USER CODE END 2 */
|
||||
|
||||
/* Infinite loop */
|
||||
|
@ -1,3 +1,10 @@
|
||||
/*
|
||||
* state_machine.h
|
||||
*
|
||||
* Created on: 07.07.2024
|
||||
* Author: Hamza
|
||||
*/
|
||||
|
||||
#include "state_machine.h"
|
||||
#include "AMS_HighLevel.h"
|
||||
#include "PWM_control.h"
|
||||
@ -23,8 +30,8 @@ uint8_t powerground_calibration_stage;
|
||||
static uint32_t timestamp;
|
||||
|
||||
void sm_init(){
|
||||
state.current_state = STATE_ERROR;
|
||||
state.target_state = STATE_ERROR;
|
||||
state.current_state = STATE_INACTIVE;
|
||||
state.target_state = STATE_INACTIVE;
|
||||
state.error_source = 0;
|
||||
precharge_timer = discharge_timer = powerground_calibration_timer = 0;
|
||||
}
|
||||
@ -329,39 +336,14 @@ bool sm_is_errored(){
|
||||
*/
|
||||
|
||||
#warning TODO: add error checking for everything here
|
||||
void sm_check_errors(){
|
||||
switch (error_data.data_kind) {
|
||||
case SEK_OVERTEMP:
|
||||
case SEK_UNDERTEMP:
|
||||
case SEK_TOO_FEW_TEMPS:
|
||||
state.error_type.temperature_error = 1;
|
||||
break;
|
||||
case SEK_OVERVOLT:
|
||||
case SEK_UNDERVOLT:
|
||||
case SEK_OPENWIRE:
|
||||
state.error_type.voltage_error = 1;
|
||||
break;
|
||||
case SEK_EEPROM_ERR:
|
||||
//state.error_type.eeprom_error = 1;
|
||||
break;
|
||||
case SEK_INTERNAL_BMS_TIMEOUT:
|
||||
state.error_type.bms_timeout = 1;
|
||||
break;
|
||||
case SEK_INTERNAL_BMS_CHECKSUM_FAIL:
|
||||
case SEK_INTERNAL_BMS_OVERTEMP:
|
||||
case SEK_INTERNAL_BMS_FAULT:
|
||||
state.error_type.bms_fault = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
state.error_type.temperature_error = (error_data.data_kind == SEK_OVERTEMP || error_data.data_kind == SEK_UNDERTEMP ||error_data.data_kind == SEK_TOO_FEW_TEMPS) ? 1 : 0;
|
||||
state.error_type.voltage_error = (error_data.data_kind == SEK_OVERVOLT || error_data.data_kind == SEK_UNDERVOLT ||error_data.data_kind == SEK_OPENWIRE) ? 1 : 0;
|
||||
void sm_check_errors(){
|
||||
state.error_type.temperature_error = (error_data.data_kind == SEK_OVERTEMP || error_data.data_kind == SEK_UNDERTEMP || error_data.data_kind == SEK_TOO_FEW_TEMPS) ? 1 : 0;
|
||||
state.error_type.voltage_error = (error_data.data_kind == SEK_OVERVOLT || error_data.data_kind == SEK_UNDERVOLT || error_data.data_kind == SEK_OPENWIRE || RELAY_BAT_SIDE_VOLTAGE < 30000) ? 1 : 0;
|
||||
state.error_type.bms_timeout = (error_data.data_kind == SEK_INTERNAL_BMS_TIMEOUT) ? 1 : 0;
|
||||
state.error_type.bms_fault = (error_data.data_kind == SEK_INTERNAL_BMS_CHECKSUM_FAIL || error_data.data_kind == SEK_INTERNAL_BMS_FAULT || error_data.data_kind == SEK_INTERNAL_BMS_OVERTEMP) ? 1 : 0;
|
||||
state.error_type.bms_fault = (error_data.data_kind == SEK_INTERNAL_BMS_CHECKSUM_FAIL || error_data.data_kind == SEK_INTERNAL_BMS_FAULT /*|| error_data.data_kind == SEK_INTERNAL_BMS_OVERTEMP*/) ? 1 : 0;
|
||||
//SEK_EEPROM_ERR: state.error_type.eeprom_error = 1;
|
||||
state.error_type.current_error = (powerground_status > 10 && CURRENT_MEASUREMENT < 1000) ? 1 : 0;
|
||||
state.error_type.current_sensor_missing = (!CURRENT_MEASUREMENT_ON) ? 1 : 0;
|
||||
state.error_type.voltage_error = (RELAY_BAT_SIDE_VOLTAGE < 30000) ? 1 : 0;
|
||||
state.error_type.voltage_missing = (RELAY_BAT_SIDE_VOLTAGE < 1000) ? 1 : 0;
|
||||
|
||||
|
||||
@ -376,7 +358,7 @@ void sm_check_errors(){
|
||||
if (state.current_state == STATE_ERROR)
|
||||
state.target_state = STATE_INACTIVE;
|
||||
}
|
||||
|
||||
sm_error_source();
|
||||
}
|
||||
|
||||
int16_t sm_return_cell_temperature(int id){ return tmp1075_temps[id]; }
|
||||
@ -422,3 +404,16 @@ void sm_test_cycle_states(){
|
||||
|
||||
state.target_state = state.current_state;
|
||||
}
|
||||
|
||||
void sm_error_source(){
|
||||
state.error_source = 0;
|
||||
state.error_source |= (state.error_type.bms_timeout << 0);
|
||||
state.error_source |= (state.error_type.bms_fault << 1);
|
||||
state.error_source |= (state.error_type.temperature_error << 2);
|
||||
state.error_source |= (state.error_type.current_error << 3);
|
||||
|
||||
state.error_source |= (state.error_type.current_sensor_missing << 4);
|
||||
state.error_source |= (state.error_type.voltage_error << 5);
|
||||
state.error_source |= (state.error_type.voltage_missing << 6);
|
||||
state.error_source |= (state.error_type.state_transition_fail << 7);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user