From c1017dae9557f047d264fb52e86e8cb08cd10e5c Mon Sep 17 00:00:00 2001 From: Evan McCarthy Date: Tue, 14 May 2024 20:06:49 -0400 Subject: [PATCH 1/9] current sense soc work It worked at some point, but now doesn't. Current broken point is that configuration doesn't seem to (fully?) apply. VEmpty seems to be set correctly, but the design capacity is reporting back 3000 (30000mah with our rsense) which is the default. I'm not sure why this is happening, it definitely worked at some point today, no idea why it isn't now. --- .../ms-drivers/inc/max17261_fuel_gauge.h | 21 +-- .../ms-drivers/inc/max17261_fuel_gauge_defs.h | 4 +- .../ms-drivers/src/max17261_fuel_gauge.c | 125 ++++++++++++------ projects/bms_carrier/inc/bms.h | 2 + projects/bms_carrier/inc/current_sense.h | 32 ++--- projects/bms_carrier/src/current_sense.c | 52 ++++---- projects/bms_carrier/src/main.c | 12 +- 7 files changed, 145 insertions(+), 103 deletions(-) diff --git a/libraries/ms-drivers/inc/max17261_fuel_gauge.h b/libraries/ms-drivers/inc/max17261_fuel_gauge.h index 51198ba5d..bee817a0c 100644 --- a/libraries/ms-drivers/inc/max17261_fuel_gauge.h +++ b/libraries/ms-drivers/inc/max17261_fuel_gauge.h @@ -22,21 +22,24 @@ typedef struct { I2CPort i2c_port; I2CAddress i2c_address; - uint16_t design_capacity; // LSB = 5.0 (micro Volt Hours / R Sense) - uint16_t empty_voltage; // Only a 9-bit field, LSB = 78.125 (micro Volts) - uint16_t charge_term_current; // LSB = 1.5625 (micro Volts / R Sense) + uint32_t pack_design_cap_mah; + uint16_t cell_empty_voltage_v; + uint16_t charge_term_current_ma; // ref end-of-charge detection https://web.archive.org/web/20220121025712mp_/https://pdfserv.maximintegrated.com/en/an/user-guide-6597-max1726x-m5-ez-rev3-p4.pdf - uint16_t i_thresh_max; - int16_t i_thresh_min; - uint16_t temp_thresh_max; + uint16_t i_thresh_max_a; + int16_t i_thresh_min_a; + uint16_t temp_thresh_max_c; - float r_sense_mohms; // Rsense in micro ohms + float sense_resistor_mohms; } Max17261Settings; typedef struct { Max17261Settings *settings; } Max17261Storage; +// StatusCode max17261_get_reg(Max17261Storage *storage, Max17261Registers reg, uint16_t *value); // TODO TEMP REMOVE +// StatusCode max17261_set_reg(Max17261Storage *storage, Max17261Registers reg, uint16_t value); // TODO TEMP REMOVE + /* @brief Gets the current state of charge given by the max17261 in percentage * @param storage - a pointer to an already initialized Max17261Storage struct * @param soc_pct - state of charge in percentage will be returned in this var @@ -49,14 +52,14 @@ StatusCode max17261_state_of_charge(Max17261Storage *storage, uint16_t *soc_pct) * @param soc_pct - remaining capactity in micro amp hours returned in this var * @return STATUS_CODE_OK on success */ -StatusCode max17261_remaining_capacity(Max17261Storage *storage, uint32_t *rem_cap_uAhr); +StatusCode max17261_remaining_capacity(Max17261Storage *storage, uint32_t *rem_cap_mAh); /* @brief Gets the full charge capacity of the battery in micro amp hours * @param storage - a pointer to an already initialized Max17261Storage struct * @param soc_pct - full charge capacitry in micro amp hours returned in this var * @return STATUS_CODE_OK on success */ -StatusCode max17261_full_capacity(Max17261Storage *storage, uint16_t *full_cap_uAhr); +StatusCode max17261_full_capacity(Max17261Storage *storage, uint32_t *full_cap_mAh); /* @brief Gets the time to empty in milliseconds * @param storage - a pointer to an already initialized Max17261Storage struct diff --git a/libraries/ms-drivers/inc/max17261_fuel_gauge_defs.h b/libraries/ms-drivers/inc/max17261_fuel_gauge_defs.h index edacb7000..446ad2092 100644 --- a/libraries/ms-drivers/inc/max17261_fuel_gauge_defs.h +++ b/libraries/ms-drivers/inc/max17261_fuel_gauge_defs.h @@ -67,6 +67,8 @@ typedef enum { MAX17261_VF_REM_CAP, MAX17261_QH = 0x4D, + MAX17261_SOFT_WAKEUP = 0x60, + MAX17261_STATUS2 = 0xB0, MAX17261_POWER, MAX17261_ID, // UserMem2 @@ -94,7 +96,7 @@ typedef enum { MAX17261_MIN_SYS_VOLTAGE, MAX17261_MPP_CURRENT, MAX17261_SPP_CURRENT, - MAX17261_MODEL_I_CFG, + MAX17261_MODEL_I_CFG = 0xDB, MAX17261_AT_Q_RESIDUAL, MAX17261_AT_TTE, MAX17261_AT_AV_SOC, diff --git a/libraries/ms-drivers/src/max17261_fuel_gauge.c b/libraries/ms-drivers/src/max17261_fuel_gauge.c index d5cdd6ce0..96066c0f2 100644 --- a/libraries/ms-drivers/src/max17261_fuel_gauge.c +++ b/libraries/ms-drivers/src/max17261_fuel_gauge.c @@ -1,14 +1,17 @@ #include "max17261_fuel_gauge.h" +#include + #include "log.h" +#include "delay.h" // See Table 3 on pg.18 of the datasheet -#define PCT_LSB (1.0f / 256) // LSBit is 1/256% -#define CAP_LSB (5.0f / storage->settings->r_sense_mohms) // LSBit is 5 micro Volt hrs / Rsense -#define TIM_LSB (5625U) // LSBit is 5625ms -#define CUR_LSB (1.5625f / storage->settings->r_sense_mohms) // LSBit is 1.5625uA / Rsense -#define VOLT_LSB (1.25f / 16) // LSBit is 1.25mV / 16 -#define TEMP_LSB (1.0f / 256) // LSBit is 1 / 256 C +#define PCT_LSB (1.0f / 256) // (%) LSBit is 1/256% +#define CAP_LSB (5.0f / storage->settings->sense_resistor_mohms) // (mAh) LSBit is 5 mili Volt hrs / Rsense (mAh) +#define TIM_LSB (5625U) // (ms) LSBit is 5625ms +#define CUR_LSB (1.5625f / storage->settings->sense_resistor_mohms) // (mA) LSBit is 1.5625uA / Rsense +#define VOLT_LSB (1.25f / 16) // (mV) LSBit is 1.25mV / 16 +#define TEMP_LSB (1.0f / 256) // (C) LSBit is 1 / 256 C static StatusCode max17261_get_reg(Max17261Storage *storage, Max17261Registers reg, uint16_t *value) { @@ -35,23 +38,38 @@ static StatusCode max17261_set_reg(Max17261Storage *storage, Max17261Registers r } StatusCode max17261_state_of_charge(Max17261Storage *storage, uint16_t *soc_pct) { + // clear lock bit if set - set on state of charge change + uint16_t reg = 0; + max17261_get_reg(storage, MAX17261_STATUS, ®); + if (reg & (1 << 7)) { + max17261_set_reg(storage, MAX17261_STATUS, reg & (uint16_t)~(1 << 7)); + } + + uint16_t status = 0; + status_ok_or_return(max17261_get_reg(storage, MAX17261_STATUS, &status)); + uint16_t soc_reg_val = 0; status_ok_or_return(max17261_get_reg(storage, MAX17261_SOC, &soc_reg_val)); *soc_pct = soc_reg_val * PCT_LSB; return STATUS_CODE_OK; } -StatusCode max17261_remaining_capacity(Max17261Storage *storage, uint32_t *rem_cap_uAhr) { +StatusCode max17261_remaining_capacity(Max17261Storage *storage, uint32_t *rem_cap_mAh) { uint16_t rem_cap_reg_val = 0; status_ok_or_return(max17261_get_reg(storage, MAX17261_CAP, &rem_cap_reg_val)); - *rem_cap_uAhr = rem_cap_reg_val * CAP_LSB; + *rem_cap_mAh = rem_cap_reg_val * CAP_LSB; return STATUS_CODE_OK; } -StatusCode max17261_full_capacity(Max17261Storage *storage, uint16_t *full_cap_uAhr) { +StatusCode max17261_full_capacity(Max17261Storage *storage, uint32_t *full_cap_mAh) { uint16_t full_cap_reg_val = 0; status_ok_or_return(max17261_get_reg(storage, MAX17261_FULL_CAP_REP, &full_cap_reg_val)); - *full_cap_uAhr = full_cap_reg_val * CAP_LSB; + *full_cap_mAh = full_cap_reg_val * CAP_LSB; + + uint16_t design = 0; + max17261_get_reg(storage, MAX17261_DESIGN_CAP, &design); + LOG_DEBUG("DESIGNCAP: %" PRIu32 "mAh\n", (uint32_t)((uint32_t)design * CAP_LSB)); + return STATUS_CODE_OK; } @@ -79,7 +97,11 @@ StatusCode max17261_current(Max17261Storage *storage, int16_t *current_ua) { StatusCode max17261_voltage(Max17261Storage *storage, uint16_t *vcell_mv) { uint16_t vcell_reg_val = 0; status_ok_or_return(max17261_get_reg(storage, MAX17261_VCELL, &vcell_reg_val)); - *vcell_mv = (uint16_t)((float)(vcell_reg_val)*VOLT_LSB / 2.5); // Reports 2.5x the Cell_X voltage + *vcell_mv = (uint16_t)((float)(vcell_reg_val) * VOLT_LSB); + + uint16_t vempty = 0; // TODO remove + max17261_get_reg(storage, MAX17261_V_EMPTY, &vempty); + LOG_DEBUG("VEMPTY: %dmV\n", (int) ((float)vempty * VOLT_LSB)); return STATUS_CODE_OK; } @@ -97,37 +119,60 @@ StatusCode max17261_init(Max17261Storage *storage, Max17261Settings *settings) { storage->settings = settings; - // Configuration for alerts - // Enable current, voltage, and temperature alerts (pg.17 of datasheet, Config (1Dh) Format) - uint16_t config = 0; - status_ok_or_return(max17261_get_reg(storage, MAX17261_CONFIG, &config)); - config |= (1 << 2); - // Enable external temp readings - // config |= (1 << 15); - // config |= (1 << 8); - // config |= (1 << 4); - status_ok_or_return(max17261_set_reg(storage, MAX17261_CONFIG, config)); - // Upper byte is IMAX and lower byte is IMIN - uint16_t current_th = (settings->i_thresh_max << 8) & (settings->i_thresh_min & 0x00FF); - status_ok_or_return(max17261_set_reg(storage, MAX17261_I_ALRT_TH, current_th)); - // Upper byte is TMAX and lower byte is TMIN (leave TMIN as 0 C) - status_ok_or_return( - max17261_set_reg(storage, MAX17261_TEMP_ALRT_THRSH, (settings->temp_thresh_max << 8))); + // ** Based on https://web.archive.org/web/20240330212616/https://pdfserv.maximintegrated.com/en/an/MAX1726x-Software-Implementation-user-guide.pdf + // Step 0 - check if already configured + uint16_t status = 0; + status_ok_or_return(max17261_get_reg(storage, MAX17261_STATUS, &status)); + if ((status & 0x0002) != 0) { + + // Step 1 -- delay until FSTAT.DNR bit == 0 + uint16_t fstat = 0; + status_ok_or_return(max17261_get_reg(storage, MAX17261_FSTAT, &fstat)); + while ((fstat & 1) != 0) { + LOG_DEBUG("data not ready, fstat: %d (%d)\n", fstat, fstat & 1); + status_ok_or_return(max17261_get_reg(storage, MAX17261_FSTAT, &fstat)); + + delay_ms(10); + } + + // Step 2 -- disable hibernation + uint16_t hibcfg = 0; + status_ok_or_return(max17261_get_reg(storage, MAX17261_HIB_CFG, &hibcfg)); + status_ok_or_return(max17261_set_reg(storage, MAX17261_SOFT_WAKEUP, 0x90)); // wakup ic + status_ok_or_return(max17261_set_reg(storage, MAX17261_HIB_CFG, 0x0)); // disable hibernation + status_ok_or_return(max17261_set_reg(storage, MAX17261_SOFT_WAKEUP, 0x0)); // clear wakeup command + + // Step 2.1 -- configure + status_ok_or_return(max17261_set_reg(storage, MAX17261_DESIGN_CAP, settings->pack_design_cap_mah / (uint32_t) CAP_LSB)); + status_ok_or_return(max17261_set_reg(storage, MAX17261_I_CHG_TERM, settings->charge_term_current_ma / CUR_LSB)); + status_ok_or_return(max17261_set_reg(storage, MAX17261_V_EMPTY, settings->cell_empty_voltage_v / VOLT_LSB)); + + status_ok_or_return(max17261_set_reg(storage, MAX17261_SOC_HOLD, 0x0)); // disable SOCHold, not relevant to us + + uint16_t modelcfg = /*refresh*/ (1 << 15) | /*R100*/ (0 << 13) | /*RChg*/ (0 << 10) | (1 << 3); + status_ok_or_return(max17261_set_reg(storage, MAX17261_MODEL_I_CFG, modelcfg)); + + // wait for modelcfg refresh to complete + while (modelcfg & (1 << 15)) { + LOG_DEBUG("modelcfg refresh not cleared: %d\n", modelcfg); + status_ok_or_return(max17261_get_reg(storage, MAX17261_MODEL_I_CFG, &modelcfg)); + delay_ms(10); + } + + // enable hibernation + //status_ok_or_return(max17261_set_reg(storage, MAX17261_HIB_CFG, hibcfg)); + } - // Make sure voltage alerts are disabled (handled by AFEs) (see datasheet pg.25 for disabled - // VAlrtTh value) - status_ok_or_return(max17261_set_reg(storage, MAX17261_VOLT_ALRT_THRSH, (0xFF00))); - // Make sure SOC alerts are disabled (see datasheet pg.26 for disabled SAlrtTh value) - status_ok_or_return(max17261_set_reg(storage, MAX17261_SOC_ALRT_THRSH, (0xFF00))); + // Step 3 + status_ok_or_return(max17261_get_reg(storage, MAX17261_STATUS, &status)); + status_ok_or_return(max17261_set_reg(storage, MAX17261_STATUS, status & (uint16_t)~(1 << 1))); // clear status POR bit - status_ok_or_return(max17261_set_reg(storage, MAX17261_DESIGN_CAP, settings->design_capacity)); - status_ok_or_return( - max17261_set_reg(storage, MAX17261_I_CHG_TERM, settings->charge_term_current)); - uint16_t old_vempty = 0; - status_ok_or_return(max17261_get_reg(storage, MAX17261_V_EMPTY, &old_vempty)); - // the 7 LSBits of the vempty reg is the recovery voltage, the last 9 are the empty voltage - uint16_t new_vempty = (settings->empty_voltage << 7) + (old_vempty & 0x7F); - status_ok_or_return(max17261_set_reg(storage, MAX17261_V_EMPTY, new_vempty)); + LOG_DEBUG("ok\n"); + uint16_t cap = 0; + + max17261_get_reg(storage, MAX17261_DESIGN_CAP, &cap); + LOG_DEBUG("design cap: %d - %d - %d - %d\n", cap, (int) ((float)((float)cap * (float) CAP_LSB)), (uint16_t) settings->pack_design_cap_mah, (int) (settings->pack_design_cap_mah / CAP_LSB)); + delay_ms(5000); return STATUS_CODE_OK; } diff --git a/projects/bms_carrier/inc/bms.h b/projects/bms_carrier/inc/bms.h index f141e52f6..031da3b92 100644 --- a/projects/bms_carrier/inc/bms.h +++ b/projects/bms_carrier/inc/bms.h @@ -21,6 +21,8 @@ typedef struct CurrentStorage { uint16_t voltage; uint16_t temperature; uint32_t fuel_guage_cycle_ms; // Time in ms between conversions (soft timer kicks) + uint32_t mah; + uint32_t full; } CurrentStorage; typedef struct BmsStorage { diff --git a/projects/bms_carrier/inc/current_sense.h b/projects/bms_carrier/inc/current_sense.h index 10cb45fd6..c9b355780 100644 --- a/projects/bms_carrier/inc/current_sense.h +++ b/projects/bms_carrier/inc/current_sense.h @@ -1,8 +1,5 @@ #pragma once -// Stores current readings from the ADS1259 in a ring buffer. -// Requires interrupts and soft timers to be initialized. - #include #include @@ -17,34 +14,23 @@ #define MAX17261_I2C_PORT (I2C_PORT_2) #define MAX17261_I2C_ADDR (0x36) -#define CURRENT_SENSE_R_SENSE_MOHMS (0.5) -#define PACK_CAPACITY_MAH 3000 - -// Capacity in units of 5.0uVh/Rsense -#define MAIN_PACK_DESIGN_CAPACITY (PACK_CAPACITY_MAH * CURRENT_SENSE_R_SENSE_MOHMS / 5) +#define SENSE_RESISTOR_MOHM (0.5) -// LSB = 78.125 (micro Volts) -#define MAIN_PACK_EMPTY_VOLTAGE_MV 2500 -#define MAIN_PACK_EMPTY_VOLTAGE (MAIN_PACK_EMPTY_VOLTAGE_MV / 78.125) +#define PACK_CAPACITY_MAH (160000) // 14V test module, TODO change to reflect pack -#define CHARGE_TERMINATION_CURRENT 0 +#define CELL_EMPTY_VOLTAGE_MV 2500 // LG M50T datasheet -// // TODO (Adel C): Change these values to their actual values -// #define CURRENT_SENSE_R_SENSE_MILLI_OHMS (0.5) -// #define MAIN_PACK_DESIGN_CAPACITY -// (1.0f / CURRENT_SENSE_R_SENSE_MILLI_OHMS) // LSB = 5.0 (micro Volt Hours / R Sense) -// #define MAIN_PACK_EMPTY_VOLTAGE (1.0f / 78.125) // Only a 9-bit field, LSB = 78.125 (micro -// Volts) #define CHARGE_TERMINATION_CURRENT (1.0f / (1.5625f / CURRENT_SENSE_R_SENSE_MILLI_OHMS)) +#define CHARGE_TERMINATION_CURRENT_MA 150 // just a guess, TODO verify // Thresholds for ALRT Pin -#define CURRENT_SENSE_MAX_CURRENT_A (58.2f) // 58.2 Amps -#define CURRENT_SENSE_MIN_CURRENT_A (27.0f) // Actually -27 -#define CURRENT_SENSE_MAX_TEMP (60U) -#define CURRENT_SENSE_MAX_VOLTAGE (15000U) // uints of 10mv +#define CURRENT_SENSE_MAX_CURRENT_A (58.2f) +#define CURRENT_SENSE_MIN_CURRENT_A (27.0f) // Actually -27 +#define CURRENT_SENSE_MAX_TEMP_C (60U) +#define CURRENT_SENSE_MAX_VOLTAGE_V (150U) #define ALRT_PIN_V_RES_MICRO_V (400) #define CELL_X_R1_KOHMS 1780 -#define CELL_X_R2_KOHMS 20 +#define CELL_X_R2_KOHMS 195 // Enum for GPIO IT alerts (just the one pin) typedef enum { CURRENT_SENSE_RUN_CYCLE = 0, ALRT_GPIO_IT, KILLSWITCH_IT } CurrentSenseNotification; diff --git a/projects/bms_carrier/src/current_sense.c b/projects/bms_carrier/src/current_sense.c index 482085ccc..6c2a586bf 100644 --- a/projects/bms_carrier/src/current_sense.c +++ b/projects/bms_carrier/src/current_sense.c @@ -1,6 +1,7 @@ #include "current_sense.h" #include +#include #include "bms.h" #include "bms_carrier_setters.h" @@ -23,14 +24,16 @@ StatusCode prv_fuel_gauge_read() { status |= max17261_state_of_charge(&s_fuel_guage_storage, &s_current_storage->soc); status |= max17261_current(&s_fuel_guage_storage, &s_current_storage->current); status |= max17261_voltage(&s_fuel_guage_storage, &s_current_storage->voltage); - s_current_storage->voltage = (s_current_storage->voltage) * (CELL_X_R2_KOHMS + CELL_X_R1_KOHMS) / - (CELL_X_R2_KOHMS) / 10; // Convert to V -> mV status |= max17261_temp(&s_fuel_guage_storage, &s_current_storage->temperature); + status |= max17261_remaining_capacity(&s_fuel_guage_storage, &s_current_storage->mah); + status |= max17261_full_capacity(&s_fuel_guage_storage, &s_current_storage->full); LOG_DEBUG("SOC: %d\n", s_current_storage->soc); LOG_DEBUG("CURRENT: %d\n", s_current_storage->current); LOG_DEBUG("VOLTAGE: %d\n", s_current_storage->voltage); LOG_DEBUG("TEMP: %d\n", s_current_storage->temperature); + LOG_DEBUG("mah: %" PRIu32 "\n", s_current_storage->mah); + LOG_DEBUG("Full: %" PRIu32 "\n", s_current_storage->full); if (status != STATUS_CODE_OK) { // TODO (Adel): Handle a fuel gauge fault @@ -47,16 +50,16 @@ StatusCode prv_fuel_gauge_read() { set_battery_vt_temperature(s_current_storage->temperature); // TODO (Aryan): Validate these checks - if (s_current_storage->current >= CURRENT_SENSE_MAX_CURRENT_A * 1000) { - fault_bps_set(BMS_FAULT_OVERCURRENT); - return STATUS_CODE_INTERNAL_ERROR; - } else if (s_current_storage->voltage >= CURRENT_SENSE_MAX_VOLTAGE) { - fault_bps_set(BMS_FAULT_OVERVOLTAGE); - return STATUS_CODE_INTERNAL_ERROR; - } else if (s_current_storage->temperature >= CURRENT_SENSE_MAX_TEMP) { - fault_bps_set(BMS_FAULT_OVERTEMP_AMBIENT); - return STATUS_CODE_INTERNAL_ERROR; - } + // if (s_current_storage->current >= CURRENT_SENSE_MAX_CURRENT_A * 1000) { + // fault_bps_set(BMS_FAULT_OVERCURRENT); + // return STATUS_CODE_INTERNAL_ERROR; + // } else if (s_current_storage->voltage >= CURRENT_SENSE_MAX_VOLTAGE) { + // fault_bps_set(BMS_FAULT_OVERVOLTAGE); + // return STATUS_CODE_INTERNAL_ERROR; + // } else if (s_current_storage->temperature >= CURRENT_SENSE_MAX_TEMP) { + // fault_bps_set(BMS_FAULT_OVERTEMP_AMBIENT); + // return STATUS_CODE_INTERNAL_ERROR; + // } return status; } @@ -112,20 +115,21 @@ StatusCode current_sense_init(BmsStorage *bms_storage, I2CSettings *i2c_settings s_fuel_gauge_settings.i2c_port = I2C_PORT_2; s_fuel_gauge_settings.i2c_address = MAX17261_I2C_ADDR; - s_fuel_gauge_settings.charge_term_current = CHARGE_TERMINATION_CURRENT; - s_fuel_gauge_settings.design_capacity = MAIN_PACK_DESIGN_CAPACITY; - s_fuel_gauge_settings.empty_voltage = MAIN_PACK_EMPTY_VOLTAGE; + s_fuel_gauge_settings.charge_term_current_ma = CHARGE_TERMINATION_CURRENT_MA; + s_fuel_gauge_settings.pack_design_cap_mah = PACK_CAPACITY_MAH; + s_fuel_gauge_settings.cell_empty_voltage_v = CELL_EMPTY_VOLTAGE_MV; // Expected MAX current / (uV / uOhmsSense) resolution - s_fuel_gauge_settings.i_thresh_max = - ((CURRENT_SENSE_MAX_CURRENT_A) / (ALRT_PIN_V_RES_MICRO_V / CURRENT_SENSE_R_SENSE_MOHMS)); - // Expected MIN current / (uV / uOhmsSense) resolution - s_fuel_gauge_settings.i_thresh_min = - ((CURRENT_SENSE_MIN_CURRENT_A) / (ALRT_PIN_V_RES_MICRO_V / CURRENT_SENSE_R_SENSE_MOHMS)); - // Interrupt threshold limits are stored in 2s-complement format with 1C resolution - s_fuel_gauge_settings.temp_thresh_max = CURRENT_SENSE_MAX_TEMP; - - s_fuel_gauge_settings.r_sense_mohms = CURRENT_SENSE_R_SENSE_MOHMS; + // TODO impl alert + // s_fuel_gauge_settings.i_thresh_max = + // ((CURRENT_SENSE_MAX_CURRENT_A) / (ALRT_PIN_V_RES_MICRO_V / CURRENT_SENSE_R_SENSE_MOHMS)); + // // Expected MIN current / (uV / uOhmsSense) resolution + // s_fuel_gauge_settings.i_thresh_min = + // ((CURRENT_SENSE_MIN_CURRENT_A) / (ALRT_PIN_V_RES_MICRO_V / CURRENT_SENSE_R_SENSE_MOHMS)); + // // Interrupt threshold limits are stored in 2s-complement format with 1C resolution + // s_fuel_gauge_settings.temp_thresh_max = CURRENT_SENSE_MAX_TEMP; + + s_fuel_gauge_settings.sense_resistor_mohms = SENSE_RESISTOR_MOHM; // Soft timer period for soc & chargin check s_current_storage->fuel_guage_cycle_ms = fuel_guage_cycle_ms; diff --git a/projects/bms_carrier/src/main.c b/projects/bms_carrier/src/main.c index 5eff0a40b..dd3029b4d 100644 --- a/projects/bms_carrier/src/main.c +++ b/projects/bms_carrier/src/main.c @@ -40,9 +40,9 @@ void pre_loop_init() { fault_bps_init(&bms_storage.bps_storage); current_sense_init(&bms_storage, &i2c_settings, FUEL_GAUGE_CYCLE_TIME_MS); // cell_sense_init(&bms_storage.ltc_afe_storage); - aux_sense_init(&bms_storage.aux_storage); - init_bms_relays(); - bms_fan_init(&bms_storage); + //aux_sense_init(&bms_storage.aux_storage); + //init_bms_relays(); + //bms_fan_init(&bms_storage); } void run_fast_cycle() {} @@ -57,15 +57,15 @@ void run_medium_cycle() { wait_tasks(1); // cell_sense_run(); - aux_sense_run(); - bms_run_fan(); + //aux_sense_run(); + //bms_run_fan(); run_can_tx_cycle(); wait_tasks(1); } void run_slow_cycle() { - cell_discharge(&bms_storage.ltc_afe_storage); + //cell_discharge(&bms_storage.ltc_afe_storage); if (fault_bps_get()) { LOG_DEBUG("FAULT_BITMASK: %d\n", fault_bps_get()); From 3ca72420077b0f9127ed12194998955f10018905 Mon Sep 17 00:00:00 2001 From: Evan McCarthy Date: Tue, 14 May 2024 20:47:16 -0400 Subject: [PATCH 2/9] add delay which seems to make it work I have no idea why this works, documentation mentions nothing about this. --- libraries/ms-drivers/src/max17261_fuel_gauge.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/libraries/ms-drivers/src/max17261_fuel_gauge.c b/libraries/ms-drivers/src/max17261_fuel_gauge.c index 96066c0f2..1e9cf073a 100644 --- a/libraries/ms-drivers/src/max17261_fuel_gauge.c +++ b/libraries/ms-drivers/src/max17261_fuel_gauge.c @@ -68,7 +68,6 @@ StatusCode max17261_full_capacity(Max17261Storage *storage, uint32_t *full_cap_m uint16_t design = 0; max17261_get_reg(storage, MAX17261_DESIGN_CAP, &design); - LOG_DEBUG("DESIGNCAP: %" PRIu32 "mAh\n", (uint32_t)((uint32_t)design * CAP_LSB)); return STATUS_CODE_OK; } @@ -99,9 +98,6 @@ StatusCode max17261_voltage(Max17261Storage *storage, uint16_t *vcell_mv) { status_ok_or_return(max17261_get_reg(storage, MAX17261_VCELL, &vcell_reg_val)); *vcell_mv = (uint16_t)((float)(vcell_reg_val) * VOLT_LSB); - uint16_t vempty = 0; // TODO remove - max17261_get_reg(storage, MAX17261_V_EMPTY, &vempty); - LOG_DEBUG("VEMPTY: %dmV\n", (int) ((float)vempty * VOLT_LSB)); return STATUS_CODE_OK; } @@ -142,6 +138,8 @@ StatusCode max17261_init(Max17261Storage *storage, Max17261Settings *settings) { status_ok_or_return(max17261_set_reg(storage, MAX17261_HIB_CFG, 0x0)); // disable hibernation status_ok_or_return(max17261_set_reg(storage, MAX17261_SOFT_WAKEUP, 0x0)); // clear wakeup command + delay_ms(10); // delay that seems to make it work, TODO ???? + // Step 2.1 -- configure status_ok_or_return(max17261_set_reg(storage, MAX17261_DESIGN_CAP, settings->pack_design_cap_mah / (uint32_t) CAP_LSB)); status_ok_or_return(max17261_set_reg(storage, MAX17261_I_CHG_TERM, settings->charge_term_current_ma / CUR_LSB)); @@ -160,19 +158,12 @@ StatusCode max17261_init(Max17261Storage *storage, Max17261Settings *settings) { } // enable hibernation - //status_ok_or_return(max17261_set_reg(storage, MAX17261_HIB_CFG, hibcfg)); + status_ok_or_return(max17261_set_reg(storage, MAX17261_HIB_CFG, hibcfg)); } // Step 3 status_ok_or_return(max17261_get_reg(storage, MAX17261_STATUS, &status)); status_ok_or_return(max17261_set_reg(storage, MAX17261_STATUS, status & (uint16_t)~(1 << 1))); // clear status POR bit - LOG_DEBUG("ok\n"); - uint16_t cap = 0; - - max17261_get_reg(storage, MAX17261_DESIGN_CAP, &cap); - LOG_DEBUG("design cap: %d - %d - %d - %d\n", cap, (int) ((float)((float)cap * (float) CAP_LSB)), (uint16_t) settings->pack_design_cap_mah, (int) (settings->pack_design_cap_mah / CAP_LSB)); - - delay_ms(5000); return STATUS_CODE_OK; } From 5239e7f8e1ba04a003fd1a8aa4f6a540e2390568 Mon Sep 17 00:00:00 2001 From: Evan McCarthy Date: Tue, 14 May 2024 21:03:25 -0400 Subject: [PATCH 3/9] add back alerts - untested --- .../ms-drivers/src/max17261_fuel_gauge.c | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/libraries/ms-drivers/src/max17261_fuel_gauge.c b/libraries/ms-drivers/src/max17261_fuel_gauge.c index 1e9cf073a..8863fedc4 100644 --- a/libraries/ms-drivers/src/max17261_fuel_gauge.c +++ b/libraries/ms-drivers/src/max17261_fuel_gauge.c @@ -137,7 +137,7 @@ StatusCode max17261_init(Max17261Storage *storage, Max17261Settings *settings) { status_ok_or_return(max17261_set_reg(storage, MAX17261_SOFT_WAKEUP, 0x90)); // wakup ic status_ok_or_return(max17261_set_reg(storage, MAX17261_HIB_CFG, 0x0)); // disable hibernation status_ok_or_return(max17261_set_reg(storage, MAX17261_SOFT_WAKEUP, 0x0)); // clear wakeup command - + delay_ms(10); // delay that seems to make it work, TODO ???? // Step 2.1 -- configure @@ -147,6 +147,8 @@ StatusCode max17261_init(Max17261Storage *storage, Max17261Settings *settings) { status_ok_or_return(max17261_set_reg(storage, MAX17261_SOC_HOLD, 0x0)); // disable SOCHold, not relevant to us + + uint16_t modelcfg = /*refresh*/ (1 << 15) | /*R100*/ (0 << 13) | /*RChg*/ (0 << 10) | (1 << 3); status_ok_or_return(max17261_set_reg(storage, MAX17261_MODEL_I_CFG, modelcfg)); @@ -157,6 +159,24 @@ StatusCode max17261_init(Max17261Storage *storage, Max17261Settings *settings) { delay_ms(10); } + // Configure alerts + uint16_t config = 0; + status_ok_or_return(max17261_get_reg(storage, MAX17261_CONFIG, &config)); + config |= (1 << 2); // enable alerts + config |= (1 << 4); // thermal alerts + // config |= (1 << 8); // external temp measurement TODO: hardware / uncomment + status_ok_or_return(max17261_set_reg(storage, MAX17261_CONFIG, &config)); + + uint16_t current_th = (settings->i_thresh_max_a << 8) & (settings->i_thresh_min_a & 0x00FF); + status_ok_or_return(max17261_set_reg(storage, MAX17261_I_ALRT_TH, current_th)); + + status_ok_or_return(max17261_set_reg(storage, MAX17261_TEMP_ALRT_THRSH, (settings->temp_thresh_max_c < 8))); + + // Disable voltage alert (handled by AFE) + status_ok_or_return(max17261_set_reg(storage, MAX17261_VOLT_ALRT_THRSH, 0xFF00)); + // Disable state of charge alerting + status_ok_or_return(max17261_set_reg(storage, MAX17261_SOC_ALRT_THRSH, 0xFF00)); + // enable hibernation status_ok_or_return(max17261_set_reg(storage, MAX17261_HIB_CFG, hibcfg)); } From 233982f1520e8ee78925fbdef0af8aa0fa7f0996 Mon Sep 17 00:00:00 2001 From: Mitch Ostler Date: Wed, 15 May 2024 22:35:02 +0000 Subject: [PATCH 4/9] add persist functionality --- .../ms-drivers/inc/max17261_fuel_gauge.h | 16 ++++++++--- .../ms-drivers/src/max17261_fuel_gauge.c | 27 +++++++++++++++++-- projects/bms_carrier/inc/current_sense.h | 2 ++ projects/bms_carrier/src/current_sense.c | 22 ++++++++++++--- projects/bms_carrier/src/main.c | 8 +++--- 5 files changed, 63 insertions(+), 12 deletions(-) diff --git a/libraries/ms-drivers/inc/max17261_fuel_gauge.h b/libraries/ms-drivers/inc/max17261_fuel_gauge.h index bee817a0c..af5c8a059 100644 --- a/libraries/ms-drivers/inc/max17261_fuel_gauge.h +++ b/libraries/ms-drivers/inc/max17261_fuel_gauge.h @@ -37,8 +37,15 @@ typedef struct { Max17261Settings *settings; } Max17261Storage; -// StatusCode max17261_get_reg(Max17261Storage *storage, Max17261Registers reg, uint16_t *value); // TODO TEMP REMOVE -// StatusCode max17261_set_reg(Max17261Storage *storage, Max17261Registers reg, uint16_t value); // TODO TEMP REMOVE +// Storage for parameters learned by fuel guage +// Must be stored in flash to keep up to date after power cycle +typedef struct Max27261Params { + uint16_t rcomp0; + uint16_t tempco; + uint16_t fullcaprep; + uint16_t cycles; + uint16_t fullcapnom; +} Max27261Params; /* @brief Gets the current state of charge given by the max17261 in percentage * @param storage - a pointer to an already initialized Max17261Storage struct @@ -101,4 +108,7 @@ StatusCode max17261_temp(Max17261Storage *storage, uint16_t *temp_c); * @param settings - populated settings struct * @return STATUS_CODE_OK on success */ -StatusCode max17261_init(Max17261Storage *storage, Max17261Settings *settings); +StatusCode max17261_init(Max17261Storage *storage, Max17261Settings *settings, Max27261Params *params); + +StatusCode max17261_set_learned_params(Max17261Storage *storage, Max27261Params *params); +StatusCode max17261_get_learned_params(Max17261Storage *storage, Max27261Params *params); diff --git a/libraries/ms-drivers/src/max17261_fuel_gauge.c b/libraries/ms-drivers/src/max17261_fuel_gauge.c index 8863fedc4..a4814b3fb 100644 --- a/libraries/ms-drivers/src/max17261_fuel_gauge.c +++ b/libraries/ms-drivers/src/max17261_fuel_gauge.c @@ -68,6 +68,7 @@ StatusCode max17261_full_capacity(Max17261Storage *storage, uint32_t *full_cap_m uint16_t design = 0; max17261_get_reg(storage, MAX17261_DESIGN_CAP, &design); + LOG_DEBUG("DES CAP: %d\n", design); return STATUS_CODE_OK; } @@ -108,7 +109,25 @@ StatusCode max17261_temp(Max17261Storage *storage, uint16_t *temp_c) { return STATUS_CODE_OK; } -StatusCode max17261_init(Max17261Storage *storage, Max17261Settings *settings) { +StatusCode max17261_get_learned_params(Max17261Storage *storage, Max27261Params *params) { + status_ok_or_return(max17261_get_reg(storage, MAX17261_R_COMP0, ¶ms->rcomp0)); + status_ok_or_return(max17261_get_reg(storage, MAX17261_TEMP_CO, ¶ms->tempco)); + status_ok_or_return(max17261_get_reg(storage, MAX17261_FULL_CAP_REP, ¶ms->fullcaprep)); + status_ok_or_return(max17261_get_reg(storage, MAX17261_CYCLES, ¶ms->cycles)); + status_ok_or_return(max17261_get_reg(storage, MAX17261_FULL_CAP_NOM, ¶ms->fullcapnom)); + return STATUS_CODE_OK; +} + +StatusCode max17261_set_learned_params(Max17261Storage *storage, Max27261Params *params) { + status_ok_or_return(max17261_set_reg(storage, MAX17261_R_COMP0, params->rcomp0)); + status_ok_or_return(max17261_set_reg(storage, MAX17261_TEMP_CO, params->tempco)); + //status_ok_or_return(max17261_set_reg(storage, MAX17261_FULL_CAP_REP, params->fullcaprep)); + status_ok_or_return(max17261_set_reg(storage, MAX17261_CYCLES, params->cycles)); + status_ok_or_return(max17261_set_reg(storage, MAX17261_FULL_CAP_NOM, params->fullcapnom)); + return STATUS_CODE_OK; +} + +StatusCode max17261_init(Max17261Storage *storage, Max17261Settings *settings, Max27261Params *params) { if (settings->i2c_port >= NUM_I2C_PORTS) { return STATUS_CODE_INVALID_ARGS; } @@ -165,7 +184,7 @@ StatusCode max17261_init(Max17261Storage *storage, Max17261Settings *settings) { config |= (1 << 2); // enable alerts config |= (1 << 4); // thermal alerts // config |= (1 << 8); // external temp measurement TODO: hardware / uncomment - status_ok_or_return(max17261_set_reg(storage, MAX17261_CONFIG, &config)); + status_ok_or_return(max17261_set_reg(storage, MAX17261_CONFIG, config)); uint16_t current_th = (settings->i_thresh_max_a << 8) & (settings->i_thresh_min_a & 0x00FF); status_ok_or_return(max17261_set_reg(storage, MAX17261_I_ALRT_TH, current_th)); @@ -185,5 +204,9 @@ StatusCode max17261_init(Max17261Storage *storage, Max17261Settings *settings) { status_ok_or_return(max17261_get_reg(storage, MAX17261_STATUS, &status)); status_ok_or_return(max17261_set_reg(storage, MAX17261_STATUS, status & (uint16_t)~(1 << 1))); // clear status POR bit + if (params) { + status_ok_or_return(max17261_set_learned_params(storage, params)); + } + return STATUS_CODE_OK; } diff --git a/projects/bms_carrier/inc/current_sense.h b/projects/bms_carrier/inc/current_sense.h index c9b355780..4e5c7496a 100644 --- a/projects/bms_carrier/inc/current_sense.h +++ b/projects/bms_carrier/inc/current_sense.h @@ -32,6 +32,8 @@ #define CELL_X_R1_KOHMS 1780 #define CELL_X_R2_KOHMS 195 +#define CURRENT_SENSE_STORE_FLASH NUM_FLASH_PAGES - 1 + // Enum for GPIO IT alerts (just the one pin) typedef enum { CURRENT_SENSE_RUN_CYCLE = 0, ALRT_GPIO_IT, KILLSWITCH_IT } CurrentSenseNotification; diff --git a/projects/bms_carrier/src/current_sense.c b/projects/bms_carrier/src/current_sense.c index 6c2a586bf..a02912670 100644 --- a/projects/bms_carrier/src/current_sense.c +++ b/projects/bms_carrier/src/current_sense.c @@ -8,15 +8,23 @@ #include "exported_enums.h" #include "fault_bps.h" #include "gpio_it.h" +#include "persist.h" #include "interrupt.h" #include "log.h" #include "tasks.h" +// Update stored learned params every 30 sec +#define UPDATE_FLASH_PARAMS_PERIOD_MS 10000 + static Max17261Storage s_fuel_guage_storage; static Max17261Settings s_fuel_gauge_settings; static CurrentStorage *s_current_storage; static bool s_is_charging; +static PersistStorage s_persist; +static Max27261Params s_fuel_params; +static TickType_t s_last_params_update; + // Periodically read and update the SoC of the car & update charging bool StatusCode prv_fuel_gauge_read() { StatusCode status = STATUS_CODE_OK; @@ -61,6 +69,13 @@ StatusCode prv_fuel_gauge_read() { // return STATUS_CODE_INTERNAL_ERROR; // } + // Commit params info periodically + if (xTaskGetTickCount() > s_last_params_update + pdMS_TO_TICKS(UPDATE_FLASH_PARAMS_PERIOD_MS)) { + LOG_DEBUG("Updating params\n"); + s_last_params_update = xTaskGetTickCount(); + max17261_get_learned_params(&s_fuel_guage_storage, &s_fuel_params); + persist_commit(&s_persist); + } return status; } @@ -75,8 +90,7 @@ TASK(current_sense, TASK_STACK_256) { // fault_bps_set(BMS_FAULT_COMMS_LOSS_CURR_SENSE); } else if (notification & 1 << KILLSWITCH_IT) { fault_bps_set(BMS_FAULT_KILLSWITCH); - } - + } prv_fuel_gauge_read(); send_task_end(); } @@ -134,7 +148,9 @@ StatusCode current_sense_init(BmsStorage *bms_storage, I2CSettings *i2c_settings // Soft timer period for soc & chargin check s_current_storage->fuel_guage_cycle_ms = fuel_guage_cycle_ms; - status_ok_or_return(max17261_init(&s_fuel_guage_storage, &s_fuel_gauge_settings)); + persist_init(&s_persist, CURRENT_SENSE_STORE_FLASH, &s_fuel_params, sizeof(s_fuel_params), false); + status_ok_or_return(max17261_init(&s_fuel_guage_storage, &s_fuel_gauge_settings, &s_fuel_params)); + tasks_init_task(current_sense, TASK_PRIORITY(2), NULL); return STATUS_CODE_OK; } diff --git a/projects/bms_carrier/src/main.c b/projects/bms_carrier/src/main.c index dd3029b4d..c88430816 100644 --- a/projects/bms_carrier/src/main.c +++ b/projects/bms_carrier/src/main.c @@ -48,8 +48,8 @@ void pre_loop_init() { void run_fast_cycle() {} void run_medium_cycle() { - run_can_rx_cycle(); - wait_tasks(1); + //run_can_rx_cycle(); + //wait_tasks(1); // cell_conversions(); // wait_tasks(1); @@ -60,8 +60,8 @@ void run_medium_cycle() { //aux_sense_run(); //bms_run_fan(); - run_can_tx_cycle(); - wait_tasks(1); + //run_can_tx_cycle(); + //wait_tasks(1); } void run_slow_cycle() { From c62abd173967c535bfad88db7f2695d0f953ea58 Mon Sep 17 00:00:00 2001 From: Evan McCarthy Date: Thu, 16 May 2024 16:20:45 -0400 Subject: [PATCH 5/9] format --- .../ms-drivers/inc/max17261_fuel_gauge.h | 7 +- .../ms-drivers/src/max17261_fuel_gauge.c | 68 +++++++++++-------- projects/bms_carrier/inc/current_sense.h | 8 +-- projects/bms_carrier/src/current_sense.c | 14 ++-- projects/bms_carrier/src/main.c | 20 +++--- 5 files changed, 64 insertions(+), 53 deletions(-) diff --git a/libraries/ms-drivers/inc/max17261_fuel_gauge.h b/libraries/ms-drivers/inc/max17261_fuel_gauge.h index af5c8a059..8856c3f2a 100644 --- a/libraries/ms-drivers/inc/max17261_fuel_gauge.h +++ b/libraries/ms-drivers/inc/max17261_fuel_gauge.h @@ -24,7 +24,9 @@ typedef struct { uint32_t pack_design_cap_mah; uint16_t cell_empty_voltage_v; - uint16_t charge_term_current_ma; // ref end-of-charge detection https://web.archive.org/web/20220121025712mp_/https://pdfserv.maximintegrated.com/en/an/user-guide-6597-max1726x-m5-ez-rev3-p4.pdf + uint16_t + charge_term_current_ma; // ref end-of-charge detection + // https://web.archive.org/web/20220121025712mp_/https://pdfserv.maximintegrated.com/en/an/user-guide-6597-max1726x-m5-ez-rev3-p4.pdf uint16_t i_thresh_max_a; int16_t i_thresh_min_a; @@ -108,7 +110,8 @@ StatusCode max17261_temp(Max17261Storage *storage, uint16_t *temp_c); * @param settings - populated settings struct * @return STATUS_CODE_OK on success */ -StatusCode max17261_init(Max17261Storage *storage, Max17261Settings *settings, Max27261Params *params); +StatusCode max17261_init(Max17261Storage *storage, Max17261Settings *settings, + Max27261Params *params); StatusCode max17261_set_learned_params(Max17261Storage *storage, Max27261Params *params); StatusCode max17261_get_learned_params(Max17261Storage *storage, Max27261Params *params); diff --git a/libraries/ms-drivers/src/max17261_fuel_gauge.c b/libraries/ms-drivers/src/max17261_fuel_gauge.c index a4814b3fb..65cd653c3 100644 --- a/libraries/ms-drivers/src/max17261_fuel_gauge.c +++ b/libraries/ms-drivers/src/max17261_fuel_gauge.c @@ -2,16 +2,18 @@ #include -#include "log.h" #include "delay.h" +#include "log.h" // See Table 3 on pg.18 of the datasheet -#define PCT_LSB (1.0f / 256) // (%) LSBit is 1/256% -#define CAP_LSB (5.0f / storage->settings->sense_resistor_mohms) // (mAh) LSBit is 5 mili Volt hrs / Rsense (mAh) -#define TIM_LSB (5625U) // (ms) LSBit is 5625ms -#define CUR_LSB (1.5625f / storage->settings->sense_resistor_mohms) // (mA) LSBit is 1.5625uA / Rsense -#define VOLT_LSB (1.25f / 16) // (mV) LSBit is 1.25mV / 16 -#define TEMP_LSB (1.0f / 256) // (C) LSBit is 1 / 256 C +#define PCT_LSB (1.0f / 256) // (%) LSBit is 1/256% +#define CAP_LSB \ + (5.0f / storage->settings->sense_resistor_mohms) // (mAh) LSBit is 5 mili Volt hrs / Rsense (mAh) +#define TIM_LSB (5625U) // (ms) LSBit is 5625ms +#define CUR_LSB \ + (1.5625f / storage->settings->sense_resistor_mohms) // (mA) LSBit is 1.5625uA / Rsense +#define VOLT_LSB (1.25f / 16) // (mV) LSBit is 1.25mV / 16 +#define TEMP_LSB (1.0f / 256) // (C) LSBit is 1 / 256 C static StatusCode max17261_get_reg(Max17261Storage *storage, Max17261Registers reg, uint16_t *value) { @@ -42,7 +44,7 @@ StatusCode max17261_state_of_charge(Max17261Storage *storage, uint16_t *soc_pct) uint16_t reg = 0; max17261_get_reg(storage, MAX17261_STATUS, ®); if (reg & (1 << 7)) { - max17261_set_reg(storage, MAX17261_STATUS, reg & (uint16_t)~(1 << 7)); + max17261_set_reg(storage, MAX17261_STATUS, reg & (uint16_t) ~(1 << 7)); } uint16_t status = 0; @@ -65,7 +67,7 @@ StatusCode max17261_full_capacity(Max17261Storage *storage, uint32_t *full_cap_m uint16_t full_cap_reg_val = 0; status_ok_or_return(max17261_get_reg(storage, MAX17261_FULL_CAP_REP, &full_cap_reg_val)); *full_cap_mAh = full_cap_reg_val * CAP_LSB; - + uint16_t design = 0; max17261_get_reg(storage, MAX17261_DESIGN_CAP, &design); LOG_DEBUG("DES CAP: %d\n", design); @@ -97,7 +99,7 @@ StatusCode max17261_current(Max17261Storage *storage, int16_t *current_ua) { StatusCode max17261_voltage(Max17261Storage *storage, uint16_t *vcell_mv) { uint16_t vcell_reg_val = 0; status_ok_or_return(max17261_get_reg(storage, MAX17261_VCELL, &vcell_reg_val)); - *vcell_mv = (uint16_t)((float)(vcell_reg_val) * VOLT_LSB); + *vcell_mv = (uint16_t)((float)(vcell_reg_val)*VOLT_LSB); return STATUS_CODE_OK; } @@ -121,25 +123,26 @@ StatusCode max17261_get_learned_params(Max17261Storage *storage, Max27261Params StatusCode max17261_set_learned_params(Max17261Storage *storage, Max27261Params *params) { status_ok_or_return(max17261_set_reg(storage, MAX17261_R_COMP0, params->rcomp0)); status_ok_or_return(max17261_set_reg(storage, MAX17261_TEMP_CO, params->tempco)); - //status_ok_or_return(max17261_set_reg(storage, MAX17261_FULL_CAP_REP, params->fullcaprep)); + // status_ok_or_return(max17261_set_reg(storage, MAX17261_FULL_CAP_REP, params->fullcaprep)); status_ok_or_return(max17261_set_reg(storage, MAX17261_CYCLES, params->cycles)); status_ok_or_return(max17261_set_reg(storage, MAX17261_FULL_CAP_NOM, params->fullcapnom)); return STATUS_CODE_OK; } -StatusCode max17261_init(Max17261Storage *storage, Max17261Settings *settings, Max27261Params *params) { +StatusCode max17261_init(Max17261Storage *storage, Max17261Settings *settings, + Max27261Params *params) { if (settings->i2c_port >= NUM_I2C_PORTS) { return STATUS_CODE_INVALID_ARGS; } storage->settings = settings; - // ** Based on https://web.archive.org/web/20240330212616/https://pdfserv.maximintegrated.com/en/an/MAX1726x-Software-Implementation-user-guide.pdf + // ** Based on + // https://web.archive.org/web/20240330212616/https://pdfserv.maximintegrated.com/en/an/MAX1726x-Software-Implementation-user-guide.pdf // Step 0 - check if already configured uint16_t status = 0; status_ok_or_return(max17261_get_reg(storage, MAX17261_STATUS, &status)); if ((status & 0x0002) != 0) { - // Step 1 -- delay until FSTAT.DNR bit == 0 uint16_t fstat = 0; status_ok_or_return(max17261_get_reg(storage, MAX17261_FSTAT, &fstat)); @@ -153,20 +156,23 @@ StatusCode max17261_init(Max17261Storage *storage, Max17261Settings *settings, M // Step 2 -- disable hibernation uint16_t hibcfg = 0; status_ok_or_return(max17261_get_reg(storage, MAX17261_HIB_CFG, &hibcfg)); - status_ok_or_return(max17261_set_reg(storage, MAX17261_SOFT_WAKEUP, 0x90)); // wakup ic + status_ok_or_return(max17261_set_reg(storage, MAX17261_SOFT_WAKEUP, 0x90)); // wakup ic status_ok_or_return(max17261_set_reg(storage, MAX17261_HIB_CFG, 0x0)); // disable hibernation - status_ok_or_return(max17261_set_reg(storage, MAX17261_SOFT_WAKEUP, 0x0)); // clear wakeup command - - delay_ms(10); // delay that seems to make it work, TODO ???? + status_ok_or_return( + max17261_set_reg(storage, MAX17261_SOFT_WAKEUP, 0x0)); // clear wakeup command - // Step 2.1 -- configure - status_ok_or_return(max17261_set_reg(storage, MAX17261_DESIGN_CAP, settings->pack_design_cap_mah / (uint32_t) CAP_LSB)); - status_ok_or_return(max17261_set_reg(storage, MAX17261_I_CHG_TERM, settings->charge_term_current_ma / CUR_LSB)); - status_ok_or_return(max17261_set_reg(storage, MAX17261_V_EMPTY, settings->cell_empty_voltage_v / VOLT_LSB)); - - status_ok_or_return(max17261_set_reg(storage, MAX17261_SOC_HOLD, 0x0)); // disable SOCHold, not relevant to us + delay_ms(10); // delay that seems to make it work, TODO ???? + // Step 2.1 -- configure + status_ok_or_return(max17261_set_reg(storage, MAX17261_DESIGN_CAP, + settings->pack_design_cap_mah / (uint32_t)CAP_LSB)); + status_ok_or_return( + max17261_set_reg(storage, MAX17261_I_CHG_TERM, settings->charge_term_current_ma / CUR_LSB)); + status_ok_or_return( + max17261_set_reg(storage, MAX17261_V_EMPTY, settings->cell_empty_voltage_v / VOLT_LSB)); + status_ok_or_return( + max17261_set_reg(storage, MAX17261_SOC_HOLD, 0x0)); // disable SOCHold, not relevant to us uint16_t modelcfg = /*refresh*/ (1 << 15) | /*R100*/ (0 << 13) | /*RChg*/ (0 << 10) | (1 << 3); status_ok_or_return(max17261_set_reg(storage, MAX17261_MODEL_I_CFG, modelcfg)); @@ -181,28 +187,30 @@ StatusCode max17261_init(Max17261Storage *storage, Max17261Settings *settings, M // Configure alerts uint16_t config = 0; status_ok_or_return(max17261_get_reg(storage, MAX17261_CONFIG, &config)); - config |= (1 << 2); // enable alerts - config |= (1 << 4); // thermal alerts + config |= (1 << 2); // enable alerts + config |= (1 << 4); // thermal alerts // config |= (1 << 8); // external temp measurement TODO: hardware / uncomment status_ok_or_return(max17261_set_reg(storage, MAX17261_CONFIG, config)); uint16_t current_th = (settings->i_thresh_max_a << 8) & (settings->i_thresh_min_a & 0x00FF); status_ok_or_return(max17261_set_reg(storage, MAX17261_I_ALRT_TH, current_th)); - status_ok_or_return(max17261_set_reg(storage, MAX17261_TEMP_ALRT_THRSH, (settings->temp_thresh_max_c < 8))); - + status_ok_or_return( + max17261_set_reg(storage, MAX17261_TEMP_ALRT_THRSH, (settings->temp_thresh_max_c < 8))); + // Disable voltage alert (handled by AFE) status_ok_or_return(max17261_set_reg(storage, MAX17261_VOLT_ALRT_THRSH, 0xFF00)); // Disable state of charge alerting status_ok_or_return(max17261_set_reg(storage, MAX17261_SOC_ALRT_THRSH, 0xFF00)); // enable hibernation - status_ok_or_return(max17261_set_reg(storage, MAX17261_HIB_CFG, hibcfg)); + status_ok_or_return(max17261_set_reg(storage, MAX17261_HIB_CFG, hibcfg)); } // Step 3 status_ok_or_return(max17261_get_reg(storage, MAX17261_STATUS, &status)); - status_ok_or_return(max17261_set_reg(storage, MAX17261_STATUS, status & (uint16_t)~(1 << 1))); // clear status POR bit + status_ok_or_return(max17261_set_reg(storage, MAX17261_STATUS, + status & (uint16_t) ~(1 << 1))); // clear status POR bit if (params) { status_ok_or_return(max17261_set_learned_params(storage, params)); diff --git a/projects/bms_carrier/inc/current_sense.h b/projects/bms_carrier/inc/current_sense.h index 4e5c7496a..4ded016da 100644 --- a/projects/bms_carrier/inc/current_sense.h +++ b/projects/bms_carrier/inc/current_sense.h @@ -16,15 +16,15 @@ #define SENSE_RESISTOR_MOHM (0.5) -#define PACK_CAPACITY_MAH (160000) // 14V test module, TODO change to reflect pack +#define PACK_CAPACITY_MAH (160000) // 14V test module, TODO change to reflect pack -#define CELL_EMPTY_VOLTAGE_MV 2500 // LG M50T datasheet +#define CELL_EMPTY_VOLTAGE_MV 2500 // LG M50T datasheet -#define CHARGE_TERMINATION_CURRENT_MA 150 // just a guess, TODO verify +#define CHARGE_TERMINATION_CURRENT_MA 150 // just a guess, TODO verify // Thresholds for ALRT Pin #define CURRENT_SENSE_MAX_CURRENT_A (58.2f) -#define CURRENT_SENSE_MIN_CURRENT_A (27.0f) // Actually -27 +#define CURRENT_SENSE_MIN_CURRENT_A (27.0f) // Actually -27 #define CURRENT_SENSE_MAX_TEMP_C (60U) #define CURRENT_SENSE_MAX_VOLTAGE_V (150U) #define ALRT_PIN_V_RES_MICRO_V (400) diff --git a/projects/bms_carrier/src/current_sense.c b/projects/bms_carrier/src/current_sense.c index a02912670..aa644b4e4 100644 --- a/projects/bms_carrier/src/current_sense.c +++ b/projects/bms_carrier/src/current_sense.c @@ -1,16 +1,16 @@ #include "current_sense.h" -#include #include +#include #include "bms.h" #include "bms_carrier_setters.h" #include "exported_enums.h" #include "fault_bps.h" #include "gpio_it.h" -#include "persist.h" #include "interrupt.h" #include "log.h" +#include "persist.h" #include "tasks.h" // Update stored learned params every 30 sec @@ -72,9 +72,9 @@ StatusCode prv_fuel_gauge_read() { // Commit params info periodically if (xTaskGetTickCount() > s_last_params_update + pdMS_TO_TICKS(UPDATE_FLASH_PARAMS_PERIOD_MS)) { LOG_DEBUG("Updating params\n"); - s_last_params_update = xTaskGetTickCount(); - max17261_get_learned_params(&s_fuel_guage_storage, &s_fuel_params); - persist_commit(&s_persist); + s_last_params_update = xTaskGetTickCount(); + max17261_get_learned_params(&s_fuel_guage_storage, &s_fuel_params); + persist_commit(&s_persist); } return status; } @@ -90,7 +90,7 @@ TASK(current_sense, TASK_STACK_256) { // fault_bps_set(BMS_FAULT_COMMS_LOSS_CURR_SENSE); } else if (notification & 1 << KILLSWITCH_IT) { fault_bps_set(BMS_FAULT_KILLSWITCH); - } + } prv_fuel_gauge_read(); send_task_end(); } @@ -150,7 +150,7 @@ StatusCode current_sense_init(BmsStorage *bms_storage, I2CSettings *i2c_settings persist_init(&s_persist, CURRENT_SENSE_STORE_FLASH, &s_fuel_params, sizeof(s_fuel_params), false); status_ok_or_return(max17261_init(&s_fuel_guage_storage, &s_fuel_gauge_settings, &s_fuel_params)); - + tasks_init_task(current_sense, TASK_PRIORITY(2), NULL); return STATUS_CODE_OK; } diff --git a/projects/bms_carrier/src/main.c b/projects/bms_carrier/src/main.c index c88430816..cb82876b3 100644 --- a/projects/bms_carrier/src/main.c +++ b/projects/bms_carrier/src/main.c @@ -40,16 +40,16 @@ void pre_loop_init() { fault_bps_init(&bms_storage.bps_storage); current_sense_init(&bms_storage, &i2c_settings, FUEL_GAUGE_CYCLE_TIME_MS); // cell_sense_init(&bms_storage.ltc_afe_storage); - //aux_sense_init(&bms_storage.aux_storage); - //init_bms_relays(); - //bms_fan_init(&bms_storage); + // aux_sense_init(&bms_storage.aux_storage); + // init_bms_relays(); + // bms_fan_init(&bms_storage); } void run_fast_cycle() {} void run_medium_cycle() { - //run_can_rx_cycle(); - //wait_tasks(1); + // run_can_rx_cycle(); + // wait_tasks(1); // cell_conversions(); // wait_tasks(1); @@ -57,15 +57,15 @@ void run_medium_cycle() { wait_tasks(1); // cell_sense_run(); - //aux_sense_run(); - //bms_run_fan(); + // aux_sense_run(); + // bms_run_fan(); - //run_can_tx_cycle(); - //wait_tasks(1); + // run_can_tx_cycle(); + // wait_tasks(1); } void run_slow_cycle() { - //cell_discharge(&bms_storage.ltc_afe_storage); + // cell_discharge(&bms_storage.ltc_afe_storage); if (fault_bps_get()) { LOG_DEBUG("FAULT_BITMASK: %d\n", fault_bps_get()); From d3ea6361bb2d6d3e4838b5334a8bed214141d676 Mon Sep 17 00:00:00 2001 From: Evan McCarthy Date: Thu, 16 May 2024 16:36:09 -0400 Subject: [PATCH 6/9] cleanup --- .../ms-drivers/inc/max17261_fuel_gauge_defs.h | 2 +- .../ms-drivers/src/max17261_fuel_gauge.c | 23 ++++++++------- projects/bms_carrier/inc/bms.h | 2 +- projects/bms_carrier/src/current_sense.c | 7 +++-- projects/bms_carrier/src/main.c | 28 +++++++++---------- 5 files changed, 33 insertions(+), 29 deletions(-) diff --git a/libraries/ms-drivers/inc/max17261_fuel_gauge_defs.h b/libraries/ms-drivers/inc/max17261_fuel_gauge_defs.h index 446ad2092..1320ffc17 100644 --- a/libraries/ms-drivers/inc/max17261_fuel_gauge_defs.h +++ b/libraries/ms-drivers/inc/max17261_fuel_gauge_defs.h @@ -96,7 +96,7 @@ typedef enum { MAX17261_MIN_SYS_VOLTAGE, MAX17261_MPP_CURRENT, MAX17261_SPP_CURRENT, - MAX17261_MODEL_I_CFG = 0xDB, + MAX17261_MODEL_I_CFG, MAX17261_AT_Q_RESIDUAL, MAX17261_AT_TTE, MAX17261_AT_AV_SOC, diff --git a/libraries/ms-drivers/src/max17261_fuel_gauge.c b/libraries/ms-drivers/src/max17261_fuel_gauge.c index 65cd653c3..47f3099bd 100644 --- a/libraries/ms-drivers/src/max17261_fuel_gauge.c +++ b/libraries/ms-drivers/src/max17261_fuel_gauge.c @@ -68,10 +68,6 @@ StatusCode max17261_full_capacity(Max17261Storage *storage, uint32_t *full_cap_m status_ok_or_return(max17261_get_reg(storage, MAX17261_FULL_CAP_REP, &full_cap_reg_val)); *full_cap_mAh = full_cap_reg_val * CAP_LSB; - uint16_t design = 0; - max17261_get_reg(storage, MAX17261_DESIGN_CAP, &design); - LOG_DEBUG("DES CAP: %d\n", design); - return STATUS_CODE_OK; } @@ -123,6 +119,8 @@ StatusCode max17261_get_learned_params(Max17261Storage *storage, Max27261Params StatusCode max17261_set_learned_params(Max17261Storage *storage, Max27261Params *params) { status_ok_or_return(max17261_set_reg(storage, MAX17261_R_COMP0, params->rcomp0)); status_ok_or_return(max17261_set_reg(storage, MAX17261_TEMP_CO, params->tempco)); + // somehow replaces fullcap with repcap, throws off all calculations. Battery degredation + // shouldn't be a huge factor for our time scale // status_ok_or_return(max17261_set_reg(storage, MAX17261_FULL_CAP_REP, params->fullcaprep)); status_ok_or_return(max17261_set_reg(storage, MAX17261_CYCLES, params->cycles)); status_ok_or_return(max17261_set_reg(storage, MAX17261_FULL_CAP_NOM, params->fullcapnom)); @@ -161,11 +159,12 @@ StatusCode max17261_init(Max17261Storage *storage, Max17261Settings *settings, status_ok_or_return( max17261_set_reg(storage, MAX17261_SOFT_WAKEUP, 0x0)); // clear wakeup command - delay_ms(10); // delay that seems to make it work, TODO ???? + delay_ms( + 25); // unsure why this works, not mentioned in any documentation. Seems reliable enough. // Step 2.1 -- configure - status_ok_or_return(max17261_set_reg(storage, MAX17261_DESIGN_CAP, - settings->pack_design_cap_mah / (uint32_t)CAP_LSB)); + status_ok_or_return( + max17261_set_reg(storage, MAX17261_DESIGN_CAP, settings->pack_design_cap_mah / CAP_LSB)); status_ok_or_return( max17261_set_reg(storage, MAX17261_I_CHG_TERM, settings->charge_term_current_ma / CUR_LSB)); status_ok_or_return( @@ -174,7 +173,11 @@ StatusCode max17261_init(Max17261Storage *storage, Max17261Settings *settings, status_ok_or_return( max17261_set_reg(storage, MAX17261_SOC_HOLD, 0x0)); // disable SOCHold, not relevant to us - uint16_t modelcfg = /*refresh*/ (1 << 15) | /*R100*/ (0 << 13) | /*RChg*/ (0 << 10) | (1 << 3); + uint16_t modelcfg = 0; + modelcfg |= (1 << 15); // refresh + modelcfg |= (0 << 13); // R100 + modelcfg |= (0 << 10); // RChg + modelcfg |= (1 << 3); // mandatory 1 status_ok_or_return(max17261_set_reg(storage, MAX17261_MODEL_I_CFG, modelcfg)); // wait for modelcfg refresh to complete @@ -189,7 +192,7 @@ StatusCode max17261_init(Max17261Storage *storage, Max17261Settings *settings, status_ok_or_return(max17261_get_reg(storage, MAX17261_CONFIG, &config)); config |= (1 << 2); // enable alerts config |= (1 << 4); // thermal alerts - // config |= (1 << 8); // external temp measurement TODO: hardware / uncomment + config |= (1 << 8); // external temp measurement status_ok_or_return(max17261_set_reg(storage, MAX17261_CONFIG, config)); uint16_t current_th = (settings->i_thresh_max_a << 8) & (settings->i_thresh_min_a & 0x00FF); @@ -200,7 +203,7 @@ StatusCode max17261_init(Max17261Storage *storage, Max17261Settings *settings, // Disable voltage alert (handled by AFE) status_ok_or_return(max17261_set_reg(storage, MAX17261_VOLT_ALRT_THRSH, 0xFF00)); - // Disable state of charge alerting + // Disable state of charge alerting (no need to fault on SOC) status_ok_or_return(max17261_set_reg(storage, MAX17261_SOC_ALRT_THRSH, 0xFF00)); // enable hibernation diff --git a/projects/bms_carrier/inc/bms.h b/projects/bms_carrier/inc/bms.h index 031da3b92..490c94ac8 100644 --- a/projects/bms_carrier/inc/bms.h +++ b/projects/bms_carrier/inc/bms.h @@ -21,7 +21,7 @@ typedef struct CurrentStorage { uint16_t voltage; uint16_t temperature; uint32_t fuel_guage_cycle_ms; // Time in ms between conversions (soft timer kicks) - uint32_t mah; + uint32_t remaining_capacity; uint32_t full; } CurrentStorage; diff --git a/projects/bms_carrier/src/current_sense.c b/projects/bms_carrier/src/current_sense.c index aa644b4e4..94f1ec46c 100644 --- a/projects/bms_carrier/src/current_sense.c +++ b/projects/bms_carrier/src/current_sense.c @@ -33,15 +33,16 @@ StatusCode prv_fuel_gauge_read() { status |= max17261_current(&s_fuel_guage_storage, &s_current_storage->current); status |= max17261_voltage(&s_fuel_guage_storage, &s_current_storage->voltage); status |= max17261_temp(&s_fuel_guage_storage, &s_current_storage->temperature); - status |= max17261_remaining_capacity(&s_fuel_guage_storage, &s_current_storage->mah); + status |= + max17261_remaining_capacity(&s_fuel_guage_storage, &s_current_storage->remaining_capacity); status |= max17261_full_capacity(&s_fuel_guage_storage, &s_current_storage->full); LOG_DEBUG("SOC: %d\n", s_current_storage->soc); LOG_DEBUG("CURRENT: %d\n", s_current_storage->current); LOG_DEBUG("VOLTAGE: %d\n", s_current_storage->voltage); LOG_DEBUG("TEMP: %d\n", s_current_storage->temperature); - LOG_DEBUG("mah: %" PRIu32 "\n", s_current_storage->mah); - LOG_DEBUG("Full: %" PRIu32 "\n", s_current_storage->full); + LOG_DEBUG("REMCAP: %" PRIu32 "\n", s_current_storage->remaining_capacity); + LOG_DEBUG("FULLCAP: %" PRIu32 "\n", s_current_storage->full); if (status != STATUS_CODE_OK) { // TODO (Adel): Handle a fuel gauge fault diff --git a/projects/bms_carrier/src/main.c b/projects/bms_carrier/src/main.c index cb82876b3..daef2a0a9 100644 --- a/projects/bms_carrier/src/main.c +++ b/projects/bms_carrier/src/main.c @@ -39,33 +39,33 @@ void pre_loop_init() { LOG_DEBUG("Welcome to BMS \n"); fault_bps_init(&bms_storage.bps_storage); current_sense_init(&bms_storage, &i2c_settings, FUEL_GAUGE_CYCLE_TIME_MS); - // cell_sense_init(&bms_storage.ltc_afe_storage); - // aux_sense_init(&bms_storage.aux_storage); - // init_bms_relays(); - // bms_fan_init(&bms_storage); + cell_sense_init(&bms_storage.ltc_afe_storage); + aux_sense_init(&bms_storage.aux_storage); + init_bms_relays(); + bms_fan_init(&bms_storage); } void run_fast_cycle() {} void run_medium_cycle() { - // run_can_rx_cycle(); - // wait_tasks(1); + run_can_rx_cycle(); + wait_tasks(1); - // cell_conversions(); - // wait_tasks(1); + cell_conversions(); + wait_tasks(1); current_sense_run(); wait_tasks(1); - // cell_sense_run(); - // aux_sense_run(); - // bms_run_fan(); + cell_sense_run(); + aux_sense_run(); + bms_run_fan(); - // run_can_tx_cycle(); - // wait_tasks(1); + run_can_tx_cycle(); + wait_tasks(1); } void run_slow_cycle() { - // cell_discharge(&bms_storage.ltc_afe_storage); + cell_discharge(&bms_storage.ltc_afe_storage); if (fault_bps_get()) { LOG_DEBUG("FAULT_BITMASK: %d\n", fault_bps_get()); From d1d218dc1f0af04c6aa9039a3ee2916682a98000 Mon Sep 17 00:00:00 2001 From: Evan McCarthy Date: Fri, 17 May 2024 12:29:04 -0400 Subject: [PATCH 7/9] remove unnecessary diff --- projects/bms_carrier/src/main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/projects/bms_carrier/src/main.c b/projects/bms_carrier/src/main.c index daef2a0a9..5eff0a40b 100644 --- a/projects/bms_carrier/src/main.c +++ b/projects/bms_carrier/src/main.c @@ -39,7 +39,7 @@ void pre_loop_init() { LOG_DEBUG("Welcome to BMS \n"); fault_bps_init(&bms_storage.bps_storage); current_sense_init(&bms_storage, &i2c_settings, FUEL_GAUGE_CYCLE_TIME_MS); - cell_sense_init(&bms_storage.ltc_afe_storage); + // cell_sense_init(&bms_storage.ltc_afe_storage); aux_sense_init(&bms_storage.aux_storage); init_bms_relays(); bms_fan_init(&bms_storage); @@ -51,12 +51,12 @@ void run_medium_cycle() { run_can_rx_cycle(); wait_tasks(1); - cell_conversions(); - wait_tasks(1); + // cell_conversions(); + // wait_tasks(1); current_sense_run(); wait_tasks(1); - cell_sense_run(); + // cell_sense_run(); aux_sense_run(); bms_run_fan(); From 9140fa5f3886ec7e99307a2985c99567b7fb1688 Mon Sep 17 00:00:00 2001 From: Evan McCarthy Date: Fri, 17 May 2024 12:30:54 -0400 Subject: [PATCH 8/9] update battery characteristics --- projects/bms_carrier/inc/current_sense.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/projects/bms_carrier/inc/current_sense.h b/projects/bms_carrier/inc/current_sense.h index 4ded016da..43e38f163 100644 --- a/projects/bms_carrier/inc/current_sense.h +++ b/projects/bms_carrier/inc/current_sense.h @@ -16,11 +16,11 @@ #define SENSE_RESISTOR_MOHM (0.5) -#define PACK_CAPACITY_MAH (160000) // 14V test module, TODO change to reflect pack +#define PACK_CAPACITY_MAH (160000) // one module #define CELL_EMPTY_VOLTAGE_MV 2500 // LG M50T datasheet -#define CHARGE_TERMINATION_CURRENT_MA 150 // just a guess, TODO verify +#define CHARGE_TERMINATION_CURRENT_MA (400) // 50 mA * 8 (one module) // Thresholds for ALRT Pin #define CURRENT_SENSE_MAX_CURRENT_A (58.2f) From 83855edeb36ff10c7a93910b251617127ab2da27 Mon Sep 17 00:00:00 2001 From: Mitch Ostler Date: Tue, 21 May 2024 21:32:01 +0000 Subject: [PATCH 9/9] some updates for voltage and timeouts --- .../ms-drivers/src/max17261_fuel_gauge.c | 12 ++++++++- libraries/ms-freertos/inc/FreeRTOSConfig.h | 2 +- projects/bms_carrier/inc/current_sense.h | 8 +++--- projects/bms_carrier/src/current_sense.c | 25 +++++++++++-------- projects/bms_carrier/src/main.c | 8 +++--- 5 files changed, 36 insertions(+), 19 deletions(-) diff --git a/libraries/ms-drivers/src/max17261_fuel_gauge.c b/libraries/ms-drivers/src/max17261_fuel_gauge.c index 47f3099bd..f5181385c 100644 --- a/libraries/ms-drivers/src/max17261_fuel_gauge.c +++ b/libraries/ms-drivers/src/max17261_fuel_gauge.c @@ -144,10 +144,15 @@ StatusCode max17261_init(Max17261Storage *storage, Max17261Settings *settings, // Step 1 -- delay until FSTAT.DNR bit == 0 uint16_t fstat = 0; status_ok_or_return(max17261_get_reg(storage, MAX17261_FSTAT, &fstat)); + // Checks that initializaton has occurred, must happen before configuration + // Should not take longer than 250 ms + TickType_t start_time = xTaskGetTickCount(); while ((fstat & 1) != 0) { LOG_DEBUG("data not ready, fstat: %d (%d)\n", fstat, fstat & 1); status_ok_or_return(max17261_get_reg(storage, MAX17261_FSTAT, &fstat)); - + if (xTaskGetTickCount() >= start_time + pdMS_TO_TICKS(250)) { + LOG_DEBUG("fstat failed: %d (%d)\n", fstat, fstat & 1); + } delay_ms(10); } @@ -181,9 +186,14 @@ StatusCode max17261_init(Max17261Storage *storage, Max17261Settings *settings, status_ok_or_return(max17261_set_reg(storage, MAX17261_MODEL_I_CFG, modelcfg)); // wait for modelcfg refresh to complete + // Should not take longer than 1sec + start_time = xTaskGetTickCount(); while (modelcfg & (1 << 15)) { LOG_DEBUG("modelcfg refresh not cleared: %d\n", modelcfg); status_ok_or_return(max17261_get_reg(storage, MAX17261_MODEL_I_CFG, &modelcfg)); + if (xTaskGetTickCount() >= start_time + pdMS_TO_TICKS(1000)) { + LOG_DEBUG("modelcfg failed: %d (%d)\n", fstat, fstat & 1); + } delay_ms(10); } diff --git a/libraries/ms-freertos/inc/FreeRTOSConfig.h b/libraries/ms-freertos/inc/FreeRTOSConfig.h index f7a715e31..f891ab982 100644 --- a/libraries/ms-freertos/inc/FreeRTOSConfig.h +++ b/libraries/ms-freertos/inc/FreeRTOSConfig.h @@ -76,7 +76,7 @@ extern uint32_t SystemCoreClock; #define configUSE_TIMERS 1 #define configTIMER_TASK_PRIORITY 3 #define configTIMER_QUEUE_LENGTH 10 -#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE +#define configTIMER_TASK_STACK_DEPTH ((uint16_t)256) // Optional functions - most linkers will remove unused functions anyway #define INCLUDE_vTaskPrioritySet 1 diff --git a/projects/bms_carrier/inc/current_sense.h b/projects/bms_carrier/inc/current_sense.h index 43e38f163..518fa42fe 100644 --- a/projects/bms_carrier/inc/current_sense.h +++ b/projects/bms_carrier/inc/current_sense.h @@ -22,15 +22,17 @@ #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 +#define CURRENT_SENSE_MIN_CURRENT_A (-27.0f) // Actually -27 #define CURRENT_SENSE_MAX_TEMP_C (60U) -#define CURRENT_SENSE_MAX_VOLTAGE_V (150U) +#define CURRENT_SENSE_MAX_VOLTAGE_V (15000) #define ALRT_PIN_V_RES_MICRO_V (400) #define CELL_X_R1_KOHMS 1780 -#define CELL_X_R2_KOHMS 195 +#define CELL_X_R2_KOHMS 20 #define CURRENT_SENSE_STORE_FLASH NUM_FLASH_PAGES - 1 diff --git a/projects/bms_carrier/src/current_sense.c b/projects/bms_carrier/src/current_sense.c index 94f1ec46c..4967adef2 100644 --- a/projects/bms_carrier/src/current_sense.c +++ b/projects/bms_carrier/src/current_sense.c @@ -37,6 +37,8 @@ StatusCode prv_fuel_gauge_read() { max17261_remaining_capacity(&s_fuel_guage_storage, &s_current_storage->remaining_capacity); status |= max17261_full_capacity(&s_fuel_guage_storage, &s_current_storage->full); + // Measured voltage corresponds to one cell. Multiply it by the number of cells in series + s_current_storage->voltage = s_current_storage->voltage * NUM_SERIES_CELLS / 10; LOG_DEBUG("SOC: %d\n", s_current_storage->soc); LOG_DEBUG("CURRENT: %d\n", s_current_storage->current); LOG_DEBUG("VOLTAGE: %d\n", s_current_storage->voltage); @@ -59,16 +61,19 @@ StatusCode prv_fuel_gauge_read() { set_battery_vt_temperature(s_current_storage->temperature); // TODO (Aryan): Validate these checks - // if (s_current_storage->current >= CURRENT_SENSE_MAX_CURRENT_A * 1000) { - // fault_bps_set(BMS_FAULT_OVERCURRENT); - // return STATUS_CODE_INTERNAL_ERROR; - // } else if (s_current_storage->voltage >= CURRENT_SENSE_MAX_VOLTAGE) { - // fault_bps_set(BMS_FAULT_OVERVOLTAGE); - // return STATUS_CODE_INTERNAL_ERROR; - // } else if (s_current_storage->temperature >= CURRENT_SENSE_MAX_TEMP) { - // fault_bps_set(BMS_FAULT_OVERTEMP_AMBIENT); - // return STATUS_CODE_INTERNAL_ERROR; - // } + if (s_current_storage->current >= CURRENT_SENSE_MAX_CURRENT_A * 1000) { + fault_bps_set(BMS_FAULT_OVERCURRENT); + return STATUS_CODE_INTERNAL_ERROR; + } else if (s_current_storage->current <= CURRENT_SENSE_MIN_CURRENT_A * 1000) { + fault_bps_set(BMS_FAULT_OVERCURRENT); + return STATUS_CODE_INTERNAL_ERROR; + } else if (s_current_storage->voltage >= CURRENT_SENSE_MAX_VOLTAGE_V) { + fault_bps_set(BMS_FAULT_OVERVOLTAGE); + return STATUS_CODE_INTERNAL_ERROR; + } else if (s_current_storage->temperature >= CURRENT_SENSE_MAX_TEMP_C) { + fault_bps_set(BMS_FAULT_OVERTEMP_AMBIENT); + return STATUS_CODE_INTERNAL_ERROR; + } // Commit params info periodically if (xTaskGetTickCount() > s_last_params_update + pdMS_TO_TICKS(UPDATE_FLASH_PARAMS_PERIOD_MS)) { diff --git a/projects/bms_carrier/src/main.c b/projects/bms_carrier/src/main.c index 5eff0a40b..a58a05d2d 100644 --- a/projects/bms_carrier/src/main.c +++ b/projects/bms_carrier/src/main.c @@ -48,8 +48,8 @@ void pre_loop_init() { void run_fast_cycle() {} void run_medium_cycle() { - run_can_rx_cycle(); - wait_tasks(1); + // run_can_rx_cycle(); + // wait_tasks(1); // cell_conversions(); // wait_tasks(1); @@ -60,8 +60,8 @@ void run_medium_cycle() { aux_sense_run(); bms_run_fan(); - run_can_tx_cycle(); - wait_tasks(1); + // run_can_tx_cycle(); + // wait_tasks(1); } void run_slow_cycle() {