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

Soft 222 smoke ltc6811 validation #513

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
13 changes: 9 additions & 4 deletions libraries/ms-drivers/inc/ltc6811.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,19 +76,24 @@ static_assert(sizeof(LtcAfeConfigRegisterData) == 6, "LtcAfeConfigRegisterData m

// COMM Register, refer to LTC6803 datasheet page 31, Table 15
typedef struct {
uint8_t d0_msb : 4;
uint8_t icom0 : 4;
uint8_t d0 : 8;
uint8_t fcom0 : 4;
uint8_t d0_lsb : 4;

uint8_t d1_msb : 4;
uint8_t icom1 : 4;
uint8_t d1 : 8;
uint8_t fcom1 : 4;
uint8_t d1_lsb : 4;

uint8_t d2_msb : 4;
uint8_t icom2 : 4;
uint8_t d2 : 8;
uint8_t fcom2 : 4;
uint8_t d2_lsb : 4;
} _PACKED LtcAfeCommRegisterData;
static_assert(sizeof(LtcAfeCommRegisterData) == 6, "LtcAfeCommRegisterData must be 6 bytes");
#define LTC6811_EXTRACT_DATA_MSB(x) ((x) >> 4)
#define LTC6811_EXTRACT_DATA_LSB(x) ((x) & 0xF)

// CFGR packet
typedef struct {
Expand All @@ -101,7 +106,7 @@ typedef struct {
typedef struct {
uint8_t wrcomm[LTC6811_CMD_SIZE];
LtcAfeCommRegisterData reg;
uint8_t pec;
uint16_t pec;
} _PACKED LtcAfeWriteCommRegPacket;

// STMCOMM + clock cycles
Expand Down
6 changes: 6 additions & 0 deletions libraries/ms-drivers/src/ltc_afe_fsm.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ static void prv_afe_read_cells_output(struct Fsm *fsm, const Event *e, void *con
event_raise(afe_events->callback_run_event, 0);

if (afe->settings.cell_result_cb != NULL) {
// for(int i = 0; i < LTC_AFE_MAX_CELLS; i++) {
// LOG_DEBUG("cell_voltages[%d] = %lu\n", i, afe->cell_voltages[i]);
// }
afe->settings.cell_result_cb(afe->cell_voltages, afe->settings.num_cells,
afe->settings.result_context);
}
Expand Down Expand Up @@ -162,6 +165,9 @@ static void prv_afe_aux_complete_output(struct Fsm *fsm, const Event *e, void *c

// 12 aux conversions complete - the array should be fully populated
if (afe->settings.aux_result_cb != NULL) {
// for(int i = 0; i < LTC_AFE_MAX_CELLS; i++) {
// LOG_DEBUG("aux_voltages[%d] = %lu\n", i, afe->aux_voltages[i]);
// }
afe->settings.aux_result_cb(afe->aux_voltages, afe->settings.num_cells,
afe->settings.result_context);
}
Expand Down
37 changes: 30 additions & 7 deletions libraries/ms-drivers/src/ltc_afe_impl.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,11 +122,13 @@ static StatusCode prv_aux_write_comm_register(LtcAfeStorage *afe, uint8_t device
// We send the a byte and then we send CSBM_HIGH to
// release the SPI port
packet.reg.icom0 = LTC6811_ICOM_CSBM_LOW;
packet.reg.d0 = device_cell;
packet.reg.d0_msb = LTC6811_EXTRACT_DATA_MSB(device_cell);
packet.reg.d0_lsb = LTC6811_EXTRACT_DATA_LSB(device_cell);
packet.reg.fcom0 = LTC6811_FCOM_CSBM_HIGH;
packet.reg.icom1 = LTC6811_ICOM_NO_TRANSMIT;
packet.reg.icom2 = LTC6811_ICOM_NO_TRANSMIT;
uint16_t comm_pec = crc15_calculate((uint8_t *)&packet.reg, sizeof(LtcAfeCommRegisterData));
packet.pec = SWAP_UINT16(comm_pec);

prv_wakeup_idle(afe);
return spi_exchange(settings->spi_port, (uint8_t *)&packet, sizeof(LtcAfeWriteCommRegPacket),
Expand Down Expand Up @@ -196,10 +198,10 @@ static void prv_calc_offsets(LtcAfeStorage *afe) {
//
// Similarly, we do the opposite mapping for discharge.
LtcAfeSettings *settings = &afe->settings;
size_t cell_index = 0;
size_t aux_index = 0;
uint16_t cell_index = 0;
uint16_t aux_index = 0;
for (size_t device = 0; device < settings->num_devices; device++) {
for (size_t device_cell = 0; device_cell < LTC_AFE_MAX_CELLS_PER_DEVICE; device_cell++) {
for (uint16_t device_cell = 0; device_cell < LTC_AFE_MAX_CELLS_PER_DEVICE; device_cell++) {
size_t cell = device * LTC_AFE_MAX_CELLS_PER_DEVICE + device_cell;

if ((settings->cell_bitset[device] >> device_cell) & 0x1) {
Expand All @@ -216,6 +218,18 @@ static void prv_calc_offsets(LtcAfeStorage *afe) {
}
}
}

if (aux_index != afe->settings.num_cells) {
LOG_CRITICAL("Result array has max_index %d but should have max %d\n",
aux_index, (uint16_t) afe->settings.num_cells);
}

if (cell_index != afe->settings.num_cells) {
LOG_CRITICAL("Result array has max_index %d but should have max %d\n",
cell_index, (uint16_t) afe->settings.num_cells);
return;
}
LOG_DEBUG("calc_offsets is fine\n");
}

StatusCode ltc_afe_impl_init(LtcAfeStorage *afe, const LtcAfeSettings *settings) {
Expand All @@ -242,8 +256,8 @@ StatusCode ltc_afe_impl_init(LtcAfeStorage *afe, const LtcAfeSettings *settings)
spi_init(settings->spi_port, &spi_config);

// Use GPIO1 as analog input, GPIO 3-5 for SPI
uint8_t gpio_bits =
LTC6811_GPIO1_PD_OFF | LTC6811_GPIO3_PD_OFF | LTC6811_GPIO4_PD_OFF | LTC6811_GPIO5_PD_OFF;
uint8_t gpio_bits = LTC6811_GPIO1_PD_OFF | LTC6811_GPIO2_PD_ON | LTC6811_GPIO3_PD_ON |
LTC6811_GPIO4_PD_ON | LTC6811_GPIO5_PD_ON;
return prv_write_config(afe, gpio_bits);
}

Expand All @@ -262,6 +276,7 @@ StatusCode ltc_afe_impl_trigger_aux_conv(LtcAfeStorage *afe, uint8_t device_cell

StatusCode ltc_afe_impl_read_cells(LtcAfeStorage *afe) {
// Read all voltage A, then B, ...
uint16_t num_readings = 0;
LtcAfeSettings *settings = &afe->settings;
for (uint8_t cell_reg = 0; cell_reg < NUM_LTC_AFE_VOLTAGE_REGISTERS; ++cell_reg) {
LtcAfeVoltageRegisterGroup voltage_register[LTC_AFE_MAX_DEVICES] = { 0 };
Expand All @@ -274,9 +289,11 @@ StatusCode ltc_afe_impl_read_cells(LtcAfeStorage *afe) {
uint16_t device_cell = cell + (cell_reg * LTC6811_CELLS_IN_REG);
uint16_t index = device * LTC_AFE_MAX_CELLS_PER_DEVICE + device_cell;

if ((settings->cell_bitset[device] >> device_cell) & 0x1) {
if (((settings->cell_bitset[device] >> device_cell) & 0x1) == 0x1) {
// Input enabled - store result
afe->cell_voltages[afe->cell_result_lookup[index]] = voltage;
LOG_DEBUG("CELL READING#%d is CELL#%d\n", afe->cell_result_lookup[index], index);
num_readings++;
}
}

Expand All @@ -290,6 +307,11 @@ StatusCode ltc_afe_impl_read_cells(LtcAfeStorage *afe) {
}
}

if (num_readings != afe->settings.num_cells) {
LOG_CRITICAL("Read %d values instead of %d", num_readings, (uint16_t)afe->settings.num_cells);
return status_code(STATUS_CODE_INTERNAL_ERROR);
}
LOG_DEBUG("read_cells is fine\n");
return STATUS_CODE_OK;
}

Expand All @@ -309,6 +331,7 @@ StatusCode ltc_afe_impl_read_aux(LtcAfeStorage *afe, uint8_t device_cell) {
// Input enabled - store result
uint16_t index = device * LTC_AFE_MAX_CELLS_PER_DEVICE + device_cell;
afe->aux_voltages[afe->aux_result_lookup[index]] = voltage;
LOG_DEBUG("AUX READING#%d is CELL#%d\n", afe->aux_result_lookup[index], index);
}

uint16_t received_pec = SWAP_UINT16(register_data[device].pec);
Expand Down
36 changes: 18 additions & 18 deletions projects/smoke_ltc6811/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@

// To disable logging for an event, set the event name to NULL
static const char *s_event_names[NUM_SMOKE_LTC_EVENTS] = {
[SMOKE_LTC_AFE_TRIGGER_CELL_CONV_EVENT] = "CELL CONVERSION TRIGGERED",
[SMOKE_LTC_AFE_CELL_CONV_COMPLETE_EVENT] = "CELL CONVERSION COMPLETE",
[SMOKE_LTC_AFE_TRIGGER_AUX_CONV_EVENT] = "AUX CONVERSION TRIGGERED",
[SMOKE_LTC_AFE_AUX_CONV_COMPLETE_EVENT] = "AUX CONVERSION COMPLETE",
[SMOKE_LTC_AFE_TRIGGER_CELL_CONV_EVENT] = NULL,
[SMOKE_LTC_AFE_CELL_CONV_COMPLETE_EVENT] = NULL,
[SMOKE_LTC_AFE_TRIGGER_AUX_CONV_EVENT] = NULL,
[SMOKE_LTC_AFE_AUX_CONV_COMPLETE_EVENT] = NULL,
[SMOKE_LTC_AFE_CALLBACK_RUN_EVENT] = "CONVERSION CALLBACK RUN",
[SMOKE_LTC_AFE_FAULT_EVENT] = "FAULT OCCURED"
};
Expand All @@ -36,7 +36,7 @@ typedef struct LtcAfeReadingBound {

static LtcAfeStorage s_afe;
static uint16_t s_result_arr[SMOKE_LTC_AFE_NUM_CELLS] = { 0 };
static size_t s_num_samples = 0;
static uint16_t s_num_samples = 0;
LtcAfeReadingBound s_sample_bounds[SMOKE_LTC_AFE_NUM_CELLS] = { 0 };

static void prv_reset_sample_bounds(void) {
Expand All @@ -47,29 +47,29 @@ static void prv_reset_sample_bounds(void) {
}

static StatusCode prv_extract_and_dump_readings(uint16_t *result_arr, size_t len,
size_t max_samples) {
if (len != sizeof(s_result_arr)) {
LOG_WARN("Expected reading length to be %zu but it was %zu\n", sizeof(s_result_arr), len);
uint16_t max_samples) {
if (len != SMOKE_LTC_AFE_NUM_CELLS) {
LOG_WARN("Expected reading length to be %d but it was %zu\n", SMOKE_LTC_AFE_NUM_CELLS, len);
return STATUS_CODE_INVALID_ARGS;
}

memcpy(s_result_arr, result_arr, len);

if (s_num_samples == 0) {
LOG_DEBUG("INITIAL READINGS:");
LOG_DEBUG("INITIAL READINGS:\n");
} else if (s_num_samples == max_samples - 1) {
LOG_DEBUG("READING STATS:");
LOG_DEBUG("READING STATS:\n");
}

for (size_t cell = 0; cell < SMOKE_LTC_AFE_NUM_CELLS; ++cell) {
for (uint16_t cell = 0; cell < SMOKE_LTC_AFE_NUM_CELLS; ++cell) {
s_sample_bounds[cell].min = MIN(s_result_arr[cell], s_sample_bounds[cell].min);
s_sample_bounds[cell].max = MAX(s_result_arr[cell], s_sample_bounds[cell].max);

if (s_num_samples == 0) {
LOG_DEBUG("CELL#%zu = %d\n", cell, s_result_arr[cell]);
LOG_DEBUG("CELL#%u = %d\n", cell, s_result_arr[cell]);
} else if (s_num_samples == max_samples - 1) {
uint16_t delta = s_sample_bounds[cell].max - s_sample_bounds[cell].min;
LOG_DEBUG("CELL#%zu DELTA %d (MIN=%d, MAX=%d)\n", cell, delta, s_sample_bounds[cell].min,
LOG_DEBUG("CELL#%u DELTA %d (MIN=%d, MAX=%d)\n", cell, delta, s_sample_bounds[cell].min,
s_sample_bounds[cell].max);
}
}
Expand All @@ -91,8 +91,8 @@ static void prv_dump_voltages(uint16_t *result_arr, size_t len, void *context) {
if (s_num_samples != 0) {
if (!status_ok(ltc_afe_request_cell_conversion(&s_afe))) return;
} else {
LOG_DEBUG("==END OF VOLTAGE SAMPLES==");
LOG_DEBUG("==START OF TEMPERATURE SAMPLES==");
LOG_DEBUG("==END OF VOLTAGE SAMPLES==\n");
LOG_DEBUG("==START OF TEMPERATURE SAMPLES==\n");
if (!status_ok(ltc_afe_request_aux_conversion(&s_afe))) return;
}
}
Expand All @@ -106,7 +106,7 @@ static void prv_dump_temps(uint16_t *result_arr, size_t len, void *context) {
if (s_num_samples != 0) {
if (!status_ok(ltc_afe_request_aux_conversion(&s_afe))) return;
} else {
LOG_DEBUG("==END OF TEMPERATURE SAMPLES==");
LOG_DEBUG("==END OF TEMPERATURE SAMPLES==\n");
// TODO(SOFT-222): Could test cell discharge here as well ...
}
}
Expand Down Expand Up @@ -134,7 +134,7 @@ static StatusCode prv_ltc_init(void) {
.num_devices = SMOKE_LTC_AFE_NUM_DEVICES,
.num_cells = SMOKE_LTC_AFE_NUM_CELLS,

.ltc_events = { .trigger_cell_conv_event = SMOKE_LTC_AFE_TRIGGER_CELL_CONV_EVENT,
.ltc_events = { .trigger_cell_conv_event = SMOKE_LTC_AFE_TRIGGER_CELL_CONV_EVENT,
.cell_conv_complete_event = SMOKE_LTC_AFE_CELL_CONV_COMPLETE_EVENT,
.trigger_aux_conv_event = SMOKE_LTC_AFE_TRIGGER_AUX_CONV_EVENT,
.aux_conv_complete_event = SMOKE_LTC_AFE_AUX_CONV_COMPLETE_EVENT,
Expand Down Expand Up @@ -169,7 +169,7 @@ int main(void) {
// Initialize bound variable
prv_reset_sample_bounds();

LOG_DEBUG("==START OF VOLTAGE SAMPLES==");
LOG_DEBUG("==START OF VOLTAGE SAMPLES==\n");
status_ok_or_return(ltc_afe_request_cell_conversion(&s_afe));

Event e = { 0 };
Expand Down