diff --git a/applications/power/power.c b/applications/power/power.c index a27231c2..eedeee1b 100644 --- a/applications/power/power.c +++ b/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; } diff --git a/firmware/targets/f5/api-hal/api-hal-power.c b/firmware/targets/f5/api-hal/api-hal-power.c index e90ebd80..2012d00d 100644 --- a/firmware/targets/f5/api-hal/api-hal-power.c +++ b/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) { diff --git a/firmware/targets/f6/api-hal/api-hal-power.c b/firmware/targets/f6/api-hal/api-hal-power.c index e90ebd80..2012d00d 100644 --- a/firmware/targets/f6/api-hal/api-hal-power.c +++ b/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) { diff --git a/lib/drivers/bq27220.c b/lib/drivers/bq27220.c index e7fcb35f..9c62f7a0 100644 --- a/lib/drivers/bq27220.c +++ b/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() { diff --git a/lib/drivers/bq27220.h b/lib/drivers/bq27220.h index a4606f4f..312d46fd 100644 --- a/lib/drivers/bq27220.h +++ b/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; diff --git a/lib/drivers/bq27220_reg.h b/lib/drivers/bq27220_reg.h index 20effd68..fa81b66e 100644 --- a/lib/drivers/bq27220_reg.h +++ b/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