V1.4
This commit is contained in:
		
							
								
								
									
										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);
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user