3. 电池单体模型建立(一阶RC等效电路模型)
好,咱们今天聊聊电池建模。说实话,这是整个BMS算法的基础。你想想看,如果连电池的行为都描述不准,那SOC估算、SOH诊断这些上层功能,基本就是空中楼阁。
我个人习惯,在项目初期先花时间把模型搞扎实。因为后面所有的标定、验证工作,都依赖这个模型。模型不准,后面全是白费功夫。
3.1 电化学模型 vs 等效电路模型
先说说两种主流建模思路。很多新手会纠结选哪个,我当年也困惑过。
电化学模型,说白了就是基于电池内部的物理化学反应来建模。它考虑锂离子在正负极之间的嵌入、脱出,电解液中的扩散,SEI膜的生长等等。精度高,但参数多,计算量大。我在做动力电池热失控预警时用过,模型跑一次要几分钟,根本没法在嵌入式MCU上实时运行。
等效电路模型,则是用电阻、电容这些电路元件来模拟电池的外特性。它不关心内部具体发生了什么,只关心端电压对电流的响应。计算量小,参数少,非常适合实时控制。
做个对比你就明白了:
| 对比项 | 电化学模型 | 等效电路模型 |
|---|---|---|
| 物理意义 | 强,反映内部机理 | 弱,仅描述外特性 |
| 计算复杂度 | 高(偏微分方程) | 低(常微分方程) |
| 参数数量 | 几十个 | 3~5个 |
| 实时性 | 差 | 好 |
| 工程应用 | 仿真分析、老化研究 | BMS实时控制 |
所以,在BMS量产项目中,99%的情况都选等效电路模型。一阶RC模型是其中最经典、最实用的一个。
核心结论: 电化学模型适合做研究,等效电路模型适合做产品。别搞反了。
3.2 一阶RC模型数学推导
一阶RC模型长什么样?说白了就是一个电压源串联一个电阻,再并联一个RC网络。电压源代表开路电压(OCV),串联电阻R0代表欧姆内阻,RC网络代表极化效应。
为什么会这样?因为电池在充放电时,电压不是瞬间跳变的。你突然拉一个电流,电压会先掉一截(欧姆内阻导致),然后慢慢再降一点(极化效应导致)。这个「慢慢降」的过程,就是RC网络在起作用。
数学上,模型的状态方程是这样的:
状态方程:
dVp/dt = -Vp/(Rp*Cp) + I/Cp
输出方程:
Vt = OCV(SOC) - Vp - I*R0
其中:
- Vt:端电压(我们实际能测到的)
- OCV:开路电压(与SOC一一对应)
- Vp:极化电压(RC网络上的电压)
- I:电流(放电为正,充电为负)
- R0:欧姆内阻
- Rp:极化内阻
- Cp:极化电容
离散化之后,我们才能在嵌入式代码里用。我一般用前向欧拉法,采样时间Ts取0.1s:
Vp(k) = Vp(k-1) * exp(-Ts/(Rp*Cp)) + I(k-1) * Rp * (1 - exp(-Ts/(Rp*Cp)))
Vt(k) = OCV(k) - Vp(k) - I(k) * R0
嗯,这里要注意。离散化公式里的指数项,在代码里要提前算好,别在循环里反复计算exp函数,太费时间了。
个人经验: 我曾经在项目里直接用浮点exp函数,结果MCU跑一次要200多微秒。后来改成查表法,降到5微秒。嵌入式开发,能查表就别计算。
3.3 Simulink模型搭建
模型搭起来其实不复杂。我习惯用Simscape Electrical里的元件,但为了代码生成方便,我建议直接用基础模块搭。
核心模块就这几个:
- OCV查表模块:输入SOC,输出OCV。用1-D Lookup Table
- 欧姆内阻模块:R0 * I,用Gain和Product
- RC网络模块:用Discrete Transfer Fcn或者自己搭差分方程
- 加法器:把OCV减去Vp减去I*R0
下面是我常用的模型结构图,用SVG画出来方便你理解:
模型搭好后,记得在Simulink里设置离散求解器,步长固定。我一般设0.1s,和BMS主循环周期一致。
注意: 千万别用连续求解器!代码生成后,MCU是离散运行的,连续模型生成的代码会有定时器问题,跑起来误差很大。
3.4 参数辨识
模型搭好了,参数从哪来?不能拍脑袋吧。参数辨识,说白了就是通过实验数据反推模型参数。
我常用的方法是混合脉冲功率特性测试(HPPC)。流程是这样的:
- 把电池充到满电,静置1小时
- 以1C电流放电10秒,静置40秒
- 以0.75C电流充电10秒,静置40秒
- 放电5% SOC,重复步骤2~3
- 一直做到SOC=0%
拿到数据后,用最小二乘法拟合。具体来说:
- R0:看电流跳变瞬间的电压变化。ΔV / ΔI 就是R0
- Rp、Cp:看静置阶段的电压恢复曲线。用指数拟合 V(t) = V0 + A * exp(-t/τ),τ = Rp*Cp
- OCV:静置结束时的电压,就是该SOC点的OCV
我在MATLAB里写过脚本,直接读HPPC数据,自动算参数。核心代码片段如下:
% 参数辨识脚本片段
% 输入:时间t,电流I,电压V
% 输出:R0, Rp, Cp, OCV
% 1. 找电流跳变点
dI = diff(I);
jump_idx = find(abs(dI) > 0.5); % 电流变化大于0.5A
% 2. 计算R0
dV = V(jump_idx(1)+1) - V(jump_idx(1));
dI_val = I(jump_idx(1)+1) - I(jump_idx(1));
R0 = abs(dV / dI_val);
% 3. 静置段指数拟合
rest_start = jump_idx(2) + 1; % 放电结束后的静置起点
rest_end = jump_idx(3) - 1; % 充电开始前
t_rest = t(rest_start:rest_end) - t(rest_start);
V_rest = V(rest_start:rest_end);
% 拟合 V = a + b*exp(-t/tau)
f = fit(t_rest, V_rest, 'exp1');
tau = -1/f.b;
Rp = tau / Cp; % Cp需要先估算,或者联合辨识
避坑指南: 我曾经在HPPC测试时,静置时间只设了20秒。结果极化还没恢复完,下一轮脉冲就开始了,拟合出来的参数偏差很大。后来我改成静置至少1分钟,数据才稳定。记住,静置时间要大于3倍的时间常数τ。
参数辨识完成后,记得做交叉验证。用一组数据辨识,另一组数据验证。如果模型输出和实测电压误差在±20mV以内,就算合格。我一般要求±10mV。
好了,这一节的内容就到这。模型搭好了,参数也辨出来了,下一步就是把它生成嵌入式代码,跑在真正的BMS板子上。不过那是后面章节的事了。
公众号:蓝海资料掘金营,微信deep3321