概述 BatterySimerKit2.0 是一套 PC 端电量计仿真环境,用于 77561 系列燃料计芯片的 DFCC(Dynamic Fuel Gauge Compensation)离线调参和算法验证。
为什么需要仿真环境:
(1) 离线调参:无需反复烧录固件,直接在 PC 上修改 DFCC 表和参数,快速迭代 (2) 对比验证:将仿真输出(simer)与芯片实际输出(cobra)和循环仪期望值(cycle)三条曲线对比,量化误差 (3) 算法一致性:仿真环境使用与固件完全相同的 C 算法库,确保仿真结果可信
三层架构:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 ┌─────────────────────────────────────────────────────────┐ │ C# WinForms GUI (BatterySimer) │ │ - SharpGL 绘图引擎 │ │ - 参数/表格编辑对话框 │ │ - COBRA日志加载 & 循环仪数据加载 │ ├─────────────────────────────────────────────────────────┤ │ C DLL (SOCLib77561.dll) ← P/Invoke 调用 │ │ - 电量计核心算法 (lib_fg) │ │ - COBRA日志解析 (main.c) │ │ - 查找表: OCV, RC, DFCC, Temperature │ ├─────────────────────────────────────────────────────────┤ │ Python 工具 (auto_update_table.py) │ │ - OCV/RC 表自动同步 (TableMaker → table.c) │ └─────────────────────────────────────────────────────────┘
工程目录结构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 BatterySimerKit2.0/ ├── BatterySimer.sln # VS解决方案(含两个项目) ├── SOCLib77561/ # C DLL - 电量计算法库 │ ├── lib/ # 核心FG算法 │ │ ├── lib_fg.h # API定义、数据结构 │ │ ├── lib_fg.c # 算法实现 │ │ └── lib_pg.c # Pack级多电芯管理 │ ├── user/ # DLL接口层 │ │ ├── main.h # DLL导出函数声明 │ │ ├── main.c # COBRA解析、FG初始化、接口实现 │ │ └── parameter.c # 电池参数(按DATA_TYPE区分) │ ├── table/ # 查找表数据 │ │ ├── table.h # DATA_TYPE宏、维度定义 │ │ ├── table.c # OCV/RC/DFCC表数据 │ │ └── dfcc_debug.c # DFCC调试打印 │ ├── ckf/ # 卡尔曼滤波模块 │ └── vnn/ # 神经网络SOC估算模块 ├── BatterySimer/ # C# WinForms GUI │ ├── Form1.cs # 主界面、DllImport、仿真循环、绘图 │ ├── FormModifyOCV.cs # OCV表编辑 │ ├── FormModifyRC.cs # RC表编辑 │ └── FormModifyParameters.cs # 参数编辑 └── auto_update_table.py # Python表同步工具
仿真输入数据详解 COBRA CSV 日志格式 COBRA 工具通过 I2C/SBS 总线实时采集电量计芯片的寄存器数据,导出为 CSV 格式。日志包含 28 列:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 enum CobraHeader { Time_Enum = 0 , BatteryMode_Enum, BatteryVolt_Enum, CellMV01_Enum, CellMV02_Enum, CellVoltMV01_Enum, CellVoltMV02_Enum, BatteryCurr_Enum, AvgCurr_Enum, OrigCurr_Enum, ETHM_Enum, ITHM_Enum, RSOC_Enum, RC_Enum, RCA_Enum, CCMAH_Enum, RSOC1_Enum, RC1_Enum, CCmAhr_Enum, GGMEM0_Enum ~ GGMEM6_Enum, CycleCount_Enum, SOH_Enum, };
输入字段到 FG_PARAM_T 的映射 DLL 的 soc_process_77561() 函数逐行解析 COBRA CSV,提取以下字段送入算法库:
COBRA 列
FG_PARAM_T 字段
转换逻辑
CellMV01 / CellMV02
volt_hi_mv / volt_lo_mv
比较两个电芯电压,取高/低值
BatteryCurr
current_ma
atoi(record) / CURR_DIV,CURR_DIV 为并联电芯数
ETHM
cellthm
atof(record) * 10,转为 0.1°C 单位
CCmAh
delta_mah
差分计算 + slope 校正(见下文)
GGMEM2 byte[28-31]
imode
-1=放电, 0=空闲, 1=充电
GGMEM3 byte[0-3]
delta_ms
相邻采样点时间差(s) × 1000 → ms
delta_mah 计算(库仑计差分 + slope 校正) COBRA 日志的 CCmAh 列是芯片库仑计的累计值,仿真需要计算相邻两个采样点的差分,并用 slope 系数校正 ADC 非线性:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 int diff_cc_uah = (CCmAh_now - CCmAh_last) * 1000 ; if (diff_cc_uah > 0 ) diff_uah = diff_cc_uah * 10000 / chgslope; else if (diff_cc_uah < 0 ) diff_uah = diff_cc_uah * 10000 / dsgslope; diff_uah = diff_uah / CURR_DIV; delta_uah += diff_uah; gg_input.delta_mah = delta_uah / 1000 ; delta_uah = delta_uah % 1000 ;
其中 chgslope 和 dsgslope 默认值为 10000(即无校正),实际项目中根据芯片 CADC trim 值调整。
Cycle Tester _Detail.csv 输入 循环仪(如新威、蓝电)导出的 _Detail.csv 文件提供 ground truth 数据,关键列:
列
含义
CC(mAh)
循环仪库仑计累计值
I(mA)
实测电流
U(mV)
实测电压
mode
1=充电, -1=放电, 0=静置
time
时间戳
仿真输出与三条 SOC 曲线 FG_RESULT_T 输出结构 每次调用 fg_update() 后,算法库返回以下结果:
1 2 3 4 5 6 7 8 9 10 typedef struct { signed int rsoc; signed int fcc; signed int rc; unsigned int dsgcap; unsigned int chgcap; unsigned int status; signed int soh; unsigned int tte; } FG_RESULT_T;
三条 SOC 曲线 BatterySimer GUI 同时显示三条 SOC 曲线,用于对比分析:
1 2 3 4 5 6 7 d2f.yy[0] = cycle SOC (期望值/ground truth) d2f.yy[1] = cobra SOC (芯片实际输出) d2f.yy[2] = simer SOC (仿真输出) d2f.yy[3] = |cycle - cobra| (芯片误差) d2f.yy[4] = |cycle - simer| (仿真误差) d2f.yy[5] = |cobra - simer| (一致性误差) d2f.yy[6] = SOH
cycle(期望值 / ground truth) 来源:循环仪 _Detail.csv 的库仑计数据。
计算公式:
1 SOC = (cc_mah - cycle_min_cc) / (cycle_max_cc - cycle_min_cc) × 100
其中:
cycle_min_cc:该放电段起点的 CC 值
cycle_max_cc:电压降到 EOD(End of Discharge,如 3200mV)时的 CC 值
关键理解:cycle SOC 是基于实际放出容量的线性归一化,不是电压线性插值。 循环仪精确测量了电池从满电到 EOD 实际放出的总容量,以此为基准将每个时刻的已放容量映射到 0-100%。
cobra(芯片实际输出) 来源:COBRA 日志的 RSOC 列,直接读取芯片寄存器值。
这是芯片内部 FG 算法的实时输出,反映固件在真实硬件上的运行结果。
simer(仿真输出) 来源:DLL soc_process_77561() 返回的 rsoc 字段。
使用与固件相同的 C 算法库,输入相同的电压/电流/温度数据,在 PC 上重新计算 SOC。
调参目标
cyc-sim 误差(yy[4])全程 < 3%
误差曲线在 GUI 中 ×10 放大显示,便于观察细微偏差
SOCLib77561 DLL 层 DLL 导出接口 main.h 声明了所有 DLL 导出函数,供 C# GUI 通过 P/Invoke 调用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 __declspec(dllexport) char * soc_init_77561 (char * line) ; __declspec(dllexport) char * soc_process_77561 (char * line) ; __declspec(dllexport) char * get_ocv_table_77561 (int index) ; __declspec(dllexport) void set_ocv_table_77561 (int index, int x, int y) ; __declspec(dllexport) char * get_rc_table_77561 (int index1, int index2) ; __declspec(dllexport) void set_rc_table_77561 (int index1, int index2, int x) ; __declspec(dllexport) char * get_x_table_77561 (int index) ; __declspec(dllexport) char * get_y_table_77561 (int index) ; __declspec(dllexport) char * get_z_table_77561 (int index) ; __declspec(dllexport) char * get_temp_table_77561 (int index) ; __declspec(dllexport) void set_temp_table_77561 (int index, int x, int y) ; __declspec(dllexport) char * get_parameters_77561 () ; __declspec(dllexport) void set_parameters_77561 (char * line) ; __declspec(dllexport) char * get_dfcc_ratio_77561 () ; __declspec(dllexport) void set_dfcc_ratio_77561 (int v1, int v2, int v3, int v4, int v5, int v6, int v7) ; __declspec(dllexport) void set_cobratable_header_77561 (char * line, int logformat) ; __declspec(dllexport) char * get_init_fcc_77561 () ; __declspec(dllexport) void set_init_fcc_77561 (int value1, int value2) ;
FG 库初始化流程 1 2 3 4 5 6 7 8 9 soc_init_77561(first_line) │ ├── 解析 GGMEM0-6 → 恢复芯片内部状态 ├── fg_setup(ram, devlst, num) → 分配句柄 ├── fg_init(handle, cfg, lut, seo) → 绑定配置和查找表 │ ├── cfg: FG_CONFIG_T (dsncap, eocmv, eodmv, sysim...) │ ├── lut: FG_LUT_T (OCV表, RC表, DFCC表, 温度表) │ └── seo: FG_AUTO_SEO_T (自学习参数) └── soc_sync_status_77561() → 同步初始SOC状态
FG_PARAM_T 输入结构 1 2 3 4 5 6 7 8 9 10 typedef struct { signed int delta_ms; signed int imode; signed int current_ma; signed int cellthm; signed int delta_mah; signed int volt_hi_mv; signed int volt_lo_mv; signed int chgr_state; } FG_PARAM_T;
DFCC 表结构 三维查找表定义 DFCC 是一个三维查找表,用于在不同工况下补偿 RC(剩余容量)估算的偏差:
轴
含义
默认维度
单位
X 轴
SOC 区间
DFCC_X = 11
%
Y 轴
电流区间
DFCC_Y = 2~4(按项目)
mA
Z 轴
温度区间
DFCC_Z = 4
0.1°C
存储格式:short DFCC_table[DFCC_Y * DFCC_Z][DFCC_X]
维度由 DATA_TYPE 宏控制 1 2 3 4 5 6 7 8 9 10 11 12 #if (DATA_TYPE == 1027) #define DFCC_Y 1 #define DFCC_Z 4 #elif (DATA_TYPE == 1028) #define DFCC_Y 2 #define DFCC_Z 4 #endif #ifndef DFCC_X #define DFCC_X 11 #endif
DFCC 补偿原理 DFCC 表中的值为权重百分比:
值 = 100:无补偿(RC 估算准确)
值 > 100:实际容量比 RC 表估算值大,需上调
值 < 100:实际容量比 RC 表估算值小,需下调
算法在放电过程中,根据当前 SOC、电流、温度三个维度查 DFCC 表,得到补偿系数,修正 RC 表的输出值。
DLL 访问接口 1 2 3 4 5 6 7 8 __declspec(dllexport) short get_dfcc_xdata_77561 (int index) ; __declspec(dllexport) short get_dfcc_ydata_77561 (int index) ; __declspec(dllexport) short get_dfcc_zdata_77561 (int index) ; __declspec(dllexport) short get_dfcc_table_77561 (int index1, int index2) ; __declspec(dllexport) void set_dfcc_table_77561 (int index1, int index2, short value) ;
C# GUI 层(BatterySimer) P/Invoke 调用模式 C# 通过 DllImport 调用 C DLL,所有字符串返回值使用 IntPtr + Marshal.PtrToStringAnsi() 模式:
1 2 3 4 5 6 7 8 9 [DllImport(@"SOCLib77561.dll" , CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl) ] public static extern IntPtr soc_init_77561 (string line ) ;[DllImport(@"SOCLib77561.dll" , CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl) ] public static extern IntPtr soc_process_77561 (string line ) ;IntPtr ptr = soc_process_77561(csv_line); string result = Marshal.PtrToStringAnsi(ptr);
仿真主循环 1 2 3 4 5 6 7 8 9 10 11 soc_init_77561(lines[1 ]); for (int i = 2 ; i < lines.Length; i++){ IntPtr ptr = soc_process_77561(lines[i]); string result = Marshal.PtrToStringAnsi(ptr); }
SharpGL 绘图数据结构 1 2 3 4 5 6 7 8 9 10 11 struct d2f { public float xx; public List<float > yy; }
GUI 支持:
各曲线独立显示/隐藏
鼠标缩放和平移
实时数据 tooltip
OCV/RC/DFCC/温度表的可视化编辑
端到端数据流 从电池测试到 DFCC 调参完成的完整链路:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 (1) 电池循环测试 循环仪按指定温度/电流执行充放电 输出: _Detail.csv (CC, I, U, mode, time) (2) COBRA 实时采集 COBRA工具通过I2C读取芯片寄存器 输出: COBRA_xxx.csv (28列, 含GGMEM状态) (3) BatterySimer 加载数据 ├── 加载 COBRA CSV → 解析列头 → set_cobratable_header_77561() └── 自动关联 _Detail.csv → 计算 cycle SOC (4) DLL 仿真处理 soc_init_77561(line[1]) → 初始化FG库 for each line: soc_process_77561(line[i]) → fg_update() → 返回 rsoc/fcc/rc/soh (5) 三曲线对比 cycle SOC vs cobra SOC vs simer SOC 误差曲线: cyc-sim 是否 < 3%? (6) DFCC 调整 ├── 误差大 → 修改 DFCC 表值 → 重新仿真 └── 误差小 → 调参完成 → 同步到固件
关键点:步骤 (4)-(6) 可以反复迭代,无需重新测试电池,这就是仿真环境的核心价值。
Python 自动化工具 auto_update_table.py 用于将 TableMaker 生成的 OCV/RC 数据自动同步到仿真代码:
工具流程: (1) 解析 OCV.txt → 提取 65 个 (电压, SOC) 数据点 (2) 解析 RC.txt → 提取三维数据(X轴 80点, Y轴 5点, Z轴 5点) (3) 用正则表达式定位 table.c 中对应 DATA_TYPE 的代码块 (4) 替换 OCV 和 RC 数组数据
注意事项:
此脚本不更新 DFCC 表 ,DFCC 需要根据客户定义的温度/电流测试条件手动配置 table.h 的 DFCC_Y/DFCC_Z 维度
更新后需人工确认 table.c 是否与 FW PRJ 一致
parameter.c 的电池参数需手动与固件同步
多项目支持与仿真-固件关系 DATA_TYPE 系统 单代码库通过 DATA_TYPE 宏支持 20+ 不同电池项目,每个项目定义独立的:
配置项
说明
示例
XAxis / YAxis / ZAxis
RC 表维度
80 / 5 / 5
DFCC_Y / DFCC_Z
DFCC 表维度
2 / 4
CURR_DIV
并联电芯数(电流分流比)
1(单芯)或 6(6并)
dsncap
设计容量 (mAh)
5000
eocmv / eodmv
满充/截止电压 (mV)
4400 / 3200
切换项目只需修改 table.h 中的 #define DATA_TYPE 值,重新编译 DLL 即可。
仿真与固件的一致性要求 仿真结果可信的前提是算法代码与固件完全一致:
(1) lib_fg.c 必须与固件版本相同(用 WinMerge 对比确认) (2) table.c / table.h 的 OCV、RC、DFCC 数据必须与固件 PRJ 匹配 (3) parameter.c 的电池参数(dsncap, eocmv, eodmv, sysim, slope)必须与固件一致
如果 cobra 曲线与 simer 曲线存在系统性偏差(而非局部 DFCC 误差),通常说明算法代码或参数不同步,需要先排查一致性问题再进行 DFCC 调参。