Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BMS Refactor + State of Charge #292

Merged
merged 9 commits into from
Sep 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions libraries/FreeRTOS/inc/projdefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ typedef void (* TaskFunction_t)( void * );
#ifndef pdMS_TO_TICKS
#define pdMS_TO_TICKS( xTimeInMs ) ( ( TickType_t ) ( ( ( TickType_t ) ( xTimeInMs ) * ( TickType_t ) configTICK_RATE_HZ ) / ( TickType_t ) 1000U ) )
#endif
#ifndef pdTICKS_TO_MS
#define pdTICKS_TO_MS( xTicks ) ( ( ( xTicks ) * 1000U ) / configTICK_RATE_HZ )
#endif

#define pdFALSE ( ( BaseType_t ) 0 )
#define pdTRUE ( ( BaseType_t ) 1 )
Expand Down
6 changes: 3 additions & 3 deletions libraries/ms-drivers/src/ltc_afe_impl.c
Original file line number Diff line number Diff line change
Expand Up @@ -296,9 +296,9 @@ StatusCode ltc_afe_impl_toggle_cell_discharge(LtcAfeStorage *afe, uint16_t cell,
uint16_t device = afe->settings.num_devices - (actual_cell / LTC_AFE_MAX_CELLS_PER_DEVICE) - 1;

if (discharge) {
afe->discharge_bitset[device] |= (1 << (device_cell + 1));
afe->discharge_bitset[device] |= (1 << (device_cell));
} else {
afe->discharge_bitset[device] &= ~(1 << (device_cell + 1));
afe->discharge_bitset[device] &= ~(1 << (device_cell));
}

return STATUS_CODE_OK;
Expand All @@ -321,7 +321,7 @@ StatusCode ltc_afe_impl_set_discharge_pwm_cycle(LtcAfeStorage *afe, uint8_t duty
// For every device, set all 6 PWM bytes to the same config
for (uint8_t curr_device = 0; curr_device < settings->num_devices; curr_device++) {
for (int cell_pwm = 0; cell_pwm < 6; cell_pwm++) {
cmd[(curr_device * 6) + cell_pwm] = duty_cycle;
cmd[4 + (curr_device * 6) + cell_pwm] = (duty_cycle << 4) | duty_cycle;
}
}

Expand Down
5 changes: 4 additions & 1 deletion projects/bms_carrier/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,8 @@
"master",
"ms-drivers"
],
"can": true
"can": true,
"mocks": {
"test_state_of_charge": ["xTaskGetTickCount"]
}
}
7 changes: 2 additions & 5 deletions projects/bms_carrier/inc/aux_sense.h
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
#pragma once

#include "adc.h"
#include "bms.h"
#include "bms_carrier_getters.h"
#include "bms_carrier_setters.h"
#include "gpio.h"

#define R2_OHMS 10000
#define R1_OHMS 47000

typedef struct AuxStorage {
uint16_t aux_battery_voltage;
} AuxStorage;

StatusCode aux_sense_init(AuxStorage *aux_storage);
StatusCode aux_sense_init(BmsStorage *storage);

StatusCode aux_sense_run(void);
37 changes: 21 additions & 16 deletions projects/bms_carrier/inc/bms.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,39 @@

#include <stdint.h>

#include "aux_sense.h"
#include "fault_bps.h"
#include "i2c.h"
#include "ltc_afe.h"
#include "max17261_fuel_gauge.h"
#include "status.h"

#define BMS_PERIPH_I2C_PORT I2C_PORT_2
#define BMS_PERIPH_I2C_SDA_PIN \
{ .port = GPIO_PORT_B, .pin = 11 }
#define BMS_PERIPH_I2C_SCL_PIN \
{ .port = GPIO_PORT_B, .pin = 10 }

