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当成一个状态变量,用模型预测+测量修正的方式,动态估算。

说白了,它不信任单一测量值。它把模型预测和实际测量加权平均,权重由噪声统计特性决定。

核心步骤:

  1. 预测:根据上一时刻SOC和电流,预测当前SOC
  2. 更新:用电压测量值修正预测值
  3. 迭代:重复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能跑起来的前提。