[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
This commit is contained in:
		
							parent
							
								
									6d648da003
								
							
						
					
					
						commit
						df4a170213
					
				| @ -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; | ||||
|                 } | ||||
| 
 | ||||
|  | ||||
| @ -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) { | ||||
|  | ||||
| @ -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) { | ||||
|  | ||||
| @ -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() { | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 gornekich
						gornekich