高通decidegc高通sdm660是什么意思思

LoongEmbedded
高通batterydata电池曲线数据学习我们产品采用的是4.2V,对应的文件为《batterydata-qrd-l42q-4v20-3200mah.dtsi》,在msm8909-qrd-skue-cb03.dtsi文件中被引用,开发板采用的是《batterydata-qrd-l45q-4v35-1800mah.dtsi》&电池曲线文件说明文档见kernel\Documentation\devicetree\bindings\batterydata\batterydata.txt文件&Battery Data is a collection of batteryprofile data made available to the QPNP Charger and BMS drivers via devicetree.电池数据是电池配置数据的集合,通过设备树供QPNP充电器和BMS驱动使用。&qcom,battery-data node required properties(电池数据节点需要的属性):
- qcom,rpull-up-kohm : The vadc pullupresistor's resistance value in kOhms.
Vadc上拉电阻的阻值
- qcom,vref-batt-therm-uv : The vadcvoltage used to make readings.
ForQualcomm VADCs this should be 1800000uV.
qcom,battery-data node optional properties:
- qcom,batt-id-range-pct : The area ofvariation between upper and lower bound
forwhich a given battery ID resistance is valid. This
valueis expressed as a percentage of the specified kohm
resistanceprovided by qcom,batt-id-kohm.
qcom,battery-data can also include anynumber of children nodes. These children
nodes will be treated as battery profiledata nodes.Batter-data可包含任何数量的子节点,这些子节点将会作为电池配置文件节点来创建。&1.&&&&&batterydata-qrd-l42q-4v20-3400mah.dtsiqcom,qrd-l42q-4v20-3200mah-data{
qcom,battery-type =&qrd_l42q_4v20_3200mah&;
qcom,batt-id-kohm = &10&;
The battery idresistance of the battery. It can be used as an array which could supportmultiple IDs for one battery module when the ID resistance of some batterymodules goes across several ranges.
电池ID电阻:当一些电池模型的ID电阻在一定范围内浮动时,电池ID电阻可以作为单电池模型数组以支持多ID
qcom,chg-term-ua = &96000&;
The terminationcharging current of the battery电池的结束充电电流,这里为96mA
qcom,default-rbatt-mohm =&120&;
The nominalbattery resistance value蓄电池电阻值
qcom,fcc-mah = &3200&;
Full charge countof the battery in milliamp-hours完全充满时电池容量为3200mAh
qcom,max-voltage-uv =&4200000&;
The maximum ratedvoltage of the battery电池最大的额定电压
qcom,rbatt-capacitive-mohm =&50&;
The capacitiveresistance of the battery电池的电容电阻
qcom,v-cutoff-uv = &3400000&;
The cutoffvoltage of the battery at which the device should shutdown gracefully
电池的截止电压,当电池电压低于此值时设备会自动关机
qcom,fcc-temp-lut {
qcom,lut-col-legend = &(-20) 025 40 60&;
qcom,lut-data = &6&;
电池配置数据需要fcc-temp-lut子节点
- qcom,fcc-temp-lut : An 1-dimensionallookup table node that encodes temperature to fcc lookup. The units for thislookuptable should be degrees celsius to milliamp-hours.
一维查找表节点会将温度编码成fcc查找。该方法的单位也应该从摄氏度变成毫安时。
- qcom,lut-col-legend : An array thatencodes the legend of the lookup table's
columns.The length of this array will determine the
lookuptable's width.
- qcom,lut-data : An array that encodes thelookup table's data. The size of this
arrayshould be equal to the size of qcom,lut-col-legend
multipliedby 1 if it's a 1-dimensional table, or
thesize of qcom,lut-row-legend if it's a 2-dimensional
table.The data should be in a flattened row-major
representation.如果lut-row-legend是一个二维表,lut-data相应的是一个偏平行表示
qcom,ibat-acc-lut{
qcom,lut-col-legend= &(-20) 0 25&;
qcom,lut-row-legend = &0 0 1500&,
qcom,lut-data= &02&,
Lookup table optional properties:
- qcom,lut-row-legend : An array thatencodes the legend of the lookup table's rows.
Ifthis property exists, then it is assumed that the
lookuptable is a 2-dimensional table.
qcom,pc-temp-ocv-lut{
qcom,lut-col-legend= &(-20) 0 25 40 60&;
qcom,lut-row-legend= &100 95 90 85 80&,
&109 8 7 6&,
&54 3 2 1&,
qcom,lut-data = &3 &,
- qcom,pc-temp-ocv-lut : A 2-dimensionallookup table node that encodes
temperatureand percent charge to open circuit voltage
lookup.The units for this lookup table should be
degreescelsius and percent to millivolts.
一个包含温度和百分比的开路电压2维查找表,查找表的单位是百分比和电压的关系
- qcom,rbatt-sf-lut : A 2-dimentionallookup table node that encodes
temperatureand percent charge to battery internal
resistance lookup. Theunits for this lookup table
shouldbe degrees celsius and percent to milliohms.2.&&&&&msm8909-qrd-skue-cb03.dtsi qrd_batterydata:qcom,battery-data {
qcom,rpull-up-kohm= &0&;
qcom,vref-batt-therm= &1800000&;
//#include&batterydata-qrd-l45q-4v35-1800mah.dtsi&
#include&batterydata-qrd-l42q-4v20-3200mah.dtsi&
//#include&batterydata-qrd-skue-4v35-2000mah.dtsi&
&pm8909_chg {
qcom,vddmax-mv= &4200&; //Target voltage of battery in mV.电池电压值
qcom,vddsafe-mv= &4380&;// Maximum Vdd voltage in mV,电池最高的安全电压会比4.2V会高一些。你们电池规格是上面会有的
qcom,vinmin-mv= &4470&;// Minimum input voltage in mV. 这个是VBUS进到充电IC的最低电压。 一般是5V, 4470是最低的值
qcom,batt-hot-percentage= &25&;
qcom,batt-cold-percentage= &80&;
qcom,tchg-mins= &360&;
qcom,bms-controlled-
qcom,disable-vbatdet-based-
status= &okay&;
//qcom,use-external-
qcom,charging-
};3.&&&&&msm-pm8909.dtsipm8909_chg: qcom,charger {
compatible= &qcom,qpnp-linear-charger&;
#address-cells= &1&;
#size-cells= &1&;
qcom,vddmax-mv= &4200&;
qcom,vddsafe-mv= &4230&;//&4200&;
qcom,vinmin-mv= &4470&;//&4308&//
qcom,ibatsafe-ma= &1440&;
qcom,thermal-mitigation= & 0&;
qcom,cool-bat-decidegc= &100&;
qcom,warm-bat-decidegc= &450&;
qcom,cool-bat-mv= &4100&;
qcom,warm-bat-mv= &4100&;
qcom,ibatmax-warm-ma= &360&;
qcom,ibatmax-cool-ma= &360&;
qcom,batt-hot-percentage= &25&;
qcom,batt-cold-percentage= &80&;
qcom,tchg-mins= &232&;
qcom,chg-vadc= &&pm8909_vadc&;
qcom,chg-adc_tm= &&pm8909_adc_tm&;
status= &disabled&;
qcom,chgr@1000{
reg= &0x&;
interrupts=
&0x0 0x10 0x7&,
&0x00x10 0x6&,
&0x00x10 0x5&,
&0x00x10 0x0&;
interrupt-names=
&chg-done&,
&chg-failed&,
&fast-chg-on&,
&vbat-det-lo&;
qcom,bat-if@1200{
reg= &0x&;
interrupts=
&0x0 0x12 0x1&,
&0x00x12 0x0&;
interrupt-names=
&bat-temp-ok&,
&batt-pres&;
qcom,usb-chgpth@1300{
reg= &0x&;
interrupts=
&0 0x13 0x4&,
&00x13 0x2&,
&00x13 0x1&;
interrupt-names=
&usb-over-temp&,
&chg-gone&,
&usbin-valid&;
qcom,chg-misc@1600{
reg= &0x&;
阅读排行榜他的最新文章
他的热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)高通batterydata电池曲线数据学习
高通batterydata电池曲线数据学习
我们产品采用的是4.2V,对应的文件为《batterydata-qrd-l42q-4v20-3200mah.dtsi》,在msm8909-qrd-skue-cb03.dtsi文件中被引用,开发板采用的是《batterydata-qrd-l45q-4v35-1800mah.dtsi》
电池曲线文件说明文档见kernel\Documentation\devicetree\bindings\batterydata\
batterydata.txt文件
Battery Data is a collection of batteryprofile data made available to the QPNP Charger and BMS drivers via devicetree.
电池数据是电池配置数据的集合,通过设备树供QPNP充电器和BMS驱动使用。
qcom,battery-data node required properties(电池数据节点需要的属性):
- qcom,rpull-up-kohm : The vadc pullupresistor's resistance value in kOhms.
Vadc上拉电阻的阻值
- qcom,vref-batt-therm-uv : The vadcvoltage used to make readings.
ForQualcomm VADCs this should be 1800000uV.
qcom,battery-data node optional properties:
- qcom,batt-id-range-pct : The area ofvariation between upper and lower bound
forwhich a given battery ID resistance is valid. This
valueis expressed as a percentage of the specified kohm
resistanceprovided by qcom,batt-id-kohm.
qcom,battery-data can also include anynumber of children nodes. These children
nodes will be treated as battery profiledata nodes.
Batter-data可包含任何数量的子节点,这些子节点将会作为电池配置文件节点来创建。
1.batterydata-qrd-l42q-4v20-3400mah.dtsi
qcom,qrd-l42q-4v20-3200mah-data{
qcom,battery-type =&qrd_l42q_4v20_3200mah&;
qcom,batt-id-kohm = &10&;
The battery idresistance of the battery. It can be used as an array which could supportmultiple IDs for one battery module when the ID resistance of some batterymodules goes across several ranges.
电池ID电阻:当一些电池模型的ID电阻在一定范围内浮动时,电池ID电阻可以作为单电池模型数组以支持多ID
qcom,chg-term-ua = &96000&;
The terminationcharging current of the battery电池的结束充电电流,这里为96mA
qcom,default-rbatt-mohm =&120&;
The nominalbattery resistance value蓄电池电阻值
qcom,fcc-mah = &3200&;
Full charge countof the battery in milliamp-hours完全充满时电池容量为3200mAh
qcom,max-voltage-uv =&4200000&;
The maximum ratedvoltage of the battery电池最大的额定电压
qcom,rbatt-capacitive-mohm =&50&;
The capacitiveresistance of the battery电池的电容电阻
qcom,v-cutoff-uv = &3400000&;
The cutoffvoltage of the battery at which the device should shutdown gracefully
电池的截止电压,当电池电压低于此值时设备会自动关机
qcom,fcc-temp-lut {
qcom,lut-col-legend = &(-20) 025 40 60&;
qcom,lut-data = &6&;
电池配置数据需要fcc-temp-lut子节点
- qcom,fcc-temp-lut : An 1-dimensionallookup table node that encodes temperature to fcc lookup. The units for thislookuptable should be degrees celsius to milliamp-hours.
一维查找表节点会将温度编码成fcc查找。该方法的单位也应该从摄氏度变成毫安时。
- qcom,lut-col-legend : An array thatencodes the legend of the lookup table's
columns.The length of this array will determine the
lookuptable's width.
- qcom,lut-data : An array that encodes thelookup table's data. The size of this
arrayshould be equal to the size of qcom,lut-col-legend
multipliedby 1 if it's a 1-dimensional table, or
thesize of qcom,lut-row-legend if it's a 2-dimensional
table.The data should be in a flattened row-major
representation.如果lut-row-legend是一个二维表,lut-data相应的是一个偏平行表示
qcom,ibat-acc-lut{
qcom,lut-col-legend= &(-20) 0 25&;
qcom,lut-row-legend = &0 0 1500&,
qcom,lut-data= &02&,
Lookup table optional properties:
- qcom,lut-row-legend : An array thatencodes the legend of the lookup table's rows.
Ifthis property exists, then it is assumed that the
lookuptable is a 2-dimensional table.
qcom,pc-temp-ocv-lut{
qcom,lut-col-legend= &(-20) 0 25 40 60&;
qcom,lut-row-legend= &100 95 90 85 80&,
&109 8 7 6&,
&54 3 2 1&,
qcom,lut-data = &3 &,
- qcom,pc-temp-ocv-lut : A 2-dimensionallookup table node that encodes
temperatureand percent charge to open circuit voltage
lookup.The units for this lookup table should be
degreescelsius and percent to millivolts.
一个包含温度和百分比的开路电压2维查找表,查找表的单位是百分比和电压的关系
- qcom,rbatt-sf-lut : A 2-dimentionallookup table node that encodes
temperatureand percent charge to battery internal
resistance lookup. Theunits for this lookup table
shouldbe degrees celsius and percent to milliohms.
2.msm8909-qrd-skue-cb03.dtsi
qrd_batterydata:qcom,battery-data {
qcom,rpull-up-kohm= &0&;
qcom,vref-batt-therm= &1800000&;
//#include&batterydata-qrd-l45q-4v35-1800mah.dtsi&
#include&batterydata-qrd-l42q-4v20-3200mah.dtsi&
//#include&batterydata-qrd-skue-4v35-2000mah.dtsi&
&pm8909_chg {
qcom,vddmax-mv= &4200&; //Target voltage of battery in mV.电池电压值
qcom,vddsafe-mv= &4380&;// Maximum Vdd voltage in mV,电池最高的安全电压会比4.2V会高一些。你们电池规格是上面会有的
qcom,vinmin-mv= &4470&;// Minimum input voltage in mV. 这个是VBUS进到充电IC的最低电压。 一般是5V, 4470是最低的值
qcom,batt-hot-percentage= &25&;
qcom,batt-cold-percentage= &80&;
qcom,tchg-mins= &360&;
qcom,bms-controlled-
qcom,disable-vbatdet-based-
status= &okay&;
//qcom,use-external-
qcom,charging-
3.msm-pm8909.dtsi
pm8909_chg: qcom,charger {
compatible= &qcom,qpnp-linear-charger&;
#address-cells= &1&;
#size-cells= &1&;
qcom,vddmax-mv= &4200&;
qcom,vddsafe-mv= &4230&;//&4200&;
qcom,vinmin-mv= &4470&;//&4308&//
qcom,ibatsafe-ma= &1440&;
qcom,thermal-mitigation= & 0&;
qcom,cool-bat-decidegc= &100&;
qcom,warm-bat-decidegc= &450&;
qcom,cool-bat-mv= &4100&;
qcom,warm-bat-mv= &4100&;
qcom,ibatmax-warm-ma= &360&;
qcom,ibatmax-cool-ma= &360&;
qcom,batt-hot-percentage= &25&;
qcom,batt-cold-percentage= &80&;
qcom,tchg-mins= &232&;
qcom,chg-vadc= &&pm8909_vadc&;
qcom,chg-adc_tm= &&pm8909_adc_tm&;
status= &disabled&;
qcom,chgr@1000{
reg= &0x&;
interrupts=
&0x0 0x10 0x7&,
&0x00x10 0x6&,
&0x00x10 0x5&,
&0x00x10 0x0&;
interrupt-names=
&chg-done&,
&chg-failed&,
&fast-chg-on&,
&vbat-det-lo&;
qcom,bat-if@1200{
reg= &0x&;
interrupts=
&0x0 0x12 0x1&,
&0x00x12 0x0&;
interrupt-names=
&bat-temp-ok&,
&batt-pres&;
qcom,usb-chgpth@1300{
reg= &0x&;
interrupts=
&0 0x13 0x4&,
&00x13 0x2&,
&00x13 0x1&;
interrupt-names=
&usb-over-temp&,
&chg-gone&,
&usbin-valid&;
qcom,chg-misc@1600{
reg= &0x&;本文转载自:
上一篇主要讲电池相关的一些知识,上节忘记讲了,电池一般分为电量计电池和非电流计电池,电量计电池,就不需要用pmu8916的IC,当然这只是只,不需要BMS来计算soc,而jni层也需要读取电流计的电池相关属性。
这一节主要是根据代码进行相关的分析。
1. 先看probe的代码:
static int qpnp_vm_bms_probe(struct spmi_device *spmi)
...........
..........
...........
..........
//这里把电池的配置文件dtsi的读出来,并存到当前的结构体。
rc = set_battery_data(chip);
rc = config_battery_data(chip-&batt_data);
..........
..........
//这个是核心的工作,一个线程,BMS的主要内容在此
INIT_DELAYED_WORK(&chip-&monitor_soc_work, monitor_soc_work);
..........
..........
//电池一些常规的检测,主要从PMIC上读到的相关信息
battery_insertion_check(chip);
battery_status_check(chip);
/* character device to pass data to the userspace */
rc = register_bms_char_device(chip);
pr_err("Unable to regiter '/dev/vm_bms' rc=%d\n", rc);
goto fail_bms_
the_chip =
//这个也很重要,我们从上节知道,初值last_ocv_soc是非常重要的,决定着后面的soc估值算法
calculate_initial_soc(chip);
//设置和注册电池的power supply
/* setup & register the battery power supply */
chip-&bms_psy.name = "bms";
chip-&bms_psy.type = POWER_SUPPLY_TYPE_BMS;
chip-&bms_psy.properties = bms_power_
chip-&bms_psy.num_properties = ARRAY_SIZE(bms_power_props);
chip-&bms_psy.get_property = qpnp_vm_bms_power_get_
chip-&bms_psy.set_property = qpnp_vm_bms_power_set_
chip-&bms_psy.external_power_changed = qpnp_vm_bms_ext_power_
chip-&bms_psy.property_is_writeable = qpnp_vm_bms_property_is_
chip-&bms_psy.supplied_to = qpnp_vm_bms_
chip-&bms_psy.num_supplicants = ARRAY_SIZE(qpnp_vm_bms_supplicants);
rc = power_supply_register(chip-&dev, &chip-&bms_psy);
if (rc & 0) {
pr_err("power_supply_register bms failed rc = %d\n", rc);
goto fail_
.....................
....................
....................
//这里启动工作线程
schedule_delayed_work(&chip-&monitor_soc_work, 0);
..........................
.......................
2. 分析如何确定初始的last_ocv_uv:
static int calculate_initial_soc(struct qpnp_bms_chip *chip)
//读当前电池温度
rc = get_batt_therm(chip, &batt_temp);
............
//读PON OCV
rc = read_and_update_ocv(chip, batt_temp, true);
..........
//读关机保存的soc和last_soc_uv
rc = read_shutdown_ocv_soc(chip);
//这里判断是使用估计soc还是估值soc。如果chip-&warm_reset 为真
if (chip-&warm_reset) {
if (chip-&shutdown_soc_invalid) { //这个是dtsi的一个配置选项,若没有配置,
//则不使用关机soc
est_ocv = estimate_ocv(chip); //估值soc
chip-&last_ocv_uv = est_
chip-&last_ocv_uv = chip-&shutdown_//使用关机的soc和ocv
pr_err("Hyan %d : set chip-&last_ocv_uv = %d\n", __LINE__, chip-&last_ocv_uv);
chip-&last_soc = chip-&shutdown_
chip-&calculated_soc = lookup_soc_ocv(chip,
chip-&shutdown_ocv, batt_temp);
if (chip-&workaround_flag & WRKARND_PON_OCV_COMP)
adjust_pon_ocv(chip, batt_temp);
/* !warm_reset use PON OCV only if shutdown SOC is invalid */
chip-&calculated_soc = lookup_soc_ocv(chip,
chip-&last_ocv_uv, batt_temp);
if (!chip-&shutdown_soc_invalid &&
(abs(chip-&shutdown_soc - chip-&calculated_soc) &
chip-&dt.cfg_shutdown_soc_valid_limit)) {
chip-&last_ocv_uv = chip-&shutdown_
chip-&last_soc = chip-&shutdown_
chip-&calculated_soc = lookup_soc_ocv(chip,
chip-&shutdown_ocv, batt_temp);//使用估值soc
chip-&shutdown_soc_invalid = //使用关机soc
.............
............
//得到PON OCV
rc = read_and_update_ocv(chip, batt_temp, true);
ocv_uv = convert_vbatt_raw_to_uv(chip, ocv_data, is_pon_ocv);
uv = vadc_reading_to_uv(reading, true); //读ADC值
uv = adjust_vbatt_reading(chip, uv);
//转化为soc_uv
rc = qpnp_vbat_sns_comp_result(chip-&vadc_dev, &uv, is_pon_ocv); //根据IC的类型,进行温度补偿
//从寄存器中读到储存的soc和ocv
read_shutdown_ocv_soc
rc = qpnp_read_wrapper(chip, (u8 *)&stored_ocv,
chip-&base + BMS_OCV_REG, 2);
rc = qpnp_read_wrapper(chip, &stored_soc, chip-&base + BMS_SOC_REG, 1);
adjust_pon_ocv(struct qpnp_bms_chip *chip, int batt_temp)
rc = qpnp_vadc_read(chip-&vadc_dev, DIE_TEMP, &result);
pc = interpolate_pc(chip-&batt_data-&pc_temp_ocv_lut,
batt_temp, chip-&last_ocv_uv / 1000); //根据ocv和temp,查表得PC(soc)。
rbatt_mohm = get_rbatt(chip, pc, batt_temp); //根据soc和temp,得电池内阻zhi
/* convert die_temp to DECIDEGC */
die_temp = (int)result.physical / 100;
current_ma = interpolate_current_comp(die_temp);
//当前电流
delta_uv = rbatt_mohm * current_
chip-&last_ocv_uv += delta_
//修正last_ocv_uv
//这个函数主要根据last_ocv_uv,计算出soc的
lookup_soc_ocv(struct qpnp_bms_chip *chip, int ocv_uv, int batt_temp)
//查表得到soc_ocv,soc_cutoff
soc_ocv = interpolate_pc(chip-&batt_data-&pc_temp_ocv_lut,
batt_temp, ocv_uv / 1000);
soc_cutoff = interpolate_pc(chip-&batt_data-&pc_temp_ocv_lut,
batt_temp, chip-&dt.cfg_v_cutoff_uv / 1000);
soc_final = DIV_ROUND_CLOSEST(100 * (soc_ocv - soc_cutoff),
(100 - soc_cutoff));
if (batt_temp & chip-&dt.cfg_low_temp_threshold)
iavg_ma = calculate_uuc_iavg(chip);
iavg_ma = chip-&current_now / 1000;
//查表得到FCC,ACC
fcc = interpolate_fcc(chip-&batt_data-&fcc_temp_lut,
batt_temp);
acc = interpolate_acc(chip-&batt_data-&ibat_acc_lut,
batt_temp, iavg_ma);
//计算出UUC
soc_uuc = ((fcc - acc) * 100) /
if (batt_temp & chip-&dt.cfg_low_temp_threshold)
soc_uuc = adjust_uuc(chip, soc_uuc);
//得到soc_acc
soc_acc = DIV_ROUND_CLOSEST(100 * (soc_ocv - soc_uuc),
(100 - soc_uuc));
soc_final = soc_
//这个为上报的soc
chip-&last_acc =
3. 看工作线程,monitor_soc_work(struct work_struct *work):
static void monitor_soc_work(struct work_struct *work)
calculate_delta_time(&chip-&tm_sec, &chip-&delta_time_s);
rc = get_batt_therm(chip, &batt_temp);
new_soc = lookup_soc_ocv(chip, chip-&last_ocv_uv,batt_temp);
new_soc = clamp_soc_based_on_voltage(chip, new_soc);
report_vm_bms_soc(chip);//上报事件,上层得到消息,调用qpnp_vm_bms_power_get_property,获取相关的属性,计算出
last_ocv_uv,并通过qpnp_vm_bms_power_set_property方法,设置last_ocv_uv,并启动monitor_soc_work。
阅读(...) 评论()高通BMS的理解 - 推酷
高通BMS的理解
(荷电状态)计算方法
FCC&&Full-charge capacity &&&&&
UC &&&&Remaining capacity
CC &&&&Coulumb counter &&&
UUC&&Unusable capacity
RUC &&Remaining usable capacity // &&&RUC=RC-CC-UUC
SoC &&State of charge &&&
OCV &&&Open circuit voltage
SOC=(RC-CC-UUC)/(FCC-UUC)
以下是各个变量的计算方法:
在校准的电池
会随温度有变化;
static struct single_row_lut fcc_temp = {
&.x&&= {-20, 0, 25, 40, 60},
&.y&&= {, , 3183},
&.cols&= 5
开机通过开始获取的开路电压(
)来查表(电池校准的
文件)计算百分比,来比对计算(电压与电荷量正比);
(ocv=vbatt+rbatt*i_ma)
内核计算方法:
static int calculate_remaining_charge_uah(struct pm8921_bms_chip *chip,
&&&&&&struct pm8921_soc_params *raw,
&&&&&&int fcc_uah, int batt_temp,
&&&&&&int chargecycles)
&int &ocv, pc, batt_temp_
&ocv = raw-&last_good_ocv_
&batt_temp_decidegc = chip-&last_ocv_temp_
&pc = calculate_pc(chip, ocv, batt_temp_decidegc, chargecycles);
&pr_info(&ocv = %d pc = %d\n&, ocv, pc);
&return (fcc_uah * pc) / 100;
但是通常情况下开机使用计算
是上次关机存下的百分比,反向查表算出的
现在我们做法是通过判断开机时的
如果偏差太大,我们将采用开机
,所以开机的
对开机的百分比影响非常大;
库伦计获取到的:
内核获取方法:
* calculate_cc_uah -
* @chip:&&the bms chip pointer
* @cc:&&&the cc reading from bms h/w
* @val:&&return value
* @coulumb_counter:&adjusted coulumb counter for 100%
* RETURNS: in val pointer coulumb counter based charger in uAh
* &&&&&&&(micro Amp hour)
static void calculate_cc_uah(struct pm8921_bms_chip *chip, int cc, int *val)
&int64_t cc_voltage_uv, cc_pvh, cc_
&cc_voltage_uv =
&pr_debug(&cc = %d\n&, cc);
&cc_voltage_uv = cc_to_microvolt(chip, cc_voltage_uv);
&cc_voltage_uv = pm8xxx_cc_adjust_for_gain(cc_voltage_uv);
&pr_debug(&cc_voltage_uv = %lld microvolts\n&, cc_voltage_uv);
&cc_pvh = ccmicrovolt_to_pvh(cc_voltage_uv);
&pr_debug(&cc_pvh = %lld pico_volt_hour\n&, cc_pvh);
&cc_uah = div_s64(cc_pvh, chip-&r_sense_uohm);
&*val = cc_
计算方法和
一致,但是
是动态变化的,会复杂点;
static int calculate_termination_uuc(struct pm8921_bms_chip *chip,
&&&&&int batt_temp, int chargecycles,
&&&&int fcc_uah, int i_ma,
&&&&int *ret_pc_unusable)
&int unusable_uv, pc_unusable,
&int i = 0;
&int batt_temp_degc = batt_temp / 10;
&int rbatt_
&int delta_
&int prev_delta_uv = 0;
&int prev_rbatt_mohm = 0;
&int prev_ocv_mv = 0;
&int uuc_rbatt_
&for (i = 0; i &= 100; i++) {
&&ocv_mv = interpolate_ocv(chip-&pc_temp_ocv_lut,
&&&&batt_temp_degc, i);
&&rbatt_mohm = get_rbatt(chip, i, batt_temp);
&&unusable_uv = (rbatt_mohm * i_ma) + (chip-&v_cutoff * 1000);
&&delta_uv = ocv_mv * 1000 - unusable_
&&pr_debug(&soc = %d ocv = %d rbat = %d u_uv = %d delta_v = %d\n&,
&&&&i, ocv_mv, rbatt_mohm, unusable_uv, delta_uv);
&&if (delta_uv &&0)
&&prev_delta_uv = delta_
&&prev_rbatt_mohm = rbatt_
&&prev_ocv_mv = ocv_
&uuc_rbatt_uv = linear_interpolate(rbatt_mohm, delta_uv,
&&&&&prev_rbatt_mohm, prev_delta_uv,
&unusable_uv = (uuc_rbatt_uv * i_ma) + (chip-&v_cutoff * 1000);
&pc_unusable = calculate_pc(chip, unusable_uv, batt_temp, chargecycles);
&uuc = (fcc_uah * pc_unusable) / 100;
&pr_debug(&For i_ma = %d, unusable_rbatt = %d unusable_uv = %d unusable_pc = %d uuc = %d\n&,
&&&&&i_ma, uuc_rbatt_uv, unusable_uv,
&&&&&pc_unusable, uuc);
&*ret_pc_unusable = pc_
高通的这套
算法运行起来由于
的校准和温度等等原因,会有一定的偏差,高通还有一套通过校准
)的机制,下面就是使用这套来校准
高通算法通过对
比较计算出
的差值,来改变
last_ocv_uv
的值,主要是改变
,重新计算
,将会使得
越来越接近,越来越准;
但是只有在&
的情况下才会发生校准,而有时在&
的情况下就上报百分比等于
了,会出现关机电压过高的问题。所以函数
adjust_soc
里面许多地方需要我们自己微调;
&只有开机时库伦计
在开机时就固定,但是当温度变化时由于
的几个值在变化,
会随之变化;当校准
时才会引起
查表得到的
变化而导致
&所以还是开机
至关重要,不准到低电时才微调
变化。但是电池电压偏高的时候微调
对百分比不敏感,所以方法中选择了在
的时候微调。
&6&[ ] read_soc_params_raw:
last_good_ocv_uv= 3777000uV
&6&[ ] read_soc_params_raw: last_good_ocv_raw= 0x943f, last_good_ocv_uv= 3777000uV
&6&[ ] calculate_soc_params: FCC = 3190000uAh batt_temp = 300, cycles = 0
&6&[ ] calculate_remaining_charge_uah: ocv = 3777000 pc = 35
&6&[ ] calculate_soc_params: RC = 1116500uAh
&6&[ ] calculate_soc_params: cc_uah = 394979uAh raw-&cc = 5764312
&6&[ ] calculate_state_of_charge: RUC(RC-CC-UUC) = 657721uAh RC = 1116500uAh CC= 394979uAh UUC= 63800uAh FCC= 3190000uAh SOC(RUC/FCC-UUC) =21
adjust_soc
&static int last_soc_est = -EINVAL;
static int adjust_soc(struct pm8921_bms_chip *chip, int soc,
&&int batt_temp, int chargecycles,
&&int rbatt, int fcc_uah, int uuc_uah, int cc_uah)
&int ibat_ua = 0, vbat_uv = 0;
&int ocv_est_uv = 0, soc_est = 0, pc_est = 0, pc = 0;
&int delta_ocv_uv = 0;
&int n = 0;
&int rc_new_uah = 0;
&int pc_new = 0;
&int soc_new = 0;
&int m = 0;
&int rc = 0;
&int delta_ocv_uv_limit = 0;
&int correction_limit_uv = 0;
&rc = pm8921_bms_get_simultaneous_battery_voltage_and_current(
&&&&&&&&ibat_ua,
&&&&&&&&vbat_uv);
&if (rc &&0) {
&&pr_err(&simultaneous vbat ibat failed err = %d\n&, rc);
&very_low_voltage_check(chip, ibat_ua, vbat_uv);
&if (chip-&low_voltage_detect &&
&&wake_lock_active(&chip-&low_voltage_wake_lock)) {
&&if (is_voltage_below_cutoff_window(chip, ibat_ua, vbat_uv)) {
&&&soc = 0;
&&&pr_info(&Voltage below cutoff, setting soc to 0\n&);
&delta_ocv_uv_limit = DIV_ROUND_CLOSEST(ibat_ua, 1000);
&ocv_est_uv = vbat_uv + (ibat_ua * rbatt)/1000;
&calc_current_max(chip, ocv_est_uv, rbatt);
&pc_est = calculate_pc(chip, ocv_est_uv, batt_temp, last_chargecycles);
&soc_est = div_s64((s64)fcc_uah * pc_est - uuc_uah*100,
&&&&&&(s64)fcc_uah - uuc_uah);
&soc_est = bound_soc(soc_est);
&/* never adjust during bms reset mode */
&if (bms_reset) {
&&pr_debug(&bms reset mode, SOC adjustment skipped\n&);
&if (ibat_ua &&0 && pm8921_is_batfet_closed()) {
&&soc = charging_adjustments(chip, soc, vbat_uv, ibat_ua,
&&&&batt_temp, chargecycles,
&&&&fcc_uah, cc_uah, uuc_uah);
&&* do not adjust
&&* if soc_est is same as what bms calculated
&&* OR if soc_est &&15
&&* OR if soc it is above 90 because we might pull it low
&&* and &cause a bad user experience
&if (soc_est == soc
&&|| soc_est &&15
&&|| soc &= 90)
&if (last_soc_est == -EINVAL)
&&last_soc_est =
&n = min(200, max(1 , soc + soc_est + last_soc_est));
&/* remember the last soc_est in last_soc_est */
&last_soc_est = soc_
&pc = calculate_pc(chip, chip-&last_ocv_uv,
&&&chip-&last_ocv_temp_decidegc, last_chargecycles);
&if (pc &&0) {
&&pc_new = calculate_pc(chip, chip-&last_ocv_uv - (++m * 1000),
&&&&&chip-&last_ocv_temp_decidegc,
&&&&&last_chargecycles);
&&while (pc_new == pc) {
&&&/* start taking 10mV steps */
&&&m = m + 10;
&&&pc_new = calculate_pc(chip,
&&&&&&chip-&last_ocv_uv - (m * 1000),
&&&&&&chip-&last_ocv_temp_decidegc,
&&&&&&last_chargecycles);
&&&* pc is already at the lowest point,
&&&* assume 1 millivolt translates to 1% pc
&&pc_new = 0;
&delta_ocv_uv = div_s64((soc - soc_est) * (s64)m * 1000,
&&&&&&&n * (pc - pc_new));
&if (abs(delta_ocv_uv) &&delta_ocv_uv_limit) {
&&pr_debug(&limiting delta ocv %d limit = %d\n&, delta_ocv_uv,
&&&&delta_ocv_uv_limit);
&&if (delta_ocv_uv &&0)
&&&delta_ocv_uv = delta_ocv_uv_
&&&delta_ocv_uv = -1 * delta_ocv_uv_
&&pr_debug(&new delta ocv = %d\n&, delta_ocv_uv);
&if (wake_lock_active(&chip-&low_voltage_wake_lock)) {
&&pr_debug(&Low Voltage, apply only ibat limited corrections\n&);
&&goto skip_limiting_
&if (chip-&last_ocv_uv &&3800000)
&&correction_limit_uv = the_chip-&high_ocv_correction_limit_
&&correction_limit_uv = the_chip-&low_ocv_correction_limit_
&if (abs(delta_ocv_uv) &&correction_limit_uv) {
&&pr_debug(&limiting delta ocv %d limit = %d\n&, delta_ocv_uv,
&&&&correction_limit_uv);
&&if (delta_ocv_uv &&0)
&&&delta_ocv_uv = correction_limit_
&&&delta_ocv_uv = -1 * correction_limit_
&&pr_debug(&new delta ocv = %d\n&, delta_ocv_uv);
skip_limiting_corrections:
&chip-&last_ocv_uv -= delta_ocv_
&if (chip-&last_ocv_uv &= chip-&max_voltage_uv)
&&chip-&last_ocv_uv = chip-&max_voltage_
&/* calculate the soc based on this new ocv */
&pc_new = calculate_pc(chip, chip-&last_ocv_uv,
&&&chip-&last_ocv_temp_decidegc, last_chargecycles);
&rc_new_uah = (fcc_uah * pc_new) / 100;
&soc_new = (rc_new_uah - cc_uah - uuc_uah)*100 / (fcc_uah - uuc_uah);
&soc_new = bound_soc(soc_new);
&&* if soc_new is ZERO force it higher so that phone doesnt report soc=0
&&* soc = 0 should happen only when soc_est == 0
&if (soc_new == 0 && soc_est &= the_chip-&hold_soc_est)
&&soc_new = 1;
&soc = soc_
&pr_debug(&ibat_ua = %d, vbat_uv = %d, ocv_est_uv = %d, pc_est = %d, &
&&&soc_est = %d, n = %d, delta_ocv_uv = %d, last_ocv_uv = %d, &
&&&pc_new = %d, soc_new = %d, rbatt = %d, m = %d\n&,
&&ibat_ua, vbat_uv, ocv_est_uv, pc_est,
&&soc_est, n, delta_ocv_uv, chip-&last_ocv_uv,
&&pc_new, soc_new, rbatt, m);
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致

我要回帖

更多关于 高通平台是什么意思 的文章

 

随机推荐