其它积累 · 2023年8月31日

常用电池电量计算方式【BATTERY】

常用电池电量计算方法

一.查表法

正常来说,电池厂商会提供一个OCV曲线表,在不同的温度下,OCV曲线不同,当然不同的温度下的,其电量也不尽相同,

不同的电压值对应不同的电量百分比

优点:便于调节

缺点:需要测试测很多组数据,进行平均,尤其是电池一致性不好时,处理起来,更费劲。

const int ocv_4v4[] = {
3200,
3300,3350,3380,3400, 3424,3525,3594,3644,3671,3680,
3684,3686,3688,3689,3692,3700,3709,3715,3722,3729,
3735,3739,3744,3747,3751,3756,3760,3764,3767,3771,
3775,3778,3782,3786,3789,3793,3797,3801,3805,3809,
3813,3818,3822,3827,3832,3837,3842,3848,3854,3860,
3866,3873,3880,3888,3896,3906,3917,3930,3943,3955,
3964,3972,3979,3988,3999,4013,4030,4047,4059,4067,
4074,4084,4096,4107,4119,4131,4142,4154,4166,4177,
4189,4202,4214,4226,4238,4250,4263,4275,4287,4300,
4312,4324,4336,4348,4350,4355,4358,4359,4360,4362,
};

const int ocv_4v1[] = {
3200,
3300,3350,3380,3400,3424,3525,3594,3644,3671,3680,
3684,3686,3688,3689,3692,3700,3709,3715,3722,3729,
3735,3739,3744,3747,3751,3756,3760,3764,3767,3771,
3775,3778,3782,3786,3789,3793,3797,3801,3805,3809,
3813,3818,3822,3827,3832,3837,3842,3848,3852,3857,
3860,3866,3870,3876,3880,3884,3888,3895,3899,3906,
3910,3915,3918,3920,3925,3930,3935,3942,3947,3950,
3955,3960,3964,3972,3979,3982,3988,3993,3999,4005,
4007,4013,4018,4020,4025,4030,4035,4040,4042,4047,
4053,4059,4063,4068,4074,4080,4085,4090,4095,4103,
};

define OCV_SIZE 100

for( i = 1 ;i < OCV_SIZE; i++ ){
    if(volt < ocv_table[i])
        break;
}
printk("volt :%d ,ocv_table is [%d] \n",volt,i);

return i;

}

二 曲线拟合法

相比上面的查表法,要稍一点技术含量,需要根据电池厂商提供的曲线来进行做几段的曲线拟合

term_volt = term_volt -40;

current_mv = upm->bat_volt;

if(current_mv >= term_volt ){
    present = 100;
    return present;
}

molecule = term_volt - current_mv ;

denominator = term_volt - UPM6920_CLOSE_VOLT;

present =100 - (( molecule*100) / denominator) ; 

if(present >= 99)
    present = 100;

更复杂一点,用积分去拟合,其实就是单线拟合改多线去拟合
用积分方式,把电池放电曲线,按同等时间分成10等分,每等分看似一个固定斜率
#define ARRAY_DIM(a) (sizeof(a) / sizeof((a)[0]))
const static int Battery_Level_Percent_Table[11] = {3000, 3650, 3700, 3740, 3760, 3795, 3840, 3910, 3980, 4070, 4150};
int toPercentage(int voltage)
{
	int i = 0;
	if(voltage < Battery_Level_Percent_Table[0])
		return 0;
 
	for(i; i<ARRAY_DIM(Battery_Level_Percent_Table); i++){
		if(voltage < Battery_Level_Percent_Table[i])
			return i*10 - (10UL * (int)(Battery_Level_Percent_Table[i] - voltage)) / 
			(int)(Battery_Level_Percent_Table[i] - Battery_Level_Percent_Table[i-1]);;
	}
 
	return 100;
}
 
/*
测试函数,输入电压值,输出百分比值
*/
void test_func(void)
{
	int i;
	while(1){
		printf("please input value:");
		scanf("%d",&i);
		printf("valu = %d\n",toPercentage(i));
	}
}
Battery_Level_Percent_Table中是电压的参考值,从0~100共11个点,电压值的单位为mV。

优点:不用去做一个表去查,只需要根据厂商的电池曲线进行做一元方程,即可
缺点:如果曲线非线性,过于多的直线去拟合,导致算法过于复杂。
打赏作者