typedef struct CurrentStorage {
uint16_t soc;
int32_t current;
uint16_t voltage;
#define MAX17261_I2C_PORT (I2C_PORT_2)
#define MAX17261_I2C_ADDR (0x36)

#define CELL_CAPACITY_MAH 4850
#define NUM_SERIES_CELLS (4 * 9)
#define NUM_PARALLEL_CELLS (8)
#define PACK_CAPACITY_MAH (CELL_CAPACITY_MAH * NUM_PARALLEL_CELLS)

typedef struct {
uint8_t series_count;
uint8_t parallel_count;
uint16_t pack_capacity;
} BmsConfig;

typedef struct {
int32_t pack_current; // mA
uint32_t pack_voltage; // mV
uint16_t temperature;
uint32_t fuel_guage_cycle_ms; // Time in ms between conversions (soft timer kicks)
uint32_t remaining_capacity;
uint32_t full;
} CurrentStorage;

typedef struct BmsStorage {
AuxStorage aux_storage;
CurrentStorage current_storage;
uint16_t aux_batt_voltage; // mV
uint16_t fault_bitset;
BmsConfig config;

LtcAfeStorage ltc_afe_storage;
BpsStorage bps_storage;
Max17261Settings fuel_guage_settings;
Max17261Storage fuel_guage_storage;
} BmsStorage;
Expand Down
4 changes: 0 additions & 4 deletions projects/bms_carrier/inc/cell_sense.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,4 @@ StatusCode cell_sense_init(BmsStorage *bms_store);
// Mark cell for discharging (takes effect after config is re-written)
// |cell| should be [0, settings.num_cells)

StatusCode cell_conversions(void);

StatusCode cell_discharge(LtcAfeStorage *afe);

StatusCode cell_sense_run(void);
4 changes: 0 additions & 4 deletions projects/bms_carrier/inc/current_sense.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,10 @@

#define SENSE_RESISTOR_MOHM (0.5)

#define PACK_CAPACITY_MAH (1440000) // one module

#define CELL_EMPTY_VOLTAGE_MV 2500 // LG M50T datasheet

#define CHARGE_TERMINATION_CURRENT_MA (400) // 50 mA * 8 (one module)

#define NUM_SERIES_CELLS 36 // Number of cells in series to multiply average cell voltage

// Thresholds for ALRT Pin
#define CURRENT_SENSE_MAX_CURRENT_A (-58.2f)
#define CURRENT_SENSE_MIN_CURRENT_A (27.0f) // Actually 27
Expand Down
2 changes: 1 addition & 1 deletion projects/bms_carrier/inc/fan.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@
#define BMS_FAN_TEMP_LOWER_THRESHOLD 40 // Threshold before fan is full strength

void bms_run_fan(void);
void bms_fan_init(BmsStorage *bms_storage);
void bms_fan_init(BmsStorage *storage);
8 changes: 2 additions & 6 deletions projects/bms_carrier/inc/fault_bps.h
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
#pragma once

#include "bms.h"
#include "bms_carrier_getters.h"
#include "bms_carrier_setters.h"
#include "relays.h"
#include "status.h"

typedef struct BpsStorage {
uint16_t fault_bitset;
} BpsStorage;

StatusCode fault_bps_init(BpsStorage *storage);
StatusCode fault_bps_init(BmsStorage *storage);

StatusCode fault_bps_set(uint8_t fault_bitmask);

Expand Down
45 changes: 45 additions & 0 deletions projects/bms_carrier/inc/state_of_charge.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#pragma once

#include "bms.h"
#include "bms_carrier_getters.h"
#include "bms_carrier_setters.h"
#include "status.h"

#define CELL_INTERNAL_RESISTANCE_mOHMS 22
#define PACK_INTERNAL_RESISTANCE_mOHMS \
(CELL_INTERNAL_RESISTANCE_mOHMS * 9 * 4) / 8 // 9 modules, each module is 8P4S
#define VOLTS_TO_mV 1000
#define LUT_SIZE 41

typedef struct {
uint32_t last_time;
float i_soc;
float v_soc;
float averaged_soc;

int32_t last_current;
} StateOfChargeStorage;

void coulomb_counting_soc();
float perdict_ocv_voltage();
void ocv_voltage_soc();

StatusCode state_of_charge_init(BmsStorage *bms_storage);

StatusCode update_state_of_chrage();

// TEST FUNCTIONS
void ramp_voltage_weight();

void set_last_time(uint32_t last_time);
void set_i_soc(float i_soc);
void set_v_soc(float v_soc);
void set_averaged_soc(float averaged_soc);
void set_last_current(int32_t last_current);

uint32_t get_last_time(void);
float get_i_soc(void);
float get_v_soc(void);
float get_averaged_soc(void);
int32_t get_last_current(void);
float get_voltage_weight(void);
16 changes: 8 additions & 8 deletions projects/bms_carrier/src/aux_sense.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#include "aux_sense.h"

static const GpioAddress aux_sense_pin = { .port = GPIO_PORT_A, .pin = 5 };
AuxStorage *s_aux_storage;
BmsStorage *storage;

StatusCode aux_sense_init(AuxStorage *aux_storage) {
s_aux_storage = aux_storage;
StatusCode aux_sense_init(BmsStorage *storage) {
storage = storage;
gpio_init_pin(&aux_sense_pin, GPIO_ANALOG, GPIO_STATE_LOW);
adc_add_channel(aux_sense_pin);
adc_init();
Expand All @@ -14,10 +14,10 @@ StatusCode aux_sense_init(AuxStorage *aux_storage) {

StatusCode aux_sense_run() {
adc_run();
adc_read_converted(aux_sense_pin, &s_aux_storage->aux_battery_voltage);
s_aux_storage->aux_battery_voltage = (s_aux_storage->aux_battery_voltage) * (R2_OHMS + R1_OHMS) /
(R2_OHMS * 100); // CONV VOLTAGE;
LOG_DEBUG("AUX READING: %d\n", s_aux_storage->aux_battery_voltage);
set_battery_status_aux_batt_v(s_aux_storage->aux_battery_voltage);
adc_read_converted(aux_sense_pin, &storage->aux_batt_voltage);
storage->aux_batt_voltage =
(storage->aux_batt_voltage) * (R2_OHMS + R1_OHMS) / (R2_OHMS * 100); // CONV VOLTAGE
LOG_DEBUG("AUX READING: %d\n", storage->aux_batt_voltage);
set_battery_status_aux_batt_v(storage->aux_batt_voltage);
return STATUS_CODE_OK;
}
80 changes: 33 additions & 47 deletions projects/bms_carrier/src/cell_sense.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include "cell_sense.h"

LtcAfeStorage *ltc_afe_storage;
static BmsStorage *bms_storage;
static LtcAfeStorage *ltc_afe_storage;
static BmsStorage *bms;

#define TEMP_RESISTANCE 10000
#define VREF2 30000.0f // in 100uV
Expand Down Expand Up @@ -42,11 +42,8 @@ static const uint16_t s_resistance_lookup[TABLE_SIZE] = {
};

int calculate_temperature(uint16_t thermistor) {
// INCOMPLETE
thermistor = (uint16_t)(thermistor * ADC_GAIN); // 100uV
LOG_DEBUG("Thermistor Voltage: %d\n", thermistor);
thermistor = (uint16_t)(thermistor * ADC_GAIN); // 100uV
uint16_t thermistor_resistance = (thermistor * TEMP_RESISTANCE) / (VREF2 - thermistor); // Ohms
LOG_DEBUG("Thermistor Resistance: %d\n", thermistor_resistance);
delay_ms(10);
uint16_t min_diff = abs(thermistor_resistance - s_resistance_lookup[0]);

Expand Down Expand Up @@ -78,7 +75,7 @@ static const LtcAfeSettings s_afe_settings = {
.num_thermistors = NUM_THERMISTORS,
};

static inline StatusCode prv_cell_sense_conversions() {
static StatusCode prv_cell_sense_conversions() {
StatusCode status = STATUS_CODE_OK;
// TODO: Figure out why cell_conv cannot happen without spi timing out (Most likely RTOS
// implemntation error) Retry Mechanism
Expand Down Expand Up @@ -163,26 +160,7 @@ static inline StatusCode prv_cell_sense_conversions() {
return status;
}

// Task bc delays
TASK(cell_sense_conversions, TASK_STACK_256) {
while (true) {
notify_wait(NULL, BLOCK_INDEFINITELY);
prv_cell_sense_conversions();
send_task_end();
}
}

StatusCode cell_conversions() {
StatusCode ret = notify(cell_sense_conversions, CELL_SENSE_CONVERSIONS);
if (ret != STATUS_CODE_OK) {
LOG_DEBUG("NOTIFY FAILED\n");
fault_bps_set(BMS_FAULT_COMMS_LOSS_AFE);
return STATUS_CODE_INTERNAL_ERROR;
}
return STATUS_CODE_OK;
}

StatusCode cell_sense_run() {
static StatusCode prv_cell_sense_run() {
StatusCode status = STATUS_CODE_OK;
uint16_t max_voltage = 0;
uint16_t min_voltage = 0xffff;
Expand Down Expand Up @@ -221,11 +199,11 @@ StatusCode cell_sense_run() {
fault_bps_set(BMS_FAULT_UNDERVOLTAGE);
status = STATUS_CODE_INTERNAL_ERROR;
}
// if (max_voltage - min_voltage >= CELL_UNBALANCED) {
// LOG_DEBUG("UNBALANCED\n");
// fault_bps_set(BMS_FAULT_UNBALANCE);
// status = STATUS_CODE_INTERNAL_ERROR;
//}
if (max_voltage - min_voltage >= CELL_UNBALANCED) {
LOG_DEBUG("UNBALANCED\n");
fault_bps_set(BMS_FAULT_UNBALANCE);
status = STATUS_CODE_INTERNAL_ERROR;
}

if (min_voltage >= AFE_BALANCING_UPPER_THRESHOLD) {
min_voltage += 20;
Expand All @@ -237,14 +215,15 @@ StatusCode cell_sense_run() {
}

// Balancing
// for (size_t cell = 0; cell < (s_afe_settings.num_devices * s_afe_settings.num_cells); cell++) {
// if (ltc_afe_storage->cell_voltages[ltc_afe_storage->cell_result_lookup[cell]] > min_voltage) {
// ltc_afe_impl_toggle_cell_discharge(ltc_afe_storage, cell, true);
// } else {
// ltc_afe_impl_toggle_cell_discharge(ltc_afe_storage, cell, false);
// }
//}
for (size_t cell = 0; cell < (s_afe_settings.num_devices * s_afe_settings.num_cells); cell++) {
if (ltc_afe_storage->cell_voltages[ltc_afe_storage->cell_result_lookup[cell]] > min_voltage) {
ltc_afe_impl_toggle_cell_discharge(ltc_afe_storage, cell, true);
} else {
ltc_afe_impl_toggle_cell_discharge(ltc_afe_storage, cell, false);
}
}
LOG_DEBUG("Config discharge bitset %d\n", ltc_afe_storage->discharge_bitset[0]);
ltc_afe_impl_write_config(ltc_afe_storage);

// Log and check all thermistor values based on settings bitset
uint16_t max_temp = 0;
Expand All @@ -263,7 +242,7 @@ StatusCode cell_sense_run() {
if (ltc_afe_storage->aux_voltages[index] > CELL_TEMP_OUTLIER) {
continue;
}
if (bms_storage->current_storage.current < 0) {
if (bms->pack_current < 0) {
if (ltc_afe_storage->aux_voltages[index] >= CELL_MAX_TEMPERATURE_DISCHARGE) {
LOG_DEBUG("CELL OVERTEMP\n");
fault_bps_set(BMS_FAULT_OVERTEMP_CELL);
Expand Down Expand Up @@ -318,15 +297,22 @@ StatusCode cell_sense_run() {
return status;
}

StatusCode cell_discharge(LtcAfeStorage *afe_storage) {
return ltc_afe_impl_write_config(afe_storage);
}

StatusCode cell_sense_init(BmsStorage *bms_store) {
bms_storage = bms_store;
ltc_afe_storage = &bms_store->ltc_afe_storage;
// Task bc delays
TASK(cell_sense_conversions, TASK_STACK_512) {
ltc_afe_init(ltc_afe_storage, &s_afe_settings);
delay_ms(10);
TickType_t xLastWakeTime = xTaskGetTickCount();
while (true) {
prv_cell_sense_conversions();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should cell_sense_run() also be prv? Also again maybe don't inline this. I remember the justification being Jarvis saying it'll save us some memory but did this fix anything? It's probably best to leave it to the compiler.

prv_cell_sense_run();
/* Delay is TBD */
xTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(10000));
}
}

StatusCode cell_sense_init(BmsStorage *storage) {
bms = storage;
ltc_afe_storage = &(bms->ltc_afe_storage);
tasks_init_task(cell_sense_conversions, TASK_PRIORITY(2), NULL);
return STATUS_CODE_OK;
}
Loading
Loading