3、安时积分法:基本原理、累积误差分析、初始SOC确定、库仑效率校准

安时积分法,说白了就是「数着电流算电量」。

你想想看,电池的充放电过程,本质上就是锂离子在正负极之间来回搬家。电流大,搬得快;电流小,搬得慢。那我们只要把每一瞬间的电流都记录下来,再对时间做个积分,理论上就能知道电池里还剩多少「家当」——也就是SOC。

这个方法很直观,也是目前BMS里最常用的SOC估算手段之一。我在项目里见过不少同行,一上来就想着用卡尔曼滤波或者神经网络,结果连安时积分法都没调明白。我个人习惯是,先把安时积分法吃透,再考虑要不要上更复杂的算法。

3.1 基本原理

安时积分法的数学表达式很简单:

SOC(t) = SOC(0) - (1 / Q_n) * ∫ η * I(t) dt

其中:

  • SOC(t):当前时刻的荷电状态
  • SOC(0):初始荷电状态
  • Q_n:电池的额定容量(单位:Ah)
  • η:库仑效率
  • I(t):t时刻的电流(放电为正,充电为负)

嗯,这里要注意:积分符号前面的负号,是因为我们定义放电电流为正。放电时电流为正,SOC下降,所以是减号。

在实际的BMS代码里,我们不可能真的去做连续积分。一般都是用离散累加的方式:

def soc_integration(soc_initial, current_array, dt, coulomb_efficiency, rated_capacity):
    """
    安时积分法离散实现
    :param soc_initial: 初始SOC (0~1)
    :param current_array: 电流采样序列 (A),放电为正
    :param dt: 采样间隔 (s)
    :param coulomb_efficiency: 库仑效率 (0~1)
    :param rated_capacity: 额定容量 (Ah)
    :return: SOC序列
    """
    soc = soc_initial
    soc_list = []
    # 将容量从Ah转换为As
    capacity_as = rated_capacity * 3600
    
    for i in current_array:
        # 累积安时变化量
        delta_soc = (coulomb_efficiency * i * dt) / capacity_as
        soc -= delta_soc
        # 限制SOC范围
        soc = max(0.0, min(1.0, soc))
        soc_list.append(soc)
    
    return soc_list

这段代码我用了很多年,核心逻辑就这几行。但实际工程中,远没有这么简单。

3.2 累积误差分析

安时积分法最大的痛点是什么?

误差会累积,而且越积越大。

为什么会这样?因为积分是个「记忆」过程。你每一次的电流采样误差、时间基准误差、容量标定误差,都会被积分器记住,然后叠加到最终结果上。

我在项目中遇到过最典型的情况:一个电池包静置时SOC显示80%,客户说「怎么放了一晚上,SOC变成82%了?」——这就是积分误差在作祟。

误差来源主要有三个:

误差来源 典型量级 影响
电流传感器偏置误差 ±5mA ~ ±50mA 长期累积,影响最大
电流传感器增益误差 ±0.5% ~ ±2% 与电流大小成正比
时间基准误差 ±10ppm ~ ±100ppm 长期运行后显现
容量标定误差 ±1% ~ ±5% 影响满充/满放判断

我曾经做过一个测试:用50mA的偏置误差去积分一个100Ah的电池包,24小时后SOC误差就超过了1%。你想想看,如果这个误差不处理,一个月下来会偏到哪里去?

⚠️ 避坑指南: 我曾经在一个项目中,因为电流传感器零点漂移没处理好,导致SOC在静置状态下每天漂移2%。后来花了整整一周排查,才发现是温度变化引起的偏置漂移。所以,电流传感器的零点校准,一定要做温度补偿

3.3 初始SOC确定

安时积分法需要一个初始值。这个初始值如果给错了,后面再怎么积分都是错的。

确定初始SOC,我常用的方法有三种:

  1. 开路电压法(OCV法):电池静置足够长时间后,端电压会趋近于开路电压。通过OCV-SOC曲线查表,就能得到初始SOC。这是最可靠的方法,但需要电池静置2小时以上。
  2. 上次下电记忆法:系统休眠前保存SOC值,下次上电时直接读取。这个方法简单,但有个坑——如果电池在休眠期间发生了自放电或者被外部负载消耗,读回来的值就不准了。
  3. 电压+温度联合查表法:对于不能长时间静置的场景(比如电动汽车),可以用电压和温度做一个粗略的SOC估计,作为积分起点。

