DFCC动态FCC自适应补偿算法(三):库仑计SOC算法工程实现

1. 工程概述

1.1 项目架构

1
2
3
4
5
6
7
sd77561-AE/
├── base_line_newton_guanyu_20250318_FCC idle_bugfix_HighTemperatureCV/
│ └── base_line_newton_guanyu/
│ ├── flash/ # 外设驱动:I2C/UART/ADC/Timer
│ ├── lib/ # 核心算法库:lib_fg.c
│ ├── user/ # 应用层:main.c, parameter.c
│ └── chip/ # 芯片抽象层:chip_irq.c, chip_adc.c

1.2 代码版本演进

lib_fg.c 的历史记录可以看到算法的持续优化:

1
2
3
4
5
6
7
2019-04-13: 初始版本
2019-09-26: Fix RSOC负值问题
2020-05-21: 加入 DFCC 触发条件
2020-07-10: 加入 CTA 温度补偿
2021-01-21: 优化充电算法
2022-05-11: 移动版优化
2024-06-03: 最新版本 (v20240603)

2. 核心数据结构

2.1 固件配置结构

1
2
3
4
5
6
7
8
9
10
typedef struct {
int16_t l_fg_dfcc_learnratio; // DFCC学习速率
int16_t l_fg_dfcc_auto_maxthm; // 自动开启温度阈值
int16_t l_fg_dfcc_auto_mincurrent; // 自动开启电流阈值
int16_t l_fg_dfcc_minstep_th; // 最小步进值
int16_t l_fg_dfcc_update_maxsoc; // 最大SOC变化
int16_t l_fg_dfcc_update_socrange; // 最小放电量
int16_t l_fg_dfcc_update_thmrange; // 温度变化范围
int16_t l_fg_dfcc_maxrange; // 单次最大补偿
} LIB_FG_PARAM_T;

2.2 算法状态结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
typedef struct {
uint32_t fcc; // Full Charge Capacity (mAh)
uint32_t rc; // Remaining Capacity (mAh)
uint32_t facc; // Fake ACC (用于估算)
int16_t soc; // State of Charge (0.01%)
int16_t rsoc; // Relative SOC (0.01%)
int16_t soh; // State of Health (0.01%)

// 内部状态
uint8_t status; // FG_STAT_XXX
int16_t cellthm; // 电芯温度
int16_t cellmv; // 电芯电压 (mV)
int32_t cc; // 累计充电容量 (mAh)
int32_t dc; // 累计放电容量 (mAh)

// DFCC 相关
int32_t dfcc; // 动态FCC
int16_t dfcc_ratio; // DFCC 速率
} LIB_FG_TYPE_T;

2.3 状态机定义

1
2
3
4
5
6
7
8
9
// 固件状态定义
#define FG_STAT_INIT 0x00 // 初始化
#define FG_STAT_DSG 0x01 // 放电状态
#define FG_STAT_CHG 0x02 // 充电状态
#define FG_STAT_IDLE 0x04 // 空闲状态
#define FG_STAT_FC 0x08 // 满充状态
#define FG_STAT_FD 0x10 // 满放状态
#define FG_STAT_DFC_TCC 0x20 // DFCC温度触发
#define FG_STAT_EXT_HDC 0x40 // 高动态电流

3. 核心算法流程

3.1 主循环 fg_update()

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
36
37
38
39
40
41
42
43
44
45
/**
* @brief 主更新函数,每秒调用一次
*/
void fg_update(void)
{
// 1. 获取原始数据
cellmv = adc_read_cell_voltage(); // 读取电芯电压
cc = adc_read_cc(); // 读取库仑计
cellthm = adc_read_temperature(); // 读取温度

// 2. 计算瞬时电流
im = (cc - cc_prv) / dt; // 电流 = 电荷变化/时间

// 3. 更新平均电流
fg_cmavg_update(im);

// 4. 状态检测
detect_battery_status();

// 5. 根据状态执行对应算法
switch (status) {
case FG_STAT_DSG:
fg_discharge_process();
break;
case FG_STAT_CHG:
fg_charge_process();
break;
case FG_STAT_IDLE:
fg_idle_process();
break;
}

// 6. DFCC 更新
if (fg_dfcc_enable) {
fg_dfcc_update();
}

// 7. SOH 更新
soh_update();

// 8. 计算最终 SOC
fg_calculate_soc();

cc_prv = cc;
}

