V1.7
This commit is contained in:
		@ -28,7 +28,8 @@ uint8_t packetChecksumFails = 0;
 | 
			
		||||
 | 
			
		||||
uint8_t deviceSleeps = 0;
 | 
			
		||||
#define MAX_DEVICE_SLEEP 3 //TODO: change to correct value
 | 
			
		||||
 | 
			
		||||
#define MAX_CELL_VOLTAGE 4100 //change to 4200
 | 
			
		||||
#define MIN_CELL_VOLTAGE 3100 //change to 3100
 | 
			
		||||
amsState currentAMSState = AMSDEACTIVE;
 | 
			
		||||
amsState lastAMSState = AMSDEACTIVE;
 | 
			
		||||
 | 
			
		||||
@ -136,13 +137,13 @@ uint8_t AMS_Idle_Loop() {
 | 
			
		||||
  
 | 
			
		||||
  int any_voltage_error = 0;
 | 
			
		||||
  for (size_t i = 0; i < numberofCells; i++) {
 | 
			
		||||
    if (module.cellVoltages[i] < 3200) {
 | 
			
		||||
    if (module.cellVoltages[i] < MIN_CELL_VOLTAGE) {
 | 
			
		||||
      any_voltage_error = 1;
 | 
			
		||||
      error_data.data_kind = SEK_UNDERVOLT;
 | 
			
		||||
      error_data.data[0] = i;
 | 
			
		||||
      uint8_t* ptr = &error_data.data[1];
 | 
			
		||||
      ptr = ftcan_marshal_unsigned(ptr, module.cellVoltages[i], 2);
 | 
			
		||||
    } else if (module.cellVoltages[i] > 4200) {
 | 
			
		||||
    } else if (module.cellVoltages[i] > MAX_CELL_VOLTAGE) {
 | 
			
		||||
      any_voltage_error = 1;
 | 
			
		||||
      error_data.data_kind = SEK_OVERVOLT;
 | 
			
		||||
      error_data.data[0] = i;
 | 
			
		||||
 | 
			
		||||
@ -65,12 +65,12 @@ void can_handle_send_status() {
 | 
			
		||||
  sm_check_battery_temperature(&id_highest_temp, &highest_temp);
 | 
			
		||||
 | 
			
		||||
  data[0] = ((state.current_state << 4) | (powerground_status >> 4));               // 1 bit emptyy | 3 bit state | 4 bit powerground 
 | 
			
		||||
  data[1] = ((powerground_status << 4) | (state.error_source >> 4));              // 4 bit powerground | 4 bit error 
 | 
			
		||||
  data[1] = ((powerground_status << 4) | (state.error_source >> 4));                // 4 bit powerground | 4 bit error 
 | 
			
		||||
  data[2] = ((state.error_source << 4) | (0));                                      // 4 bit error | 4 bit state of charge
 | 
			
		||||
  data[3] = ((RELAY_BAT_SIDE_VOLTAGE >> 8));                                // 4 bit state of charge | 4 bit battery voltage
 | 
			
		||||
  data[3] = ((RELAY_BAT_SIDE_VOLTAGE >> 8));                                        // 8 bit battery voltage
 | 
			
		||||
  data[4] = ((RELAY_BAT_SIDE_VOLTAGE >> 0));
 | 
			
		||||
  data[5] = ((CURRENT_MEASUREMENT >> 8));
 | 
			
		||||
  data[6] = ((CURRENT_MEASUREMENT & 0x000F) | (highest_temp >> 12));
 | 
			
		||||
  data[5] = ((CURRENT_MEASUREMENT) / 1000);
 | 
			
		||||
  data[6] = (/*(CURRENT_MEASUREMENT & 0x000F) |*/ (highest_temp >> 12));
 | 
			
		||||
  data[7] = ((highest_temp) >> 4);
 | 
			
		||||
  //data[7] = state.error_source;
 | 
			
		||||
  ftcan_transmit(CAN_ID_OUT, data, sizeof(data));
 | 
			
		||||
@ -144,6 +144,12 @@ void can_handle_recieve_command(const uint8_t *data){
 | 
			
		||||
    sm_handle_ams_in(data);
 | 
			
		||||
  } else if (data[0] == 0x02 && data[1] <= 100) { 
 | 
			
		||||
    sm_handle_ams_in(data);
 | 
			
		||||
  } else if (data[0] == 0xF0 && data[1] == 0x00) { 
 | 
			
		||||
    sm_handle_ams_in(data);
 | 
			
		||||
  } else if (data[0] == 0xF1 && data[1] == 0) { 
 | 
			
		||||
    sm_handle_ams_in(data);
 | 
			
		||||
  } else if (data[0] == 0xFF && data[1] == 0) { 
 | 
			
		||||
    sm_handle_ams_in(data);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
#include "eeprom.h"
 | 
			
		||||
#include "errors.h"
 | 
			
		||||
#include "stm32f3xx_hal.h"
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#define EEPROM_I2C_ADDR          0xA0
 | 
			
		||||
@ -10,11 +10,13 @@
 | 
			
		||||
#define EEPROM_CONFIG_ECC_OFFSET 0x20
 | 
			
		||||
 | 
			
		||||
EEPROMConfig eeprom_config;
 | 
			
		||||
uint32_t current_address;
 | 
			
		||||
 | 
			
		||||
static I2C_HandleTypeDef* hi2c;
 | 
			
		||||
 | 
			
		||||
void eeprom_init(I2C_HandleTypeDef* handle) {
 | 
			
		||||
  hi2c = handle;
 | 
			
		||||
  current_address = 0;
 | 
			
		||||
  uint8_t buf[sizeof(EEPROMConfig) * 3];
 | 
			
		||||
  // Read 3 EEPROM config buffers at 32 byte offsets
 | 
			
		||||
  for (size_t ecc_i = 0; ecc_i < 3; ecc_i++) {
 | 
			
		||||
@ -58,3 +60,23 @@ void eeprom_config_save() {
 | 
			
		||||
    HAL_Delay(100);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void eeprom_write_status(){
 | 
			
		||||
  uint8_t data_length = 16;
 | 
			
		||||
  uint8_t data[data_length] = {};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  eeprom_write(data, data_length);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void eeprom_read(int8_t* data){}
 | 
			
		||||
 | 
			
		||||
void eeprom_write(uint8_t* data, uint8_t data_length){
 | 
			
		||||
  HAL_StatusTypeDef status = HAL_I2C_Mem_Write(
 | 
			
		||||
        hi2c, EEPROM_I2C_ADDR,
 | 
			
		||||
        current_address, 2,
 | 
			
		||||
        (uint8_t*)&eeprom_config, sizeof(eeprom_config), 100);
 | 
			
		||||
  if (status != HAL_OK) {
 | 
			
		||||
    set_error_source(ERROR_SOURCE_EEPROM);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										91
									
								
								Core/Src/soc_estimation.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								Core/Src/soc_estimation.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,91 @@
 | 
			
		||||
#include "soc_estimation.h"
 | 
			
		||||
 | 
			
		||||
#include "state_machine.h"
 | 
			
		||||
#include "stm32f3xx_hal.h"
 | 
			
		||||
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#define SOC_ESTIMATION_NO_CURRENT_THRESH 200     // mA
 | 
			
		||||
#define SOC_ESTIMATION_NO_CURRENT_TIME 100000    // ms
 | 
			
		||||
#define SOC_ESTIMATION_BATTERY_CAPACITY 70300800 // mAs
 | 
			
		||||
 | 
			
		||||
#define MIN_CELL_VOLTAGE 3000
 | 
			
		||||
#define MAX_CELL_VOLTAGE 4200
 | 
			
		||||
 | 
			
		||||
ocv_soc_pair_t OCV_SOC_PAIRS[] = {
 | 
			
		||||
    {25000, 0.00f},  {29900, 3.97f},  {32300, 9.36f},  {33200, 12.60f},
 | 
			
		||||
    {33500, 13.68f}, {34100, 20.15f}, {35300, 32.01f}, {38400, 66.53f},
 | 
			
		||||
    {40100, 83.79f}, {40200, 90.26f}, {40400, 94.58f}, {41000, 98.89f},
 | 
			
		||||
    {42000, 100.00f}};
 | 
			
		||||
 | 
			
		||||
float current_soc;
 | 
			
		||||
 | 
			
		||||
int current_was_flowing;
 | 
			
		||||
uint32_t last_current_time;
 | 
			
		||||
float soc_before_current;
 | 
			
		||||
float mAs_before_current;
 | 
			
		||||
 | 
			
		||||
void soc_init() {
 | 
			
		||||
  current_soc = 0;
 | 
			
		||||
  last_current_time = 0;
 | 
			
		||||
  current_was_flowing = 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void soc_update() {
 | 
			
		||||
  uint32_t now = HAL_GetTick();
 | 
			
		||||
  if (CURRENT_MEASUREMENT >= SOC_ESTIMATION_NO_CURRENT_THRESH) {
 | 
			
		||||
    last_current_time = now;
 | 
			
		||||
    if (!current_was_flowing) {
 | 
			
		||||
      soc_before_current = current_soc;
 | 
			
		||||
      mAs_before_current = CURRENT_MEASUREMENT;
 | 
			
		||||
    }
 | 
			
		||||
    current_was_flowing = 1;
 | 
			
		||||
  } else {
 | 
			
		||||
    current_was_flowing = 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (now - last_current_time >= SOC_ESTIMATION_NO_CURRENT_TIME ||
 | 
			
		||||
      last_current_time == 0) {
 | 
			
		||||
    // Assume we're measuring OCV if there's been no current for a while (or
 | 
			
		||||
    // we've just turned on the battery).
 | 
			
		||||
    current_soc = soc_for_ocv(min_voltage);
 | 
			
		||||
  } else {
 | 
			
		||||
    // Otherwise, use the current counter to update SoC
 | 
			
		||||
    float as_delta = shunt_data.current_counter - mAs_before_current;
 | 
			
		||||
    float soc_delta = as_delta / SOC_ESTIMATION_BATTERY_CAPACITY * 100;
 | 
			
		||||
    current_soc = soc_before_current + soc_delta;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float soc_for_ocv(uint16_t ocv) {
 | 
			
		||||
  size_t i = 0;
 | 
			
		||||
  size_t array_length = sizeof(OCV_SOC_PAIRS) / sizeof(*OCV_SOC_PAIRS);
 | 
			
		||||
  // Find the index of the first element with OCV greater than the target OCV
 | 
			
		||||
  while (i < array_length && OCV_SOC_PAIRS[i].ocv <= ocv) {
 | 
			
		||||
    i++;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // If the target OCV is lower than the smallest OCV in the array, return the
 | 
			
		||||
  // first SOC value
 | 
			
		||||
  if (i == 0) {
 | 
			
		||||
    return OCV_SOC_PAIRS[0].soc;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // If the target OCV is higher than the largest OCV in the array, return the
 | 
			
		||||
  // last SOC value
 | 
			
		||||
  if (i == array_length) {
 | 
			
		||||
    return OCV_SOC_PAIRS[array_length - 1].soc;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Perform linear interpolation
 | 
			
		||||
  uint16_t ocv1 = OCV_SOC_PAIRS[i - 1].ocv;
 | 
			
		||||
  uint16_t ocv2 = OCV_SOC_PAIRS[i].ocv;
 | 
			
		||||
  float soc1 = OCV_SOC_PAIRS[i - 1].soc;
 | 
			
		||||
  float soc2 = OCV_SOC_PAIRS[i].soc;
 | 
			
		||||
 | 
			
		||||
  float slope = (soc2 - soc1) / (ocv2 - ocv1);
 | 
			
		||||
  float interpolated_soc = soc1 + slope * (ocv - ocv1);
 | 
			
		||||
 | 
			
		||||
  return interpolated_soc;
 | 
			
		||||
}
 | 
			
		||||
@ -49,13 +49,13 @@ void sm_update(){
 | 
			
		||||
  //  state.current_state = state.target_state = STATE_ERROR;
 | 
			
		||||
 | 
			
		||||
  if (state.current_state == STATE_INACTIVE){
 | 
			
		||||
    base_offset = module.auxVoltages[0];
 | 
			
		||||
    CURRENT_MEASUREMENT = (module.auxVoltages[0] > 2494) ? (module.auxVoltages[0] - (2494.0)) * (300.0) : 0;
 | 
			
		||||
  } else {
 | 
			
		||||
    CURRENT_MEASUREMENT = (module.auxVoltages[0] > 2477) ? (module.auxVoltages[0] - (2477.0)) * (4600.0) : 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  CURRENT_MEASUREMENT = roundf((module.auxVoltages[0] - base_offset) * 350);
 | 
			
		||||
  CURRENT_MEASUREMENT_ON = (module.auxVoltages[1] > 2400);
 | 
			
		||||
  RELAY_ESC_SIDE_VOLTAGE = module.auxVoltages[2] * 11.711;
 | 
			
		||||
  RELAY_BAT_SIDE_VOLTAGE = module.auxVoltages[3] * 11.711;     // the calculation says the factor is 11. 11.711 yields the better result
 | 
			
		||||
  RELAY_ESC_SIDE_VOLTAGE = module.auxVoltages[2] * 15.98;
 | 
			
		||||
  RELAY_BAT_SIDE_VOLTAGE = module.auxVoltages[3] * 15.98;     // the calculation says the factor is 11. 11.711 yields the better result
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
  switch (state.current_state) {
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user