Skip to main content

Command Palette

Search for a command to run...

扩展卡尔曼滤波(EKF)与自适应扩展卡尔曼滤波(AEKF)SOC 估算实现文档(基于本工程)

Updated
5 min readView as Markdown

本文档面向工程 S32K146OFBMU_B/,给出可直接落地到现有调度与接口的 EKF/AEKF SOC 估算实现方案。
工程当前 SOC 以“安时积分 + 修正 + 平滑显示”为主,且在 SocSoeLibAllTask() 中预留了“SOC/SOE 扩展卡尔曼”分支但未实现(空语句)。本方案将 EKF/AEKF 作为“估算器”,对安时积分 SOC 做在线校正,并与现有 CorrGNowCapBySocAPI() 等接口兼容。


目录

  1. 理论基础

  2. 电池等效电路模型

  3. EKF算法实现

  4. AEKF算法实现

  5. 系统集成方案

  6. 代码实现

  7. 参数调优

  8. 测试验证


理论基础

1) 为什么需要 EKF/AEKF

本工程当前 SOC 主体为安时积分(Coulomb Counting),在动态工况下会受到以下误差累积影响:

  • 电流零漂/比例误差:积分误差随时间累积。

  • 容量、效率、温度的非线性:电池有效容量、充电效率随温度/倍率变化。

  • 端电压与 SOC 的非线性关系:静置或小电流工况下,端电压更能约束 SOC;大电流时必须考虑内阻与极化。

EKF 用“电池模型 + 电压观测”持续校正 SOC;AEKF 在 EKF 基础上进一步在线自适应噪声协方差((Q/R)),提升跨工况鲁棒性。

2) EKF/AEKF 在本工程里的角色

建议采用“安时积分作为预测,EKF/AEKF 作为校正”:

  • 预测(Prediction):根据采样电流积分更新 SOC(工程已有成熟实现)。

  • 校正(Update):用端电压(或平均单体电压)与模型生成的估计电压比较(创新量),对 SOC 做修正。

  • 对外输出:仍走工程现有 SOC 输出链路(显示平滑、组间同步、修正策略等),EKF/AEKF 只给出“建议 SOC/容量修正量”。


电池等效电路模型

本工程未看到现成的 OCV-SOC 查表和 RC 模型参数表,因此 EKF/AEKF 必须补齐两类基础能力:

  1. OCV(SOC, T):开路电压与 SOC/温度的映射(查表 + 插值)。

  2. ECM 参数(R0、R1、C1…):至少一阶 Thevenin(1RC)即可支撑工程级 EKF。

1) 推荐模型:一阶 Thevenin(1RC)

状态选取(最小可用形态):

[ \mathbf{x}= \begin{bmatrix} z \ v_p \end{bmatrix} ]

  • (z):SOC(0~1)

  • (v_p):极化电压(V)

输入:

  • (i):电流(A),本工程约定:负号为充电(见 GetGSampOutCurrAPI() 注释)。

观测:

  • (v):端电压(V),可选用电池组采样总电压或单体平均电压映射后的等效值。

连续模型:

[ \dot{z} = -\frac{\eta(i,T)}{Q_n(T,SOH)} i ] [ \dot{v}_p = -\frac{1}{R_1 C_1} v_p + \frac{1}{C_1} i ] [ v = OCV(z,T) - iR_0 - v_p ]

其中:

  • (R_0):欧姆内阻

  • (R_1,C_1):极化支路参数

  • (\eta):库伦效率(可先简化为 1,后续在调参中加入充电效率)

  • (Q_n):当前可用容量(可取工程 GetGroupTotalCapAPI() 或其温度/衰减修正版本)

2) 离散化(适配本工程周期)

本工程 SOC/SOE 总任务 SocSoeLibAllTask() 在 50ms 触发,内部有 500ms 分支可放 EKF/AEKF。
若 EKF 运行周期为 (\Delta t = 0.5s),则:

[ z_{k+1} = z_k - \frac{\eta}{Q_n} i_k \Delta t ] [ v_{p,k+1} = a v_{p,k} + b i_k ]

其中:

[ a=e^{-\Delta t/(R_1 C_1)},\quad b=R_1(1-a) ]

