-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
189 additions
and
206 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
#pragma once |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
#include "aux_sense.h" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.