3.2 放电处理 fg_discharge_process()

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
void fg_discharge_process(void)
{
// 1. 累计放电容量
deltauah = -im * dt / 3600; // mAs → mAh
dc += deltauah;

// 2. 更新 RC (Remaining Capacity)
rc = fcc - dc;

// 3. 检测快速放电状态
if (detect_fast_discharge()) {
fg_fast_dsg();
}

// 4. 检测过放
if (cellmv < EODMV) {
status = FG_STAT_FD;
fcc = dc; // 更新 FCC
}

// 5. DFCC 更新条件检测
if (dfcc_condition_met()) {
dfcc_update_by_lookup();
}
}

3.3 满放检测 fg_fast_dsg()

快速放电状态下,放电末端 SOC 变化速率加快:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* @brief 快速放电处理 (RSOC < 10%)
* 规则:
* EOD ~ (EOD-100): 10s 1%
* (EOD-100) ~ (EOD-200): 5s 1%
* (EOD-200) ~ : 1s 1%
*/
void fg_fast_dsg(void)
{
int16_t soc_remaining = rsoc; // 剩余 RSOC

if (soc_remaining > 100) {
// RSOC > 10%, 正常速度
rsoc -= 1; // 10s 下降 1%
}
else if (soc_remaining > 0) {
// RSOC < 10%, 加速
rsoc -= 2; // 5s 下降 1%
}
}

4. DFCC 自适应实现

4.1 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
25
26
27
28
29
/**
* @brief 检测是否满足 DFCC 更新条件
* 触发条件(满足任一即可):
* 1. 温度变化 > 阈值
* 2. SOC 变化 > 阈值
* 3. 累计放电量 > 阈值
*/
static uint8_t dfcc_condition_met(void)
{
int16_t dthm = abs(cellthm - dfcc_last_thm);
int16_t dsoc = abs(rsoc - dfcc_last_soc);

// 条件1: 温度变化超过 1°C
if (dthm > 10) { // 单位 0.1°C
return 1;
}

// 条件2: SOC 变化超过 2%
if (dsoc > 200) { // 单位 0.01%
return 1;
}

// 条件3: 累计放电量超过 50mAh
if (abs(dccuh) > 5000) { // 单位 0.01mAh
return 1;
}

return 0;
}

4.2 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
25
26
27
28
29
/**
* @brief 通过查表更新 DFCC
*/
static void dfcc_update_by_lookup(void)
{
// 1. 查找当前工况对应的表格索引
int soc_idx = find_soc_index(rsoc);
int cur_idx = find_current_index(abs(im));
int thm_idx = find_temp_index(cellthm);

// 2. 查表得到目标 DFCC
int target_dfcc = DFCC_table[thm_idx][cur_idx][soc_idx];

// 3. 渐进式更新
int delta = (target_dfcc - dfcc) * dfcc_ratio / 100;

// 4. 限制单次最大变化
if (delta > FG_DFCC_MAXRANGE) delta = FG_DFCC_MAXRANGE;
if (delta < -FG_DFCC_MAXRANGE) delta = -FG_DFCC_MAXRANGE;

dfcc += delta;

// 5. 同步更新 FCC
fcc = dfcc;

// 6. 记录当前状态
dfcc_last_thm = cellthm;
dfcc_last_soc = rsoc;
}

5. 温度补偿

5.1 温度对电量的影响

电池在低温下可用容量显著降低,需要温度补偿:

1
2
3
25°C:  100% 可用容量
0°C: 70% 可用容量
-10°C: 50% 可用容量