观测方程:

[ v_k = OCV(z_k,T_k) - i_kR_0 - v_{p,k} ]

3) OCV-SOC 查表与插值

建议使用分段线性插值:

  • 输入:SOC(01 或 01000)、温度(可先只做 25℃一条曲线,后扩展多温度面)

  • 输出:OCV(V,或 mV)

  • 导数:EKF 需要 (\frac{dOCV}{dz})(可由相邻点斜率近似)


EKF算法实现

1) EKF 结构(2 状态 1 观测)

预测:

[ \hat{x}{k|k-1} = f(\hat{x}{k-1|k-1}, u_k) ] [ P_{k|k-1} = F_k P_{k-1|k-1} F_k^T + Q ]

更新:

[ y_k = v_k - h(\hat{x}{k|k-1},u_k) ] [ S_k = H_k P{k|k-1} H_k^T + R ] [ K_k = P_{k|k-1} H_k^T S_k^{-1} ] [ \hat{x}{k|k}=\hat{x}{k|k-1}+K_k y_k ] [ P_{k|k}=(I-K_k H_k)P_{k|k-1} ]

2) 雅可比矩阵(离散模型)

对 (x=[z, v_p]^T):

  • 状态转移雅可比(线性近似):

[ F_k= \begin{bmatrix} 1 & 0 \ 0 & a \end{bmatrix} ]

  • 观测雅可比:

[ H_k= \begin{bmatrix} \frac{dOCV}{dz} & -1 \end{bmatrix} ]

3) 输入/观测量的工程单位换算

本工程可直接用以下接口(注意单位与符号):

  • 电压

    • GetGSampSumVoltAPI():电池组采样总电压,单位 0.1V

    • GetGCellAvgVoltAPI():单体平均电压,单位 1mV

  • 电流GetGSampOutCurrAPI(),单位 0.1A,负号为充电

  • 温度GetGCellAvgTempAPI(),单位 1℃

  • SOCGetGRealSocMilliAPI()GetGBattSocAPI(),单位 0.1%

建议在 EKF 内部统一使用 SI 单位(V/A/s),并将 SOC 使用 01 浮点或 01000 整型(千分比)统一。

4) EKF 输出如何回灌到工程 SOC

工程提供 “按 SOC 修正容量”接口:

  • CorrGNowCapBySocAPI(u16 soc):按目标 SOC(0.1%)修正当前容量

建议策略:

  • EKF 更新后的 (z) 转换为 soc_milli = z * 1000(0.1%)

  • 设置“允许修正阈值”(例如 0.5% 以上才修正),避免抖动

  • 电池信息就绪非严重保护时才允许修正(例如参考 EnerGetGroupBattReadyHook() 与保护状态 Hook)


AEKF算法实现

AEKF 的关键是让 (Q/R) 随工况变化而自适应,工程上常用两类做法(推荐从简单稳定的开始):

1) 基于创新量的 R 自适应(推荐起步)

创新量 (y_k) 反映“电压预测误差”。当电压噪声或模型失配变大时,增大 (R) 可以降低对电压的信任,避免 SOC 被错误拉动。

一种工程可用形式:

[ R_k = clamp(R_{min},\ \lambda R_{k-1} + (1-\lambda) y_k^2,\ R_{max}) ]

  • (\lambda):遗忘因子(例如 0.95~0.995)

  • clamp:限定上下界防止数值发散

2) Q 自适应(适合模型不确定较大场景)

当倍率变化导致极化参数变化明显时,增大过程噪声 (Q)(尤其是 (v_p) 的过程噪声)能提高对变化的跟踪能力。

可用简单规则:

  • 当 (|i|) 大于某阈值或变化率大时:增大 (Q_{v_p})

  • 静置/小电流时:减小 (Q_{v_p}),并可启用 OCV 强约束

3) 与工况模式联动(本工程强烈建议)

本工程已有充放电状态与工作状态接口(例如 GetGChgDhgStateAPI()GetGWorkStateAPI()),可用来切换 AEKF 参数集:

  • 静置(Idle):小电流,R 小、Q 小,强化 OCV 约束

  • 放电(Dhg):R 适中、Q 适中

  • 充电(Chg):考虑库伦效率 (\eta < 1),并适当增大 R(充电时电压波动更敏感)


