Procházet zdrojové kódy

[FL-1268] Gauge re-calibration (#471)

* bq27220: add new battery profile parameters
* bq27220: add gauging configuration
* power: change poweroff condition depending on remain capacity
* api-hal-power: update api for f6 target
gornekich před 4 roky
rodič
revize
df4a170213

+ 1 - 1
applications/power/power.c

@@ -206,7 +206,7 @@ int32_t power_task(void* p) {
                 model->temperature_gauge =
                     api_hal_power_get_battery_temperature(ApiHalPowerICFuelGauge);
 
-                if(model->voltage_gauge < 3.3f && model->voltage_vbus < 4.0f) {
+                if(model->charge == 0 && model->voltage_vbus < 4.0f) {
                     battery_low = true;
                 }
 

+ 29 - 15
firmware/targets/f5/api-hal/api-hal-power.c

@@ -24,26 +24,40 @@ static volatile ApiHalPower api_hal_power = {
 };
 
 const ParamCEDV cedv = {
+    .cedv_conf.gauge_conf = {
+        .CCT = 1,
+        .CSYNC = 0,
+        .EDV_CMP = 0,
+        .SC = 1,
+        .FIXED_EDV0 = 1,
+        .FCC_LIM = 1,
+        .FC_FOR_VDQ = 1,
+        .IGNORE_SD = 1,
+        .SME0 = 0,
+    },
     .full_charge_cap = 2100,
     .design_cap = 2100,
-    .EMF = 3739,
-    .C0 = 776,
+    .EDV0 = 3300,
+    .EDV1 = 3321,
+    .EDV2 = 3355,
+    .EMF = 3679,
+    .C0 = 430,
     .C1 = 0,
-    .R1 = 193,
-    .R0 = 1,
-    .T0 = 1,
+    .R1 = 408,
+    .R0 = 334,
+    .T0 = 4626,
     .TC = 11,
     .DOD0 = 4044,
-    .DOD10 = 3899,
-    .DOD20 = 3796,
-    .DOD30 = 3704,
-    .DOD40 = 3627,
-    .DOD50 = 3573,
-    .DOD60 = 3535,
-    .DOD70 = 3501,
-    .DOD80 = 3453,
-    .DOD90 = 3366,
-    .DOD100 = 2419,
+    .DOD10 = 3905,
+    .DOD20 = 3807,
+    .DOD30 = 3718,
+    .DOD40 = 3642,
+    .DOD50 = 3585,
+    .DOD60 = 3546,
+    .DOD70 = 3514,
+    .DOD80 = 3477,
+    .DOD90 = 3411,
+    .DOD100 = 3299,
 };
 
 void HAL_RCC_CSSCallback(void) {

+ 29 - 15
firmware/targets/f6/api-hal/api-hal-power.c

@@ -24,26 +24,40 @@ static volatile ApiHalPower api_hal_power = {
 };
 
 const ParamCEDV cedv = {
+    .cedv_conf.gauge_conf = {
+        .CCT = 1,
+        .CSYNC = 0,
+        .EDV_CMP = 0,
+        .SC = 1,
+        .FIXED_EDV0 = 1,
+        .FCC_LIM = 1,
+        .FC_FOR_VDQ = 1,
+        .IGNORE_SD = 1,
+        .SME0 = 0,
+    },
     .full_charge_cap = 2100,
     .design_cap = 2100,
-    .EMF = 3739,
-    .C0 = 776,
+    .EDV0 = 3300,
+    .EDV1 = 3321,
+    .EDV2 = 3355,
+    .EMF = 3679,
+    .C0 = 430,
     .C1 = 0,
-    .R1 = 193,
-    .R0 = 1,
-    .T0 = 1,
+    .R1 = 408,
+    .R0 = 334,
+    .T0 = 4626,
     .TC = 11,
     .DOD0 = 4044,
-    .DOD10 = 3899,
-    .DOD20 = 3796,
-    .DOD30 = 3704,
-    .DOD40 = 3627,
-    .DOD50 = 3573,
-    .DOD60 = 3535,
-    .DOD70 = 3501,
-    .DOD80 = 3453,
-    .DOD90 = 3366,
-    .DOD100 = 2419,
+    .DOD10 = 3905,
+    .DOD20 = 3807,
+    .DOD30 = 3718,
+    .DOD40 = 3642,
+    .DOD50 = 3585,
+    .DOD60 = 3546,
+    .DOD70 = 3514,
+    .DOD80 = 3477,
+    .DOD90 = 3411,
+    .DOD100 = 3299,
 };
 
 void HAL_RCC_CSSCallback(void) {

+ 23 - 20
lib/drivers/bq27220.c

@@ -53,6 +53,7 @@ bool bq27220_set_parameter_u16(uint16_t address, uint16_t value) {
             buffer[4] = value & 0xFF;
             return api_hal_i2c_tx(POWER_I2C, BQ27220_ADDRESS, buffer, 5, BQ27220_I2C_TIMEOUT);
         });
+    delay_us(10000);
     uint8_t checksum = bq27220_get_checksum(&buffer[1], 4);
     with_api_hal_i2c(
         bool, &ret, () {
@@ -61,59 +62,61 @@ bool bq27220_set_parameter_u16(uint16_t address, uint16_t value) {
             buffer[2] = 6;
             return api_hal_i2c_tx(POWER_I2C, BQ27220_ADDRESS, buffer, 3, BQ27220_I2C_TIMEOUT);
         });
+    delay_us(10000);
     return ret;
 }
 
 bool bq27220_init(const ParamCEDV* cedv) {
     uint32_t timeout = 100;
+    uint16_t design_cap = bq27220_get_design_capacity();
+    if(cedv->design_cap == design_cap) {
+        FURI_LOG_I("gauge", "Skip battery profile update");
+        return true;
+    }
+    FURI_LOG_I("gauge", "Start updating battery profile");
     OperationStatus status = {};
     if(!bq27220_control(Control_ENTER_CFG_UPDATE)) {
+        FURI_LOG_E("gauge", "Can't configure update");
         return false;
     };
+
     while((status.CFGUPDATE != 1) && (timeout-- > 0)) {
         bq27220_get_operation_status(&status);
     }
+    bq27220_set_parameter_u16(AddressGaugingConfig, cedv->cedv_conf.gauge_conf_raw);
     bq27220_set_parameter_u16(AddressFullChargeCapacity, cedv->full_charge_cap);
-    delay_us(15000);
     bq27220_set_parameter_u16(AddressDesignCapacity, cedv->design_cap);
-    delay_us(15000);
     bq27220_set_parameter_u16(AddressEMF, cedv->EMF);
-    delay_us(15000);
     bq27220_set_parameter_u16(AddressC0, cedv->C0);
-    delay_us(15000);
     bq27220_set_parameter_u16(AddressR0, cedv->R0);
-    delay_us(15000);
     bq27220_set_parameter_u16(AddressT0, cedv->T0);
-    delay_us(15000);
     bq27220_set_parameter_u16(AddressR1, cedv->R1);
-    delay_us(15000);
     bq27220_set_parameter_u16(AddressTC, (cedv->TC) << 8 | cedv->C1);
-    delay_us(15000);
     bq27220_set_parameter_u16(AddressStartDOD0, cedv->DOD0);
-    delay_us(15000);
     bq27220_set_parameter_u16(AddressStartDOD10, cedv->DOD10);
-    delay_us(15000);
     bq27220_set_parameter_u16(AddressStartDOD20, cedv->DOD20);
-    delay_us(15000);
     bq27220_set_parameter_u16(AddressStartDOD30, cedv->DOD30);
-    delay_us(15000);
     bq27220_set_parameter_u16(AddressStartDOD40, cedv->DOD40);
-    delay_us(15000);
     bq27220_set_parameter_u16(AddressStartDOD50, cedv->DOD40);
-    delay_us(15000);
     bq27220_set_parameter_u16(AddressStartDOD60, cedv->DOD60);
-    delay_us(15000);
     bq27220_set_parameter_u16(AddressStartDOD70, cedv->DOD70);
-    delay_us(15000);
     bq27220_set_parameter_u16(AddressStartDOD80, cedv->DOD80);
-    delay_us(15000);
     bq27220_set_parameter_u16(AddressStartDOD90, cedv->DOD90);
-    delay_us(15000);
     bq27220_set_parameter_u16(AddressStartDOD100, cedv->DOD100);
-    delay_us(15000);
+    bq27220_set_parameter_u16(AddressEDV0, cedv->EDV0);
+    bq27220_set_parameter_u16(AddressEDV1, cedv->EDV1);
+    bq27220_set_parameter_u16(AddressEDV2, cedv->EDV2);
 
     bq27220_control(Control_EXIT_CFG_UPDATE);
-    return true;
+    delay_us(10000);
+    design_cap = bq27220_get_design_capacity();
+    if(cedv->design_cap == design_cap) {
+        FURI_LOG_I("gauge", "Battery profile update success");
+        return true;
+    } else {
+        FURI_LOG_E("gauge", "Battery profile update failed");
+        return false;
+    }
 }
 
 uint16_t bq27220_get_voltage() {

+ 26 - 0
lib/drivers/bq27220.h

@@ -44,8 +44,34 @@ typedef struct {
 } OperationStatus;
 
 typedef struct {
+    // Low byte, Low bit first
+    bool CCT : 1;
+    bool CSYNC : 1;
+    bool RSVD0 : 1;
+    bool EDV_CMP : 1;
+    bool SC : 1;
+    bool FIXED_EDV0 : 1;
+    uint8_t RSVD1 : 2;
+    // High byte, Low bit first
+    bool FCC_LIM : 1;
+    bool RSVD2 : 1;
+    bool FC_FOR_VDQ : 1;
+    bool IGNORE_SD : 1;
+    bool SME0 : 1;
+    uint8_t RSVD3 : 3;
+} GaugingConfig;
+
+
+typedef struct {
+    union {
+        GaugingConfig gauge_conf;
+        uint16_t gauge_conf_raw;
+    } cedv_conf;
     uint16_t full_charge_cap;
     uint16_t design_cap;
+    uint16_t EDV0;
+    uint16_t EDV1;
+    uint16_t EDV2;
     uint16_t EMF;
     uint16_t C0;
     uint16_t R0;

+ 5 - 1
lib/drivers/bq27220_reg.h

@@ -67,6 +67,7 @@
 #define Control_EXIT_CFG_UPDATE 0x0092
 #define Control_RETURN_TO_ROM 0x0F00
 
+#define AddressGaugingConfig 0x929B
 #define AddressFullChargeCapacity 0x929D
 #define AddressDesignCapacity 0x929F
 #define AddressEMF 0x92A3
@@ -75,7 +76,10 @@
 #define AddressT0 0x92AD
 #define AddressR1 0x92AF
 #define AddressTC 0x92B1
-#define AddressC1 0x92B1
+#define AddressC1 0x92B2
+#define AddressEDV0 0x92B4
+#define AddressEDV1 0x92B7
+#define AddressEDV2 0x92BA
 #define AddressStartDOD0 0x92BD
 #define AddressStartDOD10 0x92BF
 #define AddressStartDOD20 0x92C1