V1.7
This commit is contained in:
parent
17e8cee0ac
commit
1a6728f7c0
@ -37,3 +37,10 @@ V1.6
|
||||
- CAN messages are now correctly formated
|
||||
- minimum cell voltage is now set to 3200 mV
|
||||
- powerground calibration is now done in STATE_PRECHARGE (well yes but actually no)
|
||||
|
||||
V1.7
|
||||
- added eeprom functions
|
||||
- fixed(tm) voltage and CURRENT_MEASUREMENT
|
||||
- changed the CAN message a bit
|
||||
- added soc_estimation.c soc_estimation.h
|
||||
- added MIN/MAX_CELL_VOLTAGE for AMS_HighLevel
|
||||
|
@ -4,6 +4,9 @@
|
||||
#include "stm32f3xx_hal.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <main.h>
|
||||
#include "AMS_HighLevel.h"
|
||||
#include "errors.h"
|
||||
|
||||
__attribute__((packed)) typedef struct {
|
||||
uint8_t id;
|
||||
@ -13,5 +16,8 @@ extern EEPROMConfig eeprom_config;
|
||||
|
||||
void eeprom_init(I2C_HandleTypeDef* hi2c);
|
||||
void eeprom_config_save();
|
||||
void eeprom_write_status();
|
||||
void eeprom_read(int8_t* data);
|
||||
void eeprom_write(uint8_t* data, uint8_t data_length);
|
||||
|
||||
#endif // INC_EEPROM_H_
|
||||
|
19
Core/Inc/soc_estimation.h
Normal file
19
Core/Inc/soc_estimation.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef INC_SOC_ESTIMATION_H
|
||||
#define INC_SOC_ESTIMATION_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <main.h>
|
||||
|
||||
extern float current_soc;
|
||||
|
||||
void soc_init();
|
||||
void soc_update();
|
||||
|
||||
typedef struct {
|
||||
uint16_t ocv;
|
||||
float soc;
|
||||
} ocv_soc_pair_t;
|
||||
extern ocv_soc_pair_t OCV_SOC_PAIRS[];
|
||||
float soc_for_ocv(uint16_t ocv);
|
||||
|
||||
#endif // INC_SOC_ESTIMATION_H
|
@ -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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user