系统集成方案

1) 现有调度与接入点(必须遵守本工程时序)

调度链路

  • Task50ms() 周期调用 SocSoeLibAllTask()(见 Sources/OSUser/OSUserHOOK.c

  • SocSoeLibAllTask() 内部 sTime 0~19 循环:

    • case 2/12:500ms 周期,注释为 “SOC、SOE 扩展卡尔曼算法任务”,目前为空(见 Sources/Funtion/SocLib/SocUserAPI.c

因此 EKF/AEKF 建议在 case 2case 12 中调用:

  • SocEkfTask_500ms()SocAekfTask_500ms()

2) 数据流(建议实现形态)

输入(来自现有系统信息层接口):

  • (v):GetGSampSumVoltAPI()GetGCellAvgVoltAPI()

  • (i):GetGSampOutCurrAPI()

  • (T):GetGCellAvgTempAPI()

  • 初始 (z):GetGRealSocMilliAPI()(或上电恢复 SOC)

  • 容量 (Q_n):GetGroupTotalCapAPI()(mAh)或工程已有修正后的容量接口(若存在)

输出(回灌到现有 SOC 体系):

  • CorrGNowCapBySocAPI(soc_ekf)(建议带阈值/限速)

  • 可选:将 EKF 估算的极化电压、创新量、R/Q 自适应值作为调试量记录(便于调参)

3) 与现有 SOC 修正/同步/显示的关系

本工程已有:

  • SocSoeAllCorrTask():温度修正、电压末端步进修正、多源融合修正

  • SocSoeTogetherSyncTask() / SocSoeGroupSyncTask():SOC/SOE 同步

  • SocDisplay.c:显示平滑

建议 EKF/AEKF 的输出定位为“更可靠的真实 SOC”,再由现有模块完成显示与同步。
也就是说:EKF 不直接改显示值,而是改“真实 SOC(容量)”,最终通过现有链路自然传递。


代码实现

1) 推荐新增文件组织(贴合现有工程结构)

Sources/Funtion/SocLib/ 新增:

  • SocEkf.h / SocEkf.c:EKF 核心(含模型、预测/更新)

  • SocAekf.h / SocAekf.c:AEKF 扩展(或在 SocEkf.c 内可配置开关)

  • BatteryModel.h / BatteryModel.c:OCV 查表、dOCV/dSOC、ECM 参数获取(可按温度/SOH/倍率分段)

Sources/Funtion/Parameter/Sources/Funtion/SocLib/ 增加参数入口(两种方式二选一):

  • 参数表方式:支持 EEPROM/Flash 参数化(适配不同电芯)

  • 常量表方式:先固化一条电芯曲线,便于快速跑通,再做参数化

2) 对接 SocSoeLibAllTask() 的改动点

Sources/Funtion/SocLib/SocUserAPI.ccase 2/12 中调用 EKF/AEKF 任务函数(500ms)。

3) 必须实现的最小接口(建议)

EKF/AEKF 模块对外提供:

  • void SocEkfInit(void);

  • void SocEkfTask500ms(void);

  • u16 SocEkfGetSocMilli(void);(可选)

BatteryModel 模块提供:

  • float OcvFromSoc(float soc_0_1, float temp_c);

  • float dOcvdSoc(float soc_0_1, float temp_c);

  • void EcmParamGet(float soc_0_1, float temp_c, float soh_0_1, float* r0, float* r1, float* c1);


参数调优

1) 先决条件(否则 EKF 很难收敛)

  • 电流标定:电流零漂/比例误差需可控(否则 EKF 会长期“追着错误跑”)

  • 电压标定:电压采样偏差会直接映射到 SOC 偏差

  • 容量基准Q_n 要与实际电池匹配(至少同量级),且随 SOH/温度变化要能被近似

2) ECM 参数(R0、R1、C1)初值建议

没有离线辨识数据时,可用“可收敛的保守初值”先跑通:

  • (R_0):用静置小电流阶跃下的 (\Delta V/\Delta I) 粗估

  • (R_1,C_1):让极化时间常数 (\tau=R_1C_1) 处在 5~60s 的合理范围(取决于电芯)

