3、电池SOC估算方法:开路电压法、安时积分法、卡尔曼滤波法、扩展卡尔曼滤波(EKF)仿真
电池SOC(State of Charge,荷电状态)是BMS的核心参数。说白了,它就是电池还剩多少电。我做了这么多年仿真,见过太多因为SOC不准导致的系统故障。今天咱们就把几种主流估算方法掰开揉碎了讲清楚。
3.1 开路电压法(OCV)
这个方法最直观。电池静置足够久,端电压和SOC有固定对应关系。查表就能知道SOC。
优点:简单、准确。静置时间够长,误差能控制在2%以内。
缺点:电池不能带载。你想想看,车在跑的时候,谁给你机会静置?
核心公式:
SOC = f(V_oc) // 查表函数
我在项目中遇到过一个问题:磷酸铁锂电池的OCV曲线太平了。中间段电压变化极小,稍微有点测量噪声,SOC就跳来跳去。后来我加了个滞回比较器,才稳住。
我的经验:OCV法只适合做初始校准。每次系统上电,如果电池静置超过2小时,用OCV法把SOC初始化一下。后面就别指望它了。
3.2 安时积分法(Ah Counting)
这个方法也简单。电流对时间积分,就知道充进去或放出来多少电量。
SOC(t) = SOC(0) - (1/Q_n) * ∫ I(t) dt
其中Q_n是额定容量,I(t)是电流(放电为正)。
优点:实时性好,计算量小。单片机都能跑。
缺点:误差会累积。电流传感器有偏置,积分时间长了,SOC就飘了。
嗯,这里要注意。我曾经有个项目,用了便宜的电流传感器,偏置有5mA。你以为没事?一天下来,SOC漂了8%。客户投诉说电池显示不准,我查了三天才找到原因。
避坑指南:安时积分法必须配合定期校准。否则误差会像滚雪球一样越来越大。我建议每100个充放电周期,至少用OCV法校准一次。
3.3 卡尔曼滤波法(KF)
这才是重头戏。卡尔曼滤波把SOC当成一个状态变量,用模型预测+测量修正的方式,动态估算。
说白了,它不信任单一测量值。它把模型预测和实际测量加权平均,权重由噪声统计特性决定。
核心步骤:
- 预测:根据上一时刻SOC和电流,预测当前SOC
- 更新:用电压测量值修正预测值
- 迭代:重复1和2
标准KF公式(离散形式):
// 预测步骤
x_k|k-1 = A * x_k-1|k-1 + B * u_k
P_k|k-1 = A * P_k-1|k-1 * A^T + Q
// 更新步骤
K_k = P_k|k-1 * H^T * (H * P_k|k-1 * H^T + R)^(-1)
x_k|k = x_k|k-1 + K_k * (z_k - H * x_k|k-1)
P_k|k = (I - K_k * H) * P_k|k-1
你可能会问:Q和R怎么设?我告诉你,这是卡尔曼滤波最玄学的地方。Q是过程噪声协方差,R是测量噪声协方差。设大了,滤波响应慢;设小了,噪声抑制差。
我个人习惯是先做离线实验。把电池充满,静置,记录电压噪声方差作为R。Q嘛,先设个对角线小矩阵,然后调参。
3.4 扩展卡尔曼滤波(EKF)仿真
标准KF只能处理线性系统。但电池是非线性的——OCV-SOC曲线不是直线,RC网络也是非线性的。怎么办?EKF登场。
EKF的核心思想:在每个工作点,把非线性函数做一阶泰勒展开,近似成线性系统。然后套用标准KF的框架。
EKF vs KF的区别:
| 项目 | 标准KF | EKF |
|---|---|---|
| 系统模型 | 线性 | 非线性 |
| 状态转移 | 矩阵A | 函数f(x,u) |
| 观测方程 | 矩阵H | 函数h(x) |
| 雅可比矩阵 | 不需要 | 需要计算 |
仿真代码片段(Python):
import numpy as np
def ekf_predict(x, P, Q, dt, current):
# 状态预测:SOC + RC电压
# 这里简化为一阶RC模型
soc = x[0]
v_rc = x[1]
# 非线性状态转移
soc_pred = soc - (current * dt) / 3600 / Q_n
v_rc_pred = v_rc * np.exp(-dt / tau) + R_rc * current * (1 - np.exp(-dt / tau))
x_pred = np.array([soc_pred, v_rc_pred])
# 雅可比矩阵 F
F = np.array([[1, 0],
[0, np.exp(-dt / tau)]])
P_pred = F @ P @ F.T + Q
return x_pred, P_pred
def ekf_update(x_pred, P_pred, R, v_meas):
# 观测方程:V_t = OCV(SOC) + V_rc + I*R0
soc = x_pred[0]
v_rc = x_pred[1]
# 查OCV表
ocv = ocv_lookup(soc)
v_pred = ocv + v_rc + I_meas * R0
# 雅可比矩阵 H
dOCV_dSOC = (ocv_lookup(soc+0.01) - ocv_lookup(soc-0.01)) / 0.02
H = np.array([[dOCV_dSOC, 1]])
# 卡尔曼增益
S = H @ P_pred @ H.T + R
K = P_pred @ H.T @ np.linalg.inv(S)
# 状态更新
innovation = v_meas - v_pred
x_upd = x_pred + K.flatten() * innovation
P_upd = (np.eye(2) - K @ H) @ P_pred
return x_upd, P_upd
我在实际仿真中发现一个坑:雅可比矩阵计算不当,EKF会发散。特别是OCV曲线斜率突变的地方(比如磷酸铁锂的平坦区),dOCV/dSOC计算不准,滤波器直接崩了。
我的解决办法:用中心差分代替前向差分。同时限制雅可比矩阵的更新步长,别让它跳得太猛。
重要提醒:EKF不是万能的。如果电池模型误差太大(比如温度影响没考虑),EKF的估计精度也会下降。我建议在EKF外面再加一层自适应机制,实时调整Q和R。
3.5 四种方法对比
| 方法 | 精度 | 实时性 | 计算量 | 适用场景 |
|---|---|---|---|---|
| 开路电压法 | 高(静置后) | 差 | 极低 | 初始校准 |
| 安时积分法 | 中等(短期) | 好 | 低 | 实时估算 |
| 卡尔曼滤波 | 较高 | 好 | 中等 | 线性系统 |
| 扩展卡尔曼滤波 | 高 | 好 | 较高 | 非线性系统 |
我个人建议:实际项目中,别只用一种方法。把OCV法做初始校准,安时积分法做主体,EKF做动态修正。三种方法融合,才能得到稳定可靠的SOC估算。
好了,这一章就到这里。下一章咱们聊聊电池模型参数辨识,那是EKF能跑起来的前提。