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画出来方便你理解:

一阶RC等效电路模型 Simulink 结构图 电流 I SOC OCV 查表 1-D Lookup R0 * I RC 网络 + 端电压 Vt 欧姆压降 极化电压 Vp OCV

模型搭好后,记得在Simulink里设置离散求解器,步长固定。我一般设0.1s,和BMS主循环周期一致。

注意: 千万别用连续求解器!代码生成后,MCU是离散运行的,连续模型生成的代码会有定时器问题,跑起来误差很大。

3.4 参数辨识

模型搭好了,参数从哪来?不能拍脑袋吧。参数辨识,说白了就是通过实验数据反推模型参数。

我常用的方法是混合脉冲功率特性测试(HPPC)。流程是这样的:

  1. 把电池充到满电,静置1小时
  2. 以1C电流放电10秒,静置40秒
  3. 以0.75C电流充电10秒,静置40秒
  4. 放电5% SOC,重复步骤2~3
  5. 一直做到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