3) 噪声协方差 (Q/R) 调参要点

  • R(电压测量噪声)

    • R 小:SOC 更“相信电压”,收敛快但可能抖动

    • R 大:SOC 更“相信积分”,稳定但纠偏慢

  • Qz(SOC 过程噪声)

    • 通常很小(预测主要由积分决定),用于容纳积分模型误差
  • Qvp(极化状态噪声)

    • 决定对动态极化的跟踪能力,倍率变化大则应增大

AEKF 调参建议:

  • 先固定 Q,只做 R 自适应(创新量法),等稳定后再做 Q 的工况自适应。

4) 工况门限建议

  • 静置判定:(|i| < I_{idle}) 且持续 (t_{idle})(例如 (|i|<0.02C),持续 60s)

  • 更新使能

    • 电池未就绪时禁用(参考 EnerGetGroupBattReadyHook()

    • 高压/低压保护、严重故障时禁用(避免模型失效)


测试验证

1) 分阶段验证策略(推荐)

  • 阶段A:离线回放验证(推荐先做)

    • 采集(或录波)电压/电流/温度/原 SOC

    • 在 PC 端跑同一套 EKF/AEKF(或用同参数对比)

    • 对比:SOC 漂移、动态响应、静置收敛

  • 阶段B:台架动态工况

    • 恒流充放电、脉冲功率、UDDS 类工况

    • 对比真值:高精度库伦计/容量计

  • 阶段C:整机长期漂移

    • 温度变化、不同倍率、不同 SOH 条件下

    • 指标:SOC 偏差均值/方差、末端一致性、静置收敛速度

2) 关键观测指标(建议记录)

  • EKF:创新量 (y)、增益 (K)、估算电压 (\hat{v})

  • AEKF:(R_k)、(Q_k) 的在线变化

  • 估算状态:(z)、(v_p)

  • 触发条件:静置判定、更新使能/禁止原因

3) 回归与安全性

EKF/AEKF 上线后必须验证对现有功能无负面影响:

  • SOC 不应出现突跳(现有显示平滑可辅助,但源 SOC 仍需限幅/限速)

  • 保护阈值与限值计算依赖 SOC 的模块(如限流)要在典型工况下回归

More from this blog

BMS Fault Diagnosis: Reliable Fault Detection Using a Two-State State Machine and Filtering Delay

前言 电池管理系统(BMS)在储能、电动汽车、UPS等高压直流应用中承担着核心的安全守卫职责。一个错误的故障判断——无论是漏报还是误 报——都可能带来严重后果:漏报导致过充过放损毁电芯甚至起火,误报导致系统频繁保护停机、影响生产和用户体验。 如何在噪声环境下做到"不该报的不报,该报的必须报"?本文基于真实固件代码,深入剖析其故障诊断体系的设计思路与实现细节。 一、两态故障状态机:简单却不简陋 1

Jul 14, 20268 min read

Integrated PV-Storage-Load Forecasting: Empowering EMS with Predictive Intelligence

光伏-储能-负荷联合预测:给 EMS 装上"预知能力" 本文结合我正在维护的一套工业储能管理系统的真实工程实践,聊聊如何把预测能力嵌入 EMS 决策链路。代码片段均来自项目实际文件,不是伪代码。 一、为什么 EMS 需要预测? 我在调试这套系统的 MQTT 指令链路时,发现一个有意思的现象:EMS 的充放电决策完全依赖当前时刻的 SOC 和预设的时段计划表。翻开 ems_management

Jun 8, 20264 min read

电力需求响应——SEMS/REMS层级架构下的多站协调控制

作者:储能系统固件开发工程师日期:2026-04-14项目背景:工商业储能管理系统(BESS),支持川崎项目多站联合需求响应,SEMS为站级本地EMS,REMS为上级远程EMS 一、为什么需要两级EMS? 最初,项目只有一个站级EMS(站级能量管理系统,SEMS)。SEMS负责控制本站的PCS充放电,执行时段计划、防逆流、防过载,运行得还算平稳。 然而,当客户在川崎项目提出"多个储能站联合响应

Apr 14, 20267 min read

BMS

14 posts