第12章:BMS核心算法——SOC与SOH估算
各位同学,今天我们来聊聊BMS里最核心、也最让人头疼的两个算法:SOC和SOH估算。
SOC,全称State of Charge,就是电池还剩多少电。SOH,State of Health,是电池的健康状态。这两个参数,说白了就是电池的“油表”和“体检报告”。
我刚开始做BMS那会儿,觉得SOC估算不就是测个电压嘛,简单。后来被现实狠狠教育了一顿——电池的电压和电量根本不是线性关系,尤其是磷酸铁锂电池,中间一大段电压几乎不变。嗯,这里面的坑,我一个个给你们讲清楚。
12.1 SOC估算:开路电压法
开路电压法,是最基础的方法。原理很简单:电池静置足够长时间后,端电压和SOC之间存在一一对应的关系。我们提前标定好这个关系表,查表就能知道SOC。
但问题来了——什么叫“静置足够长时间”?
我做过测试,一块三元锂电池从满电状态断开负载,电压会先快速下降,然后缓慢趋稳。这个过程少说要30分钟,长的要2小时。你想想看,手机用户能等这么久吗?显然不能。
所以开路电压法只能用在特定场景:比如电动车刚启动时,或者设备长时间待机后首次开机。平时跑起来,这个方法基本废了。
核心要点:开路电压法精度高(误差<2%),但要求电池静置≥30分钟。适合作为初始SOC校准,不适合动态估算。
12.2 SOC估算:安时积分法
安时积分法,也叫库仑计数法。原理更简单:实时测量电流,对时间积分,算出充进去了多少电、放出了多少电。
公式长这样:
SOC(t) = SOC(0) + (1/Q_n) * ∫[0→t] I(t) * η(t) dt
其中Q_n是额定容量,η是库仑效率(充电一般取0.98~0.99,放电取1.0)。
这个方法的好处是实时性好,每秒都能更新SOC。但坏处也很明显——误差会累积。
我曾经在一个项目里,用安时积分法跑了三天,SOC从100%漂到了112%。为什么?因为电流传感器的零点漂移,每次测量都有微小误差,日积月累就爆炸了。
避坑指南:安时积分法必须定期校准。我建议每次充满电时强制置为100%,或者每次静置后用开路电压法修正。否则误差会像滚雪球一样越来越大。
12.3 SOC估算:卡尔曼滤波
卡尔曼滤波,是解决上述问题的终极方案。它把开路电压法和安时积分法融合在一起,取长补短。
简单说,卡尔曼滤波做了两件事:
- 预测:用安时积分法推算下一时刻的SOC
- 更新:用开路电压法(或其他观测值)修正预测结果
它还会根据当前的不确定性,动态调整预测和修正的权重。噪声大的时候多相信测量,噪声小的时候多相信模型。
我给你们画个流程图,一看就明白:
卡尔曼滤波的代码实现也不复杂。我贴一个简化版的一阶卡尔曼滤波,用于SOC估算:
// 一阶卡尔曼滤波SOC估算(简化版)
typedef struct {
float soc; // 状态量:SOC
float P; // 误差协方差
float Q; // 过程噪声
float R; // 测量噪声
} KalmanFilter;
void Kalman_Init(KalmanFilter *kf, float init_soc) {
kf->soc = init_soc;
kf->P = 0.1f; // 初始不确定性
kf->Q = 0.001f; // 过程噪声(安时积分误差)
kf->R = 0.01f; // 测量噪声(电压测量误差)
}
void Kalman_Update(KalmanFilter *kf, float current, float voltage, float dt) {
// 1. 预测:安时积分
float soc_pred = kf->soc + (current * dt) / 3600.0f / Q_n;
float P_pred = kf->P + kf->Q;
// 2. 计算卡尔曼增益
float K = P_pred / (P_pred + kf->R);
// 3. 更新:用电压修正
float soc_meas = OCV_to_SOC(voltage); // 开路电压查表
kf->soc = soc_pred + K * (soc_meas - soc_pred);
kf->P = (1.0f - K) * P_pred;
}
个人经验:卡尔曼滤波的Q和R参数需要根据实际电池特性调优。我一般先用仿真数据跑一遍,再在实际硬件上微调。Q设大了响应快但噪声大,R设大了平滑但滞后。这个平衡点,得靠经验慢慢找。
12.4 SOH估算
SOH,说白了就是电池还能用多久。通常定义为当前容量与额定容量的比值:
SOH = Q_current / Q_rated × 100%
当SOH低于80%时,一般认为电池寿命到了终点。
SOH估算比SOC更难,因为它变化太慢了。一个电池从100%衰减到80%,可能要充放电500次。你没法实时测量,只能通过长期数据来推算。
常用的方法有三种:
| 方法 | 原理 | 优点 | 缺点 |
|---|---|---|---|
| 容量测试法 | 满充+满放,计算实际容量 | 最准确 | 需要完整充放电周期,耗时 |
| 内阻测量法 | 内阻随老化增大,反推SOH | 可在线测量 | 受温度影响大,精度一般 |
| 循环计数法 | 统计充放电次数,查表估算 | 简单易实现 | 不考虑使用工况,误差大 |
我实际项目中,用的是容量测试法+内阻测量法结合。每次充满电时记录一次容量,同时定期测量内阻。两个数据互相印证,准确度能到95%以上。
注意:SOH估算不要频繁更新。我建议每50次充放电周期更新一次,或者每月更新一次。更新太频繁,反而会因为测量噪声导致SOH值来回跳动,用户看了会困惑。
12.5 实际项目中的坑与对策
最后,我总结几个实际项目中踩过的坑:
- 温度补偿:电池的OCV-SOC曲线在不同温度下差异很大。零下10度和40度,同一电压对应的SOC能差15%。一定要做温度查表补偿。
- 电流传感器零点漂移:我遇到过传感器在零电流时输出0.5mA的偏移,一天下来SOC漂了3%。解决办法是定期做零点校准,或者用硬件自动归零。
- 电池老化后的OCV曲线变化:新电池和用了两年的电池,OCV-SOC曲线不一样。我建议每半年重新标定一次曲线,或者用自适应算法在线更新。
- 脉冲负载的影响:手机突然亮屏、电动车急加速,电流瞬间变大,电压会骤降。这时候用电压查SOC会严重偏低。我的做法是加一个低通滤波器,或者检测到脉冲时暂时禁用电压修正。
好了,SOC和SOH估算的核心内容就这些。说白了,没有完美的算法,只有最适合你应用场景的方案。做产品嘛,就是在精度、实时性和成本之间找平衡。
公众号:蓝海资料掘金营,微信deep3321