1. 电池SOC估算的背景与挑战
电池荷电状态(State of Charge, SOC)估算是电池管理系统(BMS)中最核心的功能之一。简单来说,SOC就是电池的"剩余电量百分比",就像手机右上角显示的那个数字。但工业级的SOC估算远比手机复杂得多——误差超过5%就可能引发严重事故。
在实际项目中,我们常遇到三个典型问题:
- 电池电压与SOC的非线性关系(比如20%电量时电压3.7V,30%时可能还是3.7V)
- 充放电电流测量存在噪声和漂移
- 电池老化导致容量衰减(新电池100Ah用两年后可能只剩85Ah)
去年我在参与某储能电站项目时,就遇到过因为SOC估算误差导致电池过放的事故。当时使用传统的安时积分法,由于电流传感器零漂,运行三个月后SOC累计误差达到了12%,最终触发了系统告警。这促使我开始深入研究更鲁棒的估算算法。
2. 三种核心算法原理与实现
2.1 安时积分法:基础但不可靠
安时积分法(Ah-Counting)是最直观的方法,其核心公式:
code复制SOC(t) = SOC(t0) + (η ∫i(t)dt) / Cn
其中η是库伦效率(通常充电0.98,放电1.0),Cn是额定容量。在Matlab中实现仅需几行代码:
matlab复制function soc = ah_integration(current, dt, initial_soc, capacity)
persistent accumulated_ah;
if isempty(accumulated_ah)
accumulated_ah = (1 - initial_soc) * capacity;
end
accumulated_ah = accumulated_ah + current * dt;
soc = 1 - (accumulated_ah / capacity);
end
但这个方法有致命缺陷:
- 完全依赖电流传感器精度
- 无法修正初始误差
- 容量衰减后失效
实测数据:使用0.5%精度的电流传感器,运行72小时后误差已达8.3%
2.2 EKF算法:引入电压观测
扩展卡尔曼滤波(EKF)通过建立电池状态空间模型来改进估算。我们采用二阶RC等效电路模型:
code复制状态方程:
x_k = A·x_{k-1} + B·u_k + w_k
观测方程:
y_k = OCV(z_k) + R·i_k + v_k
其中x_k=[SOC, V1, V2]^T,u_k是电流,y_k是端电压。关键实现步骤:
- 建立OCV-SOC查表(通过实验获取)
- 线性化状态转移矩阵:
matlab复制function [A, B, C] = ekf_linearize(soc, current, model_params)
R0 = model_params.R0;
R1 = model_params.R1;
C1 = model_params.C1;
tau1 = R1*C1;
A = [1 0 0;
0 exp(-dt/tau1) 0;
0 0 exp(-dt/tau2)];
B = [-dt/Qn;
R1*(1-exp(-dt/tau1));
R2*(1-exp(-dt/tau2))];
C = [dOCV/dSOC -1 -1];
end
- 实现预测-更新循环:
matlab复制for k = 2:length(t)
% 预测步骤
x_pred = A * x_est(:,k-1) + B * current(k);
P_pred = A * P_est(:,:,k-1) * A' + Q;
% 更新步骤
K = P_pred * C' / (C * P_pred * C' + R);
x_est(:,k) = x_pred + K * (voltage(k) - (OCV(x_pred(1)) - x_pred(2) - x_pred(3) - R0*current(k)));
P_est(:,:,k) = (eye(3) - K*C) * P_pred;
end
2.3 UEKF算法:突破线性化局限
无迹EKF(UEKF)采用sigma点采样避免雅可比矩阵计算。其核心步骤:
- 选择2n+1个sigma点(n为状态维数):
matlab复制function X = sigma_points(x, P, gamma)
n = length(x);
X = zeros(n, 2*n+1);
X(:,1) = x;
sqrtP = chol((n+gamma)*P)';
for i=1:n
X(:,i+1) = x + sqrtP(:,i);
X(:,i+n+1) = x - sqrtP(:,i);
end
end
- 无迹变换过程:
matlab复制% 生成sigma点
X = sigma_points(x_est(:,k-1), P_est(:,:,k-1), gamma);
% 预测变换
X_pred = zeros(size(X));
for i=1:size(X,2)
X_pred(:,i) = state_transition(X(:,i), current(k), dt);
end
x_pred = X_pred * Wm';
% 观测变换
Z_pred = zeros(1, size(X_pred,2));
for i=1:size(X_pred,2)
Z_pred(i) = observation_model(X_pred(:,i), current(k));
end
z_pred = Z_pred * Wm';
实测对比数据(25℃环境):
| 算法 | 初始误差 | 72小时后误差 | 计算耗时 |
|---|---|---|---|
| 安时积分 | 0% | 8.3% | 0.1ms |
| EKF | 5% | 2.7% | 3.2ms |
| UEKF | 5% | 1.2% | 6.8ms |
3. 完整Matlab实现架构
3.1 工程文件结构
code复制bms_soc_estimation/
├── data/ # 测试数据集
│ ├── battery_ocv.csv
│ └── drive_cycle.mat
├── lib/ # 核心算法库
│ ├── ah_integration.m
│ ├── ekf_core.m
│ └── uekf_core.m
├── models/ # 电池参数模型
│ └── lfp_100ah.mat
└── main.m # 主测试脚本
3.2 关键实现细节
- 电池参数标定(以LiFePO4电池为例):
matlab复制% 在25℃下通过HPPC测试获取
params = struct(...
'Qn', 100, ... % 额定容量(Ah)
'R0', 0.002, ... % 欧姆内阻(Ω)
'R1', 0.001, ... % 极化电阻1(Ω)
'C1', 3000, ... % 极化电容1(F)
'R2', 0.0015, ... % 极化电阻2(Ω)
'C2', 15000); % 极化电容2(F)
- OCV-SOC关系拟合:
matlab复制% 使用5阶多项式拟合实验数据
ocv_data = csvread('battery_ocv.csv');
p = polyfit(ocv_data(:,2), ocv_data(:,1), 5);
ocv_func = @(z) polyval(p,z);
- 主循环处理流程:
matlab复制for k = 2:length(t)
% 读取当前时刻数据
current = meas_i(k);
voltage = meas_v(k);
temp = meas_t(k);
% 参数温度补偿
params = temp_compensation(params, temp);
% 执行估算算法
switch algo_type
case 'AH'
soc(k) = ah_integration(current, dt, soc(k-1), params.Qn);
case 'EKF'
[soc(k), x_est(:,k)] = ekf_update(x_est(:,k-1), current, voltage);
case 'UEKF'
[soc(k), x_est(:,k)] = uekf_update(x_est(:,k-1), current, voltage);
end
end
4. 工程实践中的关键问题
4.1 初始SOC校准
在项目实践中我们发现,EKF类算法对初始值非常敏感。我们开发了三级校准策略:
- 静置判据:当|电流|<0.01C且持续时间>5分钟,用OCV反查SOC
- 充电满判据:电压>3.65V且dQ/dV<0.1%时强制SOC=100%
- 历史数据:记录上次关机前最后10分钟的SOC变化趋势
4.2 模型参数辨识
通过混合脉冲功率特性(HPPC)测试获取模型参数时,要注意:
- 每个SOC点静置1小时后再测试
- 脉冲时间建议10s(太短无法激发极化响应)
- 温度控制在±0.5℃范围内
我们开发了自动参数辨识工具:
matlab复制function params = identify_params(test_data)
options = optimoptions('lsqnonlin', 'Display', 'iter');
init_guess = [0.002, 0.001, 3000, 0.0015, 15000];
params = lsqnonlin(@(x) cost_function(x, test_data), init_guess, [], [], options);
end
function err = cost_function(x, data)
R0 = x(1); R1 = x(2); C1 = x(3); R2 = x(4); C2 = x(5);
% 计算模型输出电压与实测误差
% ...省略详细实现...
end
4.3 实时性优化技巧
在嵌入式平台部署时,我们采用以下优化:
- 预计算OCV-SOC查表(0.1%间隔)
- 固定点运算替代浮点(Q15格式)
- 矩阵运算展开为标量运算
- 降低更新频率(从1kHz降到100Hz)
优化前后对比(STM32F407平台):
| 操作 | 优化前 | 优化后 |
|---|---|---|
| EKF单次执行 | 1.2ms | 0.3ms |
| UEKF单次执行 | 2.8ms | 0.7ms |
| RAM占用 | 12KB | 4KB |
5. 不同场景下的算法选择建议
根据实际项目经验,给出以下推荐:
-
储能电站:
- 特点:充放电平稳,对实时性要求低
- 推荐:UEKF + 每日零点OCV校准
- 预期精度:<2%
-
电动汽车:
- 特点:动态工况,需快速响应
- 推荐:EKF + 安时积分融合(权重各50%)
- 预期精度:<3%
-
消费电子:
- 特点:低成本,低功耗
- 推荐:改进型安时积分(带电压修正)
- 预期精度:<5%
在最近参与的某车用电池项目中,我们采用EKF+安时积分融合方案,经过3万公里路试,SOC估算误差始终保持在2.5%以内。关键是在急加速时增加电流权重,滑行时增加电压权重,这种动态调整策略效果显著。