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

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

* * *

## 目录

1.  [理论基础](#%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80)
    
2.  [电池等效电路模型](#%E7%94%B5%E6%B1%A0%E7%AD%89%E6%95%88%E7%94%B5%E8%B7%AF%E6%A8%A1%E5%9E%8B)
    
3.  [EKF算法实现](#ekf%E7%AE%97%E6%B3%95%E5%AE%9E%E7%8E%B0)
    
4.  [AEKF算法实现](#aekf%E7%AE%97%E6%B3%95%E5%AE%9E%E7%8E%B0)
    
5.  [系统集成方案](#%E7%B3%BB%E7%BB%9F%E9%9B%86%E6%88%90%E6%96%B9%E6%A1%88)
    
6.  [代码实现](#%E4%BB%A3%E7%A0%81%E5%AE%9E%E7%8E%B0)
    
7.  [参数调优](#%E5%8F%82%E6%95%B0%E8%B0%83%E4%BC%98)
    
8.  [测试验证](#%E6%B5%8B%E8%AF%95%E9%AA%8C%E8%AF%81)
    

* * *

## 理论基础

### 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（0~1 或 0~1000）、温度（可先只做 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℃
    
*   **SOC**：`GetGRealSocMilliAPI()` 或 `GetGBattSocAPI()`，单位 0.1%
    

建议在 EKF 内部统一使用 SI 单位（V/A/s），并将 SOC 使用 0~1 浮点或 0~1000 整型（千分比）统一。

### 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 2` 与 `case 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.c` 的 `case 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 的模块（如限流）要在典型工况下回归
