Skip to content

Commit

Permalink
cell sense module
Browse files Browse the repository at this point in the history
  • Loading branch information
Akashem06 committed Mar 14, 2024
1 parent 55a623e commit c217405
Show file tree
Hide file tree
Showing 10 changed files with 189 additions and 206 deletions.
2 changes: 0 additions & 2 deletions libraries/ms-drivers/inc/ltc_afe.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,6 @@ typedef struct LtcAfeSettings {
} LtcAfeSettings;

typedef struct LtcAfeStorage {
Fsm fsm;

// Only used for storage in the FSM so we store data for the correct cells
uint16_t aux_index;
uint16_t retry_count;
Expand Down
1 change: 1 addition & 0 deletions projects/bms_carrier/inc/aux_sense.h
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#pragma once
21 changes: 1 addition & 20 deletions projects/bms_carrier/inc/bms.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,24 @@

#include <stdint.h>

#include "cell_sense.h"
#include "current_sense.h"
#include "i2c.h"
#include "ltc_afe.h"
#include "status.h"

#define BMS_PERIPH_I2C_PORT I2C_PORT_2
#define BMS_PERIPH_I2C_SDA_PIN \
{ GPIO_PORT_B, 11 }
#define BMS_PERIPH_I2C_SCL_PIN \
{ GPIO_PORT_B, 10 }
#define BMS_FAN_ALERT_PIN \
{ GPIO_PORT_A, 9 }

#define BMS_IO_EXPANDER_I2C_ADDR 0x40

#define BMS_FAN_CTRL_1_I2C_ADDR 0x5E
#define BMS_FAN_CTRL_2_I2C_ADDR 0x5F

#define MAX_VOLTAGE 42000
#define MIN_VOLTAGE 40000

// Fault thresholds
#define OVERVOLTAGE_THRESHOLD 42500
#define UNDERVOLTAGE_THRESHOLD 25000
#define AFE_BALANCING_UPPER_THRESHOLD 41500
#define AFE_BALANCING_LOWER_THRESHOLD 40000
#define MAX_CURRENT 27
#define MAX_AMBIENT_TEMP 75
#define MAX_CELL_TEMP 90

// Not dealing with debouncer here
typedef struct BmsStorage {
// RelayStorage relay_storage;
CurrentStorage current_storage;
AfeReadings afe_readings;
LtcAfeStorage ltc_afe_storage;
CellSenseStorage cell_storage;
// FanStorage fan_storage_1;
// FanStorage fan_storage_2;
// DebouncerStorage killswitch_storage;
Expand Down
98 changes: 25 additions & 73 deletions projects/bms_carrier/inc/cell_sense.h
Original file line number Diff line number Diff line change
@@ -1,99 +1,51 @@
// Individual AFE FSM module. Initialize it and then it should continuously run by itself
#pragma once

#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

#include "fsm.h"
#include "bms.h"
#include "bms_carrier_getters.h"
#include "bms_carrier_setters.h"
#include "delay.h"
#include "gpio.h"
#include "ltc_afe.h"
#include "ltc_afe_impl.h"
#include "spi.h"
#include "status.h"

#define LTC_AFE_FSM_CELL_CONV_DELAY_MS 10
#define LTC_AFE_FSM_AUX_CONV_DELAY_MS 6
#define CONV_DELAY_MS 10
// Maximum number of retry attempts to read cell/aux data once triggered
#define LTC_AFE_FSM_MAX_RETRY_COUNT 3

#define NUM_LTC_AFE_FSM_STATES 6
#define NUM_LTC_AFE_FSM_TRANSITIONS 14
#define RETRY_DELAY_MS 5

#define NUM_AFES 3
#define NUM_CELL_MODULES_PER_AFE 6
#define NUM_CELL_MODULES_PER_AFE 12
#define NUM_TOTAL_CELLS (NUM_AFES * NUM_CELL_MODULES_PER_AFE)
#define NUM_THERMISTORS (NUM_TOTAL_CELLS * 2)
#define MAX_AFE_FAULTS 5

#define AFE_SPI_PORT SPI_PORT_1
#define AFE_SPI_SS \
{ .port = GPIO_PORT_A, .pin = 4 }
// Fault thresholds
#define OVERVOLTAGE_THRESHOLD 42500
#define UNDERVOLTAGE_THRESHOLD 25000
#define AFE_BALANCING_UPPER_THRESHOLD 41500
#define AFE_BALANCING_LOWER_THRESHOLD 40000
#define AFE_UNBALANCE_THRESHOLD 10000

#define AFE_SPI_PORT SPI_PORT_2
#define AFE_SPI_CS \
{ .port = GPIO_PORT_B, .pin = 12 }
#define AFE_SPI_SCK \
{ .port = GPIO_PORT_A, .pin = 5 }
{ .port = GPIO_PORT_B, .pin = 13 }
#define AFE_SPI_MISO \
{ .port = GPIO_PORT_A, .pin = 6 }
{ .port = GPIO_PORT_B, .pin = 14 }
#define AFE_SPI_MOSI \
{ .port = GPIO_PORT_A, .pin = 7 }

// Wraps the LTC AFE module and handles all the sequencing.
// Requires LTC AFE, soft timers to be initialized.
//

DECLARE_FSM(ltc_afe_fsm);

typedef enum LtcAfeFsmStateId {
LTC_AFE_IDLE = 0,
LTC_AFE_TRIGGER_CELL_CONV,
LTC_AFE_READ_CELLS,
LTC_AFE_TRIGGER_AUX_CONV,
LTC_AFE_READ_AUX,
LTC_AFE_AUX_COMPLETE,
LTC_AFE_FAULT
} LtcAfeFsmStateId;

// We can raise a fault using this when transitioning to LTC_AFE_FAULT to identify where it came
// from
typedef enum {
LTC_AFE_FSM_FAULT_TRIGGER_CELL_CONV = 0,
LTC_AFE_FSM_FAULT_READ_ALL_CELLS,
LTC_AFE_FSM_FAULT_TRIGGER_AUX_CONV,
LTC_AFE_FSM_FAULT_READ_AUX,
NUM_LTC_AFE_FSM_FAULTS
} LtcAfeFsmFault;
{ .port = GPIO_PORT_B, .pin = 15 }

typedef struct CellSenseSettings {
// Units are 100 uV (or DeciMilliVolts)
uint16_t undervoltage_dmv;
uint16_t overvoltage_dmv;
uint16_t charge_overtemp_dmv;
uint16_t discharge_overtemp_dmv;
} CellSenseSettings;

typedef struct AfeReadings {
// TODO(SOFT-9): total_voltage used to be stored here as well
uint16_t voltages[NUM_TOTAL_CELLS];
uint16_t temps[NUM_THERMISTORS];
} AfeReadings;

typedef struct CellSenseStorage {
LtcAfeStorage *afe;
AfeReadings *readings;
uint16_t num_afe_faults;
CellSenseSettings settings;
} CellSenseStorage;

// First initialize the cell_sense module.
// Since it is the only module using the LTC6811, we can also initialize that and the corresponding
// FSM. Initialize the LTC6811. |settings.cell_bitset| and |settings.aux_bitset| should be an array
// of bitsets where bits 0 to 11 represent whether we should monitor the cell input for the given
// device. prv_extract_cell_result and prv_extract_aux_result will be called when the
// corresponding conversion is completed.

StatusCode cell_sense_init(const CellSenseSettings *settings, AfeReadings *readings,
LtcAfeStorage *afe, LtcAfeSettings *ltc_settings);
StatusCode cell_sense_init(LtcAfeStorage *afe_storage);

// Mark cell for discharging (takes effect after config is re-written)
// |cell| should be [0, settings.num_cells)

StatusCode ltc_afe_toggle_cell_discharge(LtcAfeStorage *afe, uint16_t cell, bool discharge);
StatusCode cell_sense_run(void);

StatusCode cell_sense_conversions(void);
9 changes: 3 additions & 6 deletions projects/bms_carrier/inc/relays_fsm.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,23 @@
#include "bms_carrier_getters.h"
#include "bms_carrier_setters.h"
#include "can.h"
#include "current_sense.h"
#include "delay.h"
#include "exported_enums.h"
#include "fsm.h"
#include "gpio.h"
#include "gpio_it.h"
#include "interrupt.h"
#include "log.h"
#include "ltc_afe.h"
#include "ltc_afe_impl.h"
#include "status.h"
#include "task.h"

#define NUM_RELAY_STATES 3
#define FUEL_GAUGE_CYCLE_TIME_MS 100
#define RELAYS_TIMEOUT

DECLARE_FSM(bms_relays);
typedef enum RelaysStateId { RELAYS_OPEN = 0, RELAYS_CLOSED, RELAYS_FAULT } RelaysStateId;

StatusCode init_bms_relays(void);
StatusCode init_bms_relays(BmsStorage *bms_storage);

// For smoke test
void close_relays();
void open_relays();
1 change: 1 addition & 0 deletions projects/bms_carrier/src/aux_sense.c
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#include "aux_sense.h"
127 changes: 127 additions & 0 deletions projects/bms_carrier/src/cell_sense.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
#include "cell_sense.h"

LtcAfeStorage *ltc_afe_storage;

static const LtcAfeSettings s_afe_settings = {
.mosi = AFE_SPI_MOSI,
.miso = AFE_SPI_MISO,
.sclk = AFE_SPI_SCK,
.cs = AFE_SPI_CS,

.spi_port = AFE_SPI_PORT,
.spi_baudrate = 750000,

.adc_mode = LTC_AFE_ADC_MODE_7KHZ,

.cell_bitset = { 0xFFF, 0xFFF, 0xFFF, 0xFFF, 0xFFF },
.aux_bitset = { 0 },

.num_devices = 2,
.num_cells = 12,
.num_thermistors = 12,
};

StatusCode 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
if (ltc_afe_impl_trigger_cell_conv(ltc_afe_storage)) {
// If this has failed, try once more after a short delay
delay_ms(RETRY_DELAY_MS);
status |= ltc_afe_impl_trigger_cell_conv(ltc_afe_storage);
}
delay_ms(CONV_DELAY_MS);

if (status != STATUS_CODE_OK) {
LOG_DEBUG("CELL_SENSE (conv failed): %d\n", status);
set_battery_status_fault(BMS_FAULT_COMMS_LOSS_AFE);
set_battery_status_status(1);
// fsm_transition(fsm, RELAYS_FAULT);
return status;
}

for (size_t i = 0; i < 10; i++) {
ltc_afe_impl_trigger_aux_conv(ltc_afe_storage, i);
delay_ms(CONV_DELAY_MS);
ltc_afe_impl_read_aux(ltc_afe_storage, i);

// Log thermistor result
LOG_DEBUG("Thermistor reading: %d\n",
ltc_afe_storage->aux_voltages[ltc_afe_storage->aux_result_lookup[i]]);
}
return status;
}

StatusCode cell_sense_run() {
StatusCode status = STATUS_CODE_OK;
uint16_t max_voltage = 0;
uint16_t min_voltage = 0xffff;

status |= ltc_afe_impl_read_cells(ltc_afe_storage);
for (size_t cell = 0; cell < (s_afe_settings.num_devices * s_afe_settings.num_cells); cell++) {
LOG_DEBUG("CELL %d: %d\n\r", cell,
ltc_afe_storage->cell_voltages[ltc_afe_storage->cell_result_lookup[cell]]);
max_voltage =
ltc_afe_storage->cell_voltages[ltc_afe_storage->cell_result_lookup[cell]] > max_voltage
? ltc_afe_storage->cell_voltages[ltc_afe_storage->cell_result_lookup[cell]]
: max_voltage;
min_voltage =
ltc_afe_storage->cell_voltages[ltc_afe_storage->cell_result_lookup[cell]] < min_voltage
? ltc_afe_storage->cell_voltages[ltc_afe_storage->cell_result_lookup[cell]]
: min_voltage;
delay_ms(2);
}
set_battery_vt_voltage(max_voltage);
LOG_DEBUG("MAX VOLTAGE: %d\n", max_voltage);
LOG_DEBUG("MIN VOLTAGE: %d\n", min_voltage);
delay_ms(1);

if (max_voltage >= OVERVOLTAGE_THRESHOLD) {
LOG_DEBUG("OVERVOLTAGE\n");
// fsm_transition(fsm, RELAYS_FAULT);
set_battery_status_fault(BMS_FAULT_OVERVOLTAGE);
set_battery_status_status(2);
return STATUS_CODE_INTERNAL_ERROR;
}
if (min_voltage <= UNDERVOLTAGE_THRESHOLD) {
LOG_DEBUG("UNDERVOLTAGE\n");
// fsm_transition(fsm, RELAYS_FAULT);
set_battery_status_fault(BMS_FAULT_UNDERVOLTAGE);
set_battery_status_status(1);
return STATUS_CODE_INTERNAL_ERROR;
}
if (max_voltage - min_voltage >= AFE_UNBALANCE_THRESHOLD) {
LOG_DEBUG("UNBALANCED\n");
// fsm_transition(fsm, RELAYS_FAULT);
set_battery_status_fault(BMS_FAULT_UNBALANCE);
set_battery_status_status(1);
return STATUS_CODE_INTERNAL_ERROR;
}

if (min_voltage >= AFE_BALANCING_UPPER_THRESHOLD) {
min_voltage += 20;
} else if (min_voltage < AFE_BALANCING_UPPER_THRESHOLD &&
min_voltage >= AFE_BALANCING_LOWER_THRESHOLD) {
min_voltage += 100;
} else {
min_voltage += 250;
}

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);
LOG_DEBUG("Cell %d unbalanced \n", cell);
// TODO: add fault for BMS_FAULT_UNBALANCE
} else {
ltc_afe_impl_toggle_cell_discharge(ltc_afe_storage, cell, false);
}
}
return status;
}

StatusCode cell_sense_init(LtcAfeStorage *afe_storage) {
ltc_afe_storage = afe_storage;
ltc_afe_init(ltc_afe_storage, &s_afe_settings);
delay_ms(10);
return STATUS_CODE_OK;
}
2 changes: 0 additions & 2 deletions projects/bms_carrier/src/current_sense.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,6 @@ StatusCode run_current_sense_cycle() {

StatusCode current_sense_init(CurrentStorage *storage, I2CSettings *i2c_settings,
uint32_t fuel_guage_cycle_ms) {
interrupt_init();
gpio_it_init();
i2c_init(I2C_PORT_1, i2c_settings);

GpioAddress alrt_pin = { .port = GPIO_PORT_A, .pin = 7 };
Expand Down
Loading

0 comments on commit c217405

Please sign in to comment.