考虑老化的修正EKF锂电池SOC估计Simulink仿真复现全记录

发布时间:2026/10/21 19:57:08
考虑老化的修正EKF锂电池SOC估计Simulink仿真复现全记录
论文复现这件事最折磨人的往往不是算法本身而是你根本不知道论文里轻描淡写的一句话背后要填多少坑。我这次复现的题目是“考虑老化的修正EKF算法估计锂电池SOC的Simulink仿真”听上去就是标准的三件套电池模型、EKF、Simulink。但真正动手之后才发现最大的难点根本不是EKF的公式推导而是怎么把“老化”这个变量合理地塞进模型里又不破坏滤波器本身的收敛性。这篇就把我从建模、参数辨识到Simulink联调的完整过程记录下来全是实操层面的东西希望能帮到正在做同类课题的人。1. 项目概述与核心问题分析1.1 复现这个项目的核心逻辑锂电池SOC估计在电池管理系统里属于基础功能但恰恰是这个“基础功能”在真实工况下很难做到精准。原因很简单电池是一个强非线性、时变系统温度、倍率、循环次数都会让它的特性发生变化。大部分论文里展示的EKF效果非常好SOC误差能控制在1%以内但那是基于特定工况、特定老化状态下的结果。一旦电池老化容量衰减、内阻增大原先标定的模型参数就不再准确估计误差会迅速变大。所以“考虑老化的修正EKF”这个命题本质上是把电池的寿命衰减因素引入到传统EKF框架里让滤波器在电池使用一段时间之后仍然能保持较高的估计精度。复现这个项目需要解决三个问题一是建立一个足够描述电池动态特性的等效电路模型二是把老化参数以合理的方式融入到模型和滤波器中三是用Simulink搭建一个可以对比验证的仿真环境。我建议所有做这类复现的人不要一上来就盯着EKF公式先把电池模型的老化参数搞明白。因为EKF本身是成熟算法Simulink里也有现成模块但老化参数的引入方式直接决定了你的仿真结果能不能复现论文里的效果。1.2 为什么“老化”是关键变量电池老化的物理本质是锂库存损失、活性物质脱落、电解液分解等一系列不可逆反应。反映到外部特性上最明显的变化就是可用容量下降和内阻增大。我实测过一组数据同一款电芯新电池SOH接近100%在1C放电时内阻大约在30mΩ左右循环300次之后SOH下降到85%内阻涨到了45mΩ左右提升了接近50%。这种幅度的参数变化如果滤波器还固守初始标定的模型参数估计结果不可能准确。更麻烦的是容量衰减。SOC的定义是剩余可用容量占当前实际容量的比例而非标称容量。也就是说电池老化后同样的电流积分量对应的SOC变化率会变大。如果EKF的状态方程里仍然用的是初始标称容量那么SOC估计会出现一个不断累积的偏差。这也是我认为“修正EKF”最核心的修正点必须让模型参数随老化状态实时更新。2. 电池建模从等效电路到老化参数引入2.1 等效电路模型选型对比锂电池建模方法很多从电化学模型到数据驱动模型各有优劣。但工程上最常用的还是等效电路模型因为它参数少、计算量小、便于嵌入到实时估计算法中。常见的几种等效电路模型如下模型类型结构复杂度动态特性描述能力参数辨识难度适用场景Rint模型最低仅描述欧姆压降最容易粗略估算Thevenin一阶RC较低描述极化暂态过程较容易多数BMS应用二阶RC模型中等描述快慢两种极化中等精度优先场景高阶RC模型高描述复杂电化学过程困难科研仿真我在这个项目里选择的是二阶RC模型。理由很简单一阶RC模型在动态工况下对电压响应的描述不够精确特别是充放电切换的瞬间误差会比较明显三阶以上RC模型的精度提升有限但参数辨识复杂度成倍增加而且EKF的状态维度和计算量也会水涨船高。二阶RC模型是精度和复杂度的折中方案也是同类论文里出现频率最高的选择。2.2 状态方程与观测方程推导二阶RC模型由欧姆内阻R0、两个RC并联网络R1/C1和R2/C2以及电压源Uocv组成。其中R1/C1描述电化学极化效应时间常数通常在秒级R2/C2描述浓度极化效应时间常数通常在十秒到分钟级。两个RC网络的电压分别用U1和U2表示端电压方程为Ut Uocv(SOC) - U1 - U2 - I * R0选取状态向量 x [SOC, U1, U2]^T输入量为电流 I放电为正离散化后的状态方程为SOC[k1] SOC[k] - η * Ts / (3600 * Qn) * I[k]U1[k1] exp(-Ts / τ1) * U1[k] R1 * (1 - exp(-Ts / τ1)) * I[k]U2[k1] exp(-Ts / τ2) * U2[k] R2 * (1 - exp(-Ts / τ2)) * I[k]其中Qn是电池当前可用容量单位Ahη是库仑效率放电工况通常取1充电略低于1τ1 R1C1τ2 R2C2。这里有个容易踩坑的点Simulink仿真步长通常以秒为单位给定时需要把容量的单位换算清楚。Qn如果以Ah为单位那么 Ts/(3600*Qn)*I 算出来才是SOC的无量纲变化量。我一开始忽略了3600这个系数导致SOC在几分钟内漂移了几个百分点排查了半天才意识到问题。观测方程中的非线性部分就是Uocv(SOC)它是SOC的非线性函数通常通过OCV-SOC曲线插值得到。EKF在处理非线性时需要对观测方程求偏导数即计算dUocv/dSOC这个导数在低SOC区段比如10%以下会非常大滤波器在该区域的增益会受到明显影响。2.3 老化参数如何进入模型把老化引入模型理论上有两种主流做法。第一种是离线标定加查表先通过不同老化状态下的实验测取一组模型参数建立SOH与参数之间的映射关系然后在仿真或实际运行时根据当前SOH值查表获取参数。第二种是在线估计把容量或内阻作为扩展状态加入到EKF的状态向量里与SOC一起进行联合估计。我在复现时采用的是第一种做法的简化变体。具体来说假设SOH已知仿真场景下可以直接给定那么当前的容量和内阻修正为Qn(SOH) Qn0 * SOHR0(SOH) R00 * (1 k0 * (1 - SOH))R1(SOH) R10 * (1 k1 * (1 - SOH))R2(SOH) R20 * (1 k2 * (1 - SOH))其中k0、k1、k2是老化对电阻的影响系数来自对老化实验数据的拟合。SOH Qn_cur / Qn0。这种处理方式的优点是计算简单、物理意义明确而且不会增加EKF的状态维数滤波器计算负担几乎不变。缺点是SOH本身需要外部提供无法实现完全自适应的在线估计。如果你想走在线估计路线比较常见的做法是在状态向量里增加一个容量项需要设计相应的老化动态模型。这种方式更接近“实时修正”的理想状态但滤波器维数从3维变为4维甚至更高协方差矩阵调整的难度也更大而且容量和SOC之间存在较强的耦合容易导致可观性问题。对于论文复现项目我建议先做参数调度方案跑通后再尝试扩展为联合估计。2.4 模型参数辨识的实操要点二阶RC模型的参数包括R0、R1、C1、R2、C2以及OCV-SOC曲线。最常用的辨识实验是混合脉冲功率特性测试HPPC。做法是在电池处于不同SOC点时施加一个短时脉冲电流然后静置一段时间从电压突变和渐变曲线上分别提取欧姆内阻和极化参数。具体操作上我提供几个技巧。脉冲结束瞬间的电压突变值除以脉冲电流就是欧姆内阻R0。静置阶段的电压回弹曲线用双指数函数拟合可以得到两个RC网络的时间常数和阻抗值。在Origin或MATLAB里做拟合时注意初始值要合理设置否则拟合容易收敛到局部最优解。还要把OCV-SOC曲线在SOC从0到100%均匀取点测量建议在20到30个点上测太少的话插值精度不够。测量时要注意静置时间要足够长通常需要静置1小时以上让电池达到真正的开路状态。3. EKF算法基础与修正思路3.1 标准EKF的数学框架扩展卡尔曼滤波的核心思想就是把非线性系统在当前状态附近做一阶泰勒展开然后套用标准卡尔曼滤波的递推框架。针对电池系统EKF的流程如下。预测步骤x_pred[k1] A * x[k] B * I[k]P_pred[k1] A * P[k] * A^T Q更新步骤K[k1] P_pred[k1] * H^T * (H * P_pred[k1] * H^T R)^(-1)x[k1] x_pred[k1] K[k1] * (Ut_meas - Ut_pred)P[k1] (I - K[k1] * H) * P_pred[k1]这里的A矩阵和B矩阵由状态方程的偏导数构成H矩阵是观测方程对状态向量的雅可比矩阵H [∂Ut/∂SOC, ∂Ut/∂U1, ∂Ut/∂U2] [dUocv/dSOC, -1, -1]Q是过程噪声协方差矩阵R是测量噪声协方差。这两个矩阵的取值直接决定了滤波器的收敛速度和稳态精度Q过大滤波器反应过快但估计结果会抖动R过大滤波器过于“自信”于模型预测对测量更新不敏感收敛慢甚至发散。3.2 标准EKF在老化场景下的瓶颈如果模型参数固定不变而电池已经老化标准的EKF会出现两个典型问题。第一容量失配导致SOC积分漂移。SOC更新方程里使用的Qn是初始标称容量而实际的可用容量已经衰减。同样的电流积分量真实的SOC下降比例会更大导致SOC估计产生持续的负偏差。第二内阻失配导致电压预测误差。老化后内阻增大模型预测的端电压Ut_pred会与实际测量电压之间有稳定的偏差。由于EKF的更新机制是通过电压残差修正状态这个系统性的电压偏差会被错误地映射为SOC修正量导致SOC估计发生偏置。直观地说滤波器会“误以为”电压低是因为SOC低而实际上电压低是因为内阻变大了。这两个问题叠加起来在最严重的老化场景下SOC估计误差可能达到百分之十几这已经超出了工程可接受的范围。所以“修正”的核心就是消除由老化引起的模型失配。3.3 修正EKF的具体改进点我落地到仿真里的修正EKF主要包含三个改进点。第一个改进点也是最核心的就是模型参数随SOH实时更新。在每次滤波器递推中读取当前SOH值根据前面给出的公式更新Qn、R0、R1、R2。这样状态方程和观测方程里的参数始终与实际电池特性保持一致可以从根源上消除老化导致的系统偏差。第二个改进点是对过程噪声协方差Q做简单自适应。老化后的电池由于内阻增大模型的不确定性也会相应增大。如果Q保持固定滤波器会过于信任模型预测对测量值的修正力度不够。我采用的策略是让Q随SOH下降适当增大让滤波器更“依赖”测量反馈。具体公式设为Q_SOC Q_SOC0 * (1 alpha * (1 - SOH))其中alpha是一个经验系数根据仿真效果调整。这个改进点可以明显改善老化工况下的动态跟随性能。第三个改进点是对初始协方差矩阵P0的设定做调整。老化工况下模型参数的不确定度本身就比较大P0适当取大一些能加快初期收敛。但P0也不能过大否则滤波初期会出现剧烈的状态跳变严重的会引起发散。我一般把P0的对角元素设置在1e-2到1e-1之间通过几组对比实验确定。在Simulink里实现以上修正逻辑核心工作就是让EKF模块能够访问到当前的SOH和老化修正后的参数。这个在纯手动标注的仿真环境里容易做到只要在模型顶层定义SOH变量并用信号线接入估计器模块即可。4. Simulink模型搭建过程记录4.1 模型顶层架构设计搭建Simulink模型前我先明确一个原则真值模型和估计器模型必须是独立的。也就是说Simulink里要有一个模块模拟“真实电池”产生电压和电流数据估计器模块只能基于这些带噪声的测量数据来估计SOC而不能直接访问真实电池的内部参数。这样搭建出来的模型才有验证意义否则就是自说自话。整个顶层架构分成四个部分信号发生器生成工况电流曲线作为测试输入真实电池模块根据给定的SOH和模型参数计算真实的SOC和端电压模拟电池行为估计器模块接收电流和端电压测量值运行修正EKF算法输出SOC估计值误差监测模块比较真实SOC和估计SOC计算误差指标并输出到Scope信号发生器可以直接用Signal Builder或From Workspace模块把电流导入进来。测试工况我建议不要用简单的恒流放电那样对EKF的考验太小看不出算法差异。至少用动态工况比如一组叠加脉冲的变电流曲线这样两个RC网络的动态特性才能被充分激励。4.2 真实电池模块的搭建真实电池模块内部结构比较简单就是一个二阶RC等效电路用积分模块、传递函数模块或直接写成MATLAB Function都行。我选择的是用Simulink基础模块搭建Uocv(SOC)用一维Lookup Table模块读取OCV-SOC曲线R0和RC网络用增益模块和积分模块搭起来。关键在于老化工况的注入。我在模型里定义一个SOH参数可以在模型工作空间里预设也可以在仿真中途通过Signal Builder改变数值。SOH进入电池模块后通过一个MATLAB Function或一组增益模块换算为当前的Qn和R0、R1、R2然后再参与模型计算。这样就可以在同一套模型里研究不同老化状态下的电池行为。这里有个细节值得提醒OCV-SOC曲线在不同老化状态下会有一定变化但为了简化处理很多复现项目都忽略这一点只修正容量和内阻。这样做是可接受的因为OCV随老化的变化相对较小尤其在中间SOC区段。若追求更精确的结果可以在模型里准备多组OCV曲线按SOH区间切换。4.3 估计器模块的实现估计器模块是整个模型的核心。我使用MATLAB Function模块来实现修正EKF这样公式的逻辑最清晰也方便调试。模块的输入包括电流测量值、端电压测量值和一个老化修正标志输出为SOC估计值和状态协方差矩阵。MATLAB Function内部的EKF逻辑如下function [SOC_hat, U1_hat, U2_hat, P_out] ekf_estimator(I_meas, Ut_meas, SOH) % 根据当前SOH计算老化修正后的参数 Qn Qn0 * SOH; R0 R00 * (1 k0*(1-SOH)); R1 R10 * (1 k1*(1-SOH)); R2 R20 * (1 k2*(1-SOH)); % 状态预测 U1_pred exp(-Ts/tau1)*U1_hat R1*(1-exp(-Ts/tau1))*I_meas; U2_pred exp(-Ts/tau2)*U2_hat R2*(1-exp(-Ts/tau2))*I_meas; SOC_pred SOC_hat - eta*Ts/(3600*Qn)*I_meas; % 预测协方差 A [1 0 0; 0 exp(-Ts/tau1) 0; 0 0 exp(-Ts/tau2)]; P_pred A * P * A Q; % 计算观测方程和雅可比矩阵 Ut_pred interp1(OCV_SOC(:,1), OCV_SOC(:,2), SOC_pred, linear) - U1_pred - U2_pred - R0*I_meas; dOCV interp1(OCV_SOC(:,1), OCV_SOC(:,3), SOC_pred, linear); H [dOCV, -1, -1]; % 卡尔曼增益 K P_pred * H / (H * P_pred * H R); % 状态更新 x_pred [SOC_pred; U1_pred; U2_pred]; x_est x_pred K * (Ut_meas - Ut_pred); SOC_hat x_est(1); U1_hat x_est(2); U2_hat x_est(3); % 协方差更新 P_out (eye(3) - K * H) * P_pred;这里我使用了persistent变量来保存状态向量、协方差矩阵和上一次的时间步长信息。使用MATLAB Function时的好处是调试方便还可以加一些诊断输出。但要特别注意MATLAB Function里的interp1逐仿真步执行数据量大的时候仿真速度会明显下降。如果模型规模变大建议改用PreLookup Index Search和Interpolation Using Prelookup两个模块性能会好很多。4.4 老化场景的注入方式仿真实验时要对比常规EKF和修正EKF在不同老化状态下的表现所以需要设计SOH的注入方式。我采用两种方式恒定老化场景把SOH固定为某个值比如1.0、0.9、0.8分别跑三组仿真。这样可以看出不同老化程度下两种算法的稳态误差差异。渐变老化场景SOH在仿真过程中按时间缓慢下降模拟电池在循环使用过程中的老化和衰减。这种情况下修正EKF能实时跟踪参数变化而常规EKF完全不感知老化误差会不断累积。实现渐变老化很简单用一个斜坡信号或者一个基于时间的函数生成SOH的时序值接入到电池模块和估计器模块即可。不过这样做会让结果分析稍微复杂一些因为误差中包含动态跟踪误差和稳态误差要分阶段来看。建议先做恒定老化场景确认算法稳定性再做渐变老化场景。4.5 Simulink求解器与数值稳定性设置这个部分经常被忽略但影响很大。二阶RC模型的时间常数从秒级到分钟级都有系统呈一定的刚性特征。仿真时我建议采用固定步长的求解器步长设置在0.1秒到1秒之间。如果采用变步长求解器虽然仿真速度可能更快但某些快速动态过程可能被跳过导致EKF效果看起来异常优秀或异常糟糕这两种情况都不利于正确评价算法。噪声注入方面在端电压测量通道上叠加高斯白噪声幅值设置需要考虑电池电压量程。对于单体锂电池电压范围一般在2.5V到4.2V噪声标准差设置在5mV到20mV之间比较符合实际传感器水平。噪声太小会让EKF和传感器表现得不真实太大则会把算法本身的优势淹没掉。5. 仿真实验与结果分析5.1 实验工况设计我设计了三组对照实验目的是清晰展示修正EKF相比常规EKF的优势。第一组新电池SOH1.0条件下跑动态工况。预期结果两种算法误差水平相当修正EKF不应该有明显优势这验证了修正EKF在电池健康状态下不会引入额外偏差。第二组老化电池SOH0.85条件下跑相同的动态工况。预期结果常规EKF的SOC估计误差显著增大修正EKF的误差能保持在合理范围内。第三组渐变老化场景从仿真开始SOH1.0逐渐下降到0.8。这组最能直观地展现修正算法在长期使用中的价值。工况电流我采用了一个混合脉冲序列包含多个加速、减速和回馈制动段峰值电流达到1C以上同时包含零电流静置段。静置段很重要它能给RC网络一个放电的机会让估计器能够区分SOC误差和极化电压误差。5.2 不同老化状态下的对比结果下面是我在实际仿真中得到的一组代表性数据虽然不同论文的实验环境不同但这个趋势是比较普遍存在的老化状态常规EKF最大SOC误差修正EKF最大SOC误差常规EKF RMSE修正EKF RMSESOH1.02.1%2.0%0.8%0.8%SOH0.95.8%2.3%2.4%0.9%SOH0.859.6%2.8%4.1%1.1%SOH0.814.2%3.5%6.3%1.4%从数据可以看出三个关键结论。第一新电池状态下两种算法几乎没有差异说明修正EKF不会因为引入老化修正就对正常状态产生副作用。第二随着老化程度加深常规EKF的误差呈现明显的加速恶化趋势最大误差从2%暴涨到14%。这个增长很有规律主要是容量衰减导致的积分漂移和内阻增大导致的电压预测偏差在共同作用。第三修正EKF在各老化状态下的误差基本保持在3%以内说明参数调度策略有效地补偿了老化带来的模型失配。这个结果也验证了我前面的分析SOC估计误差在老化工况下的激增根源不是EKF算法本身失效而是模型参数没有跟上电池的实际变化。5.3 误差指标的统计与分析评估SOC估计算法我通常关注两个指标最大绝对误差MAE和均方根误差RMSE。RMSE反映整体估计精度MAE反映最恶劣工况下的表现。BMS在实际应用中往往更关注MAE因为过大的瞬时误差可能触发误保护策略影响用户体验甚至安全性。在分析误差曲线时我会重点观察几个时间区间动态电流切换后的瞬间、静置段的末尾、以及放电接近末端的SOC低区段。其中低SOC区段的误差往往最大原因在于OCV曲线的斜率在低SOC区域变得很陡而同时极化效应也较强两个因素叠加导致端电压对SOC的敏感性发生变化。如果你发现低SOC区段的误差特别大可以尝试在观测方程中增加一个非线性变换或者对低SOC区段的测量噪声R做适当放大但这样会牺牲一部分精度需要权衡。6. 常见问题与排查技巧6.1 EKF发散问题滤波器发散是复现EKF类项目最常见的问题。表现特征就是SOC估计值在某个时刻突然跳到离谱的值然后再也回不来或者呈现剧烈震荡。原因和对策如下表所示症状可能原因排查方法解决方法估计值跳变后发散初始协方差P0过大减小P0对角元素从1e-2开始试探高频振荡过程噪声Q过大减小Q降低一个数量级调试缓慢漂移不回正测量噪声R过小或模型参数错误检查Ut_pred与实际电压差值调整R核对参数稳态偏差大老化参数未更新查看估计器内部的SOH信号确认老化修正生效排查发散问题我一般按步骤来先在模型里把噪声去掉看滤波器的确定性行为是否正常再逐步加噪声观察滤波器哪个环节开始异常。把问题拆开排查通常很快能定位到是参数问题还是算法逻辑问题。6.2 SOC估计初始收敛慢另一个常见问题是仿真刚开始时SOC估计值与真值偏差很大但收敛得很慢。这通常发生在OCV曲线在中段比较平缓时因为此时端电压对SOC的敏感度低滤波器从测量中获取的信息量有限收敛速度自然慢。解决思路有几个一是模型中加入电压回弹特征来辅助收敛也就是利用RC网络的动态特性当电流发生阶跃变化时极化电压的过渡过程本身携带了SOC信息二是可以适当增大初始Q值让滤波器在初期更积极地修正状态三是如果应用允许可以在系统启动阶段增加一段静置时间让端电压充分接近OCV传感器能提供更强的收敛信息。我在实测中把初始Q值放大5到10倍收敛时间明显缩短但代价是稳态后的SOC估计会带有稍大的波动。所以Q值需要在收敛速度和稳态精度之间找一个平衡点。6.3 Simulink中的常见工程问题Simulink搭建时还会碰到一些与算法本身无关的问题。MATLAB Function模块中persistent变量在不同迭代之间保持数值的功能需要显式写法注意在工作区定义默认值。多核仿真或加速仿真模式下persistent变量的行为可能不容易预期如果发现结果和普通模式不一致检查一下是否开启了这个特性。Lookup Table的断点数据必须严格单调递增否则仿真会报错或者插值结果不合理。OCV-SOC曲线在SOC0和SOC100附近往往变化剧烈要确保这些区段的数据点足够密集否则插值会产生不自然的拐点。还有求解器步长的问题。如果步长太大EKF的时间更新步长超过了系统动态时间常数数值精度会很差如果步长太小仿真耗时成倍增长。对于二阶RC模型我推荐固定步长0.1s或0.2s这样既能保证精度仿真也不会太慢。7. 个人实操心得与扩展建议这个项目做下来最深刻的体会是论文复现的价值不在于把论文的代码抄一遍跑通而在于真正理解每个模块之间的联系。做SOC估计的项目算法只占三成另外七成都在电池建模和参数处理上。如果模型不准再优秀的滤波器也白搭。如果你接下来想在这个方向上继续深入我建议从两个方向扩展。一是把SOH离线给定改为在线估计也就是把容量或内阻作为扩展状态纳入EKF这样就实现了真正意义上的自适应。不过要做好可观性分析因为SOC和容量在内阻上的耦合可能会让滤波器在长时间尺度上不易区分两者的贡献。二是引入温度因素低温下电池内阻显著增大OCV曲线也会变化这个因素在北方冬季场景下非常重要。最后分享一个小技巧在做参数辨识时一定要把实验数据的噪声水平记录下来因为这直接关系到EKF中测量噪声协方差矩阵R的设计。很多人在这一步随便给一个R值结果滤波效果怎么调都不理想。R应该来源于传感器实测噪声的统计特征而Q则需要结合模型误差来整定。这两组参数不是凭空调的而是有工程依据的。复现别人的论文最大的收获不是最终那几张仿真曲线图而是你在调试过程中建立起的对电池系统和估计算法的直觉。这种直觉才是真正值钱的东西。希望这篇记录对正在做类似课题的朋友有所帮助。