我个人习惯是:能静置就静置,不能静置就保守估计

举个例子,在储能BMS项目中,我要求系统上电后先判断静置时间。如果静置超过2小时,就用OCV法;如果不足2小时,就用上次记忆的SOC,但标记为「低置信度」,同时启动电压辅助校正。

def determine_initial_soc(ocv, rest_time, last_soc, ocv_soc_table):
    """
    确定初始SOC
    :param ocv: 当前开路电压 (V)
    :param rest_time: 静置时间 (s)
    :param last_soc: 上次保存的SOC
    :param ocv_soc_table: OCV-SOC查表数据
    :return: (初始SOC, 置信度)
    """
    if rest_time > 7200:  # 静置超过2小时
        # 使用OCV法
        soc = lookup_ocv_soc(ocv, ocv_soc_table)
        confidence = 0.95
    elif rest_time > 1800:  # 静置超过30分钟
        # OCV法,但置信度降低
        soc = lookup_ocv_soc(ocv, ocv_soc_table)
        confidence = 0.80
    else:
        # 使用上次记忆值
        soc = last_soc
        confidence = 0.60
        # 如果电压明显异常,做限幅处理
        voltage_based_soc = lookup_ocv_soc(ocv, ocv_soc_table)
        if abs(soc - voltage_based_soc) > 0.15:
            soc = voltage_based_soc
            confidence = 0.50
    
    return soc, confidence
💡 小技巧: OCV-SOC曲线在中间区域(20%~80%)比较平缓,电压变化很小。这时候查表法误差会比较大。我建议在两端区域(0%~20%和80%~100%)优先使用OCV法,中间区域则更依赖积分结果。

3.4 库仑效率校准

库仑效率,就是放出的电量与充入的电量之比。理想情况下是1.0,但实际中总会小于1。

为什么?因为充进去的电量,有一部分会变成热量散失掉,还有一部分会消耗在副反应中(比如SEI膜的形成)。

库仑效率不是个固定值,它跟很多因素有关:

  • 温度:低温下库仑效率明显下降,因为锂离子扩散变慢,副反应加剧
  • 电流倍率:大电流充放电时,极化效应增强,库仑效率降低
  • 电池老化:随着循环次数增加,内阻增大,库仑效率逐渐下降
  • SOC区间:在低SOC和高SOC区间,库仑效率通常更低

我在项目中是怎么处理库仑效率的?

说白了,就是建一个二维查表:

# 库仑效率查表:行=温度,列=电流倍率
coulomb_efficiency_table = {
    # 温度: { 电流倍率: 库仑效率 }
    25: { 0.1: 0.998, 0.5: 0.995, 1.0: 0.990, 2.0: 0.980 },
    10: { 0.1: 0.995, 0.5: 0.990, 1.0: 0.982, 2.0: 0.970 },
    0:  { 0.1: 0.990, 0.5: 0.980, 1.0: 0.970, 2.0: 0.955 },
    -10: { 0.1: 0.980, 0.5: 0.965, 1.0: 0.950, 2.0: 0.930 },
}

def get_coulomb_efficiency(temperature, c_rate):
    """
    根据温度和电流倍率获取库仑效率
    """
    # 找到最接近的温度和倍率
    temps = sorted(coulomb_efficiency_table.keys())
    temp = min(temps, key=lambda x: abs(x - temperature))
    
    rates = sorted(coulomb_efficiency_table[temp].keys())
    rate = min(rates, key=lambda x: abs(x - c_rate))
    
    return coulomb_efficiency_table[temp][rate]

嗯,这里要注意:库仑效率的校准不是一劳永逸的。我建议每半年或者每100次循环做一次在线校准。方法很简单——做一次完整的充放电循环,用实际放出的电量除以充入的电量,就能得到当前状态下的平均库仑效率。

核心要点总结:

  • 安时积分法原理简单,但误差会累积,必须配合其他方法校正
  • 初始SOC的确定,优先使用OCV法,静置时间不够时用记忆值+限幅
  • 库仑效率不是常数,要建立温度-倍率二维查表
  • 电流传感器的零点漂移是最大的误差源,务必做好温度补偿

最后说一句:安时积分法虽然「土」,但它是BMS的基石。我见过太多人一上来就搞什么深度学习、粒子滤波,结果连最基本的积分误差都控不住。先把安时积分法玩明白了,再谈别的。