5.2 CTA (Cell Temperature Aging) 估算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* @brief 估算温度补偿因子
* 根据当前电流和温度,计算温度升高导致的容量变化
*/
static void fg_cellthm_estimation(void)
{
// 温度升高 = I² × R_internal × t
// 简化计算:温度变化 ≈ I × K_thm

int16_t thm_delta = cellthm - thm_base; // 温度变化
int32_t i_sqr = im * im; // 电流平方

// 容量补偿 = I² × K × ΔT
int32_t dcap_thm = (i_sqr * K_thm * thm_delta) / 10000;

// 应用补偿
rc += dcap_thm;

// 更新基准温度
thm_base = cellthm;
}

6. 边界处理

6.1 满充检测

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#define FG_CHG_EOCTIME    30   // EOC 判定时间 (s)
#define FG_FC_VOLTAGE 4400 // 满充电压 (mV)
#define FG_EOC_CURRENT 100 // 涓流判定电流 (mA)

void fg_charge_process(void)
{
// 1. 检测 CV 阶段
if (cellmv > CV_THRESHOLD) {
status_cv = 1;
}

// 2. CV 阶段判断满充
if (status_cv && abs(im) < FG_EOC_CURRENT) {
chgtime++;
if (chgtime > FG_CHG_EOCTIME) {
status = FG_STAT_FC;
fcc = cc; // 更新 FCC
}
}
}

6.2 满放检测

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#define FG_EOD_VOLTAGE    3000 // 满放电压 (mV)
#define FG_ELT_VOLTAGE 3200 // 极低电量电压 (mV)

void fg_discharge_process(void)
{
// 1. 检测极低电量
if (cellmv < FG_ELT_VOLTAGE) {
status = FG_STAT_ELT;
rsoc = 100; // 约 1%
}

// 2. 检测满放
if (cellmv < FG_EOD_VOLTAGE) {
status = FG_STAT_FD;
fcc = dc; // FCC = 实际放出的容量
rsoc = 0;
}
}

7. 调试与日志

7.1 调试打印

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#ifdef FG_DEBUG
void fg_debug_print(void)
{
printf("[FG] FCC=%d RC=%d SOC=%d.%02d%% RSOC=%d.%02d%% SOH=%d.%02d%%\n",
fcc, rc,
soc/100, soc%100,
rsoc/100, rsoc%100,
soh/100, soh%100);

printf("[FG] V=%dmV I=%dmA T=%d.%d°C Status=0x%02X\n",
cellmv, im,
cellthm/10, cellthm%10,
status);

printf("[FG] CC=%d DC=%d DFCC=%d\n",
cc, dc, dfcc);
}
#endif

7.2 固件版本获取

1
2
3
4
5
6
7
/**
* @brief 获取固件版本
*/
uint32_t fg_get_version(void)
{
return LIB_FG_VERSION; // 0x20240603
}

8. 与简历要点的对应

简历要点 代码实现
电量算法核心逻辑 lib_fg.c 完整 SOC/DFCC 算法
满充/满放边界处理 fg_charge_process() / fg_discharge_process()
系统阻抗导致的电量异常跳变 fg_cellthm_estimation() 温度补偿
ADC 温度漂移校准 adc_read_temperature() + 滤波
电量精度误差 < 3% DFCC 三维权衡 + 平滑更新
动态容量估算 dfcc_update_by_lookup()
电量报满机制 fg_fast_dsg() 快速放电处理
温度阻抗补偿 CTA 温度补偿算法
系统校准 OCV 查表初始化

9. 小结

本文介绍了库仑计电量算法的完整工程实现:

  1. 状态机架构:INIT → IDLE/DSG/CHG → FC/FD
  2. DFCC 自适应:查表 + 渐进式更新 + 触发条件
  3. 温度补偿:CTA 估算 + 容量补偿
  4. 边界处理:满充、满放、快速放电
  5. 调试支持:完整日志、版本查询

结合第一篇的算法原理和第二篇的仿真调参,形成了算法研究 → 仿真验证 → 固件实现的完整闭环。


系列目录
01. DFCC算法原理与电池阻抗追踪
02. DFCC参数调校与仿真验证系统
03. 库仑计SOC算法工程实现(本文)