基于STM32F4的锂电池SOC估算与均衡策略工程实践
1. 做SOC均衡前先搞清楚SOC为什么会偏1.1 单体不一致是均衡存在的唯一理由去年我做一块16串磷酸铁锂电池组的BMS样机时遇到了一个很典型的毛病整组充电器已经转灯但拆下来一量某几串电芯电压只有3.35V另外几串却已经顶到3.65V。当时保护板没有均衡功能SOC显示还有8%结果一拉载电压直接塌到保护值。说白了这就是电芯不一致导致的容量利用率问题。电芯不一致来自三个方面制造工艺的离散性、使用过程中的温度差异、以及循环老化速度不同。哪怕是同一批次出厂的电芯内阻、自放电率、容量也不可能完全一致。随着充放电循环次数增加这种差异会被逐步放大。一组电池的可用容量不是由平均值决定的而是由最差的那一串决定的。均衡的目的就是让各串电芯在充放电过程中尽量保持同步避免某一串提前到达截止电压从而浪费整组容量。1.2 SOC误差的三个来源采样、积分、模型做SOC估算时我习惯把误差来源分成三层来排查。第一层是采样误差。电压、电流、温度的测量精度直接决定SOC估算的上限。STM32F4内部的12位ADC理论上能分辨3.3V/4096约0.8mV但在实际板上电源纹波、PCB走线压降、参考电压漂移都会把有效精度拉低。我实测一块板子ADC采样值在静止状态下有±5mV的跳变这对SOC估算来说是不可接受的噪声。第二层是积分误差。安时积分法说白了就是把电流对时间做累加积分误差会随时间累积。假设电流采样偏置有10mA对一块100Ah的电池来说10小时就累积0.1Ah折合SOC约0.1%。看起来不大但如果偏置达到100mA10小时就是1%的SOC偏差而且这个误差只增不减没有收敛机制。第三层是模型误差。无论是开路电压查表还是等效电路模型本质上都是对电芯特性的近似。磷酸铁锂的OCV-SOC曲线在中段20%到90%非常平缓电压变化只有几十毫伏这个时候靠电压反推SOC误差相当可观。模型误差不像积分误差那样随时间累积但在特定SOC区间会被放大。1.3 为什么单独靠电压法撑不住很多人会问SOC直接查开路电压曲线不就行了吗实测中问题很多。电池从工作状态切换到静置状态极化电压需要相当长时间才能消除磷酸铁锂可能需要2小时以上。也就是说你必须等电池真正休息够测得端电压才对应OCV曲线。行驶中、充电中、刚停机时的电压都叠加了极化内阻和欧姆内阻上的压降直接查表必然不准。我在样机上做过一个对比测试同一串电芯静态放置3小时后测得电压3.32V查表SOC约55%而在1C放电过程中同样测到3.32V实际SOC已经到了40%左右。两者相差15个百分点。这就是我坚持在方案中采用OCV查表 安时积分 卡尔曼滤波三者融合的原因——任何一个单独方案都有硬伤组合起来才能互相弥补。2. 采样链路设计电压、电流、温度这三路数据怎么喂给STM32F42.1 电压采样从模拟前端到ADC的完整链路对串数较多的电池组优先选择专用模拟前端芯片来做电压采样比如常见的16串AFE方案通过SPI或I2C与MCU通信同时提供均衡MOS驱动、诊断功能和温度采集接口。它的优点是采样精度高、通道间一致性有保障、电气隔离也天然解决。STM32F4在这里的角色是负责策略判断、数据融合和总线上位机通信而不是直接去量每一串电压。如果只做几串的低压保护板试验当然可以用STM32F4的ADC直接采。此时必须注意输入通道的共模电压范围以及前端电阻分压网络的精度温漂。分压电阻用1%还是0.1%的合金电阻直接决定整条采样链路的精度天花板。我建议至少用0.5%精度、温度系数小于100ppm的电阻并且在ADC引脚对地并联一个0.1uF电容配合几十到几百欧姆的串联电阻构成低通滤波滤除高频噪声。关于采样触发我强烈建议用定时器触发ADC而不是在软件里用延时循环去读。STM32F4的ADC支持外部触发注入配合DMA可以做到固定采样率、零CPU干预。我一般配置定时器每100ms触发一次16路电压采样每路做64次累加后取平均等效采样率足够滤掉大部分工频干扰。CPU只在DMA传输完成中断里做数据搬运耗时几乎可以忽略。2.2 电流采样两个方向两种做法电流采样有两条路线分流电阻法和霍尔传感器法。分流电阻法在BMS里更常见尤其是需要控制BOM成本的场合。用毫欧级的锰铜或合金电阻串联在主回路中通过高精度运放把微弱压降放大到ADC可测范围或者直接用带放大功能的专用电流检测芯片。STM32F4的ADC采集放大后的信号换算成实际电流。这种方法线性度好、温漂可控但需要注意分流电阻的功率损耗100A电流流过2mΩ电阻功耗20W散热设计不能马虎。霍尔传感器的优势是隔离和几乎零插入损耗但零漂和温漂相对更明显小电流下精度不如分流电阻。我做均衡电流检测时用了开环霍尔静态输出有±10mA的波动对SOC积分来说需要做零点校准。方案里我用了一个低成本的零点校准策略电池静置超过一定时间后把霍尔输出读数的平均值记录为零偏量实时计算时扣除。无论哪种方式电流采样值最终都要进安时积分器所以偏置误差必须严肃对待。我调试时发现运放的输入偏置电流和参考电压误差会造成实测零点偏移这一步不做校准后面SOC积分会越漂越远。2.3 温度采样与SOC温度修正温度对SOC估算的影响常被低估。电池在不同温度下的可用容量不同低温时放电容量明显衰减内阻增大、极化加剧同一SOC下端电压也不同。如果SOC算法不引入温度修正冬季低温场景会出现SOC虚高、电量跳变的现象。我在这块BMS上用了两种温度采集方式混合每串电芯附近的AFE芯片自带NTC输入采集电芯表面温度同时在电池组两侧布置两路独立NTC通过STM32F4的ADC直接采集作为环境温度参考。所有温度数据进入SOC算法后参与两个修正一是容量修正系数二是OCV查表曲线的温度插值。温度采样同样要用DMA配合定时器只不过NTC信号本身变化慢采样频率可以降到每1秒一次。另外NTC的串联分压电阻需要低漂移类型否则温度变化引起的分压变化会被错误当成NTC阻值变化产生几度的偏差。我在实际样板调试时遇到过NTC引脚被干扰的问题解决方法是在ADC引脚加100nF电容并做软件滤波。3. 核心算法落地查表、安时积分与卡尔曼滤波的组合拳3.1 OCV-SOC查表与滞回处理在STM32F4上做SOC估算大多数人会先建立一张电压-SOC查找表。这张表怎么来最好不要直接拿厂家手册的典型曲线而应该用你实际批次电芯做静态标定充满后静置按5%或10%的SOC步进放电每次静置足够长时间后记录端电压再把数据拟合、插值成至少几十个点的数组。实测过程中最值得注意的是滞回现象。充电平衡状态下和放电平衡状态下相同SOC对应的OCV并不一致差距可以到20mV以上。磷酸铁锂这方面尤其明显。我在算法里维护了充放电两套OCV表根据最近的电流方向和充电累计电量切换查表。同时增加了一个滞回过渡逻辑当电流方向改变时估算的OCV在两条曲线之间渐进过渡而不是瞬时跳变避免SOC输出明显突变。具体数据结构很简单一个const数组存SOC点对应的OCV一个const数组存OCV点对应的SOC二分查找配合线性插值。在STM32F4上用浮点计算和二分法没有任何性能压力查找一次耗时是微秒级完全可以在1秒周期的估算任务里随意调用。3.2 安时积分采样率、漂移与校零安时积分的基础公式就是SOC(t) SOC(0) - (∫I dt) / Q_nom。工程上要做的首先是把电流采样值转换为Ah增量并按固定周期积分。我设定估算周期为1秒电流采样周期为100ms每1秒对近10个电流样本做算术平均再乘时间差得到Ah增量累加到当前SOC上。积分有两个关键敌人。第一个是零点漂移上面提到过霍尔和运放都会有零偏。我在设备进入静置状态且电流小于一定阈值时把当前读数的平均值记录为零偏补偿量参与实时计算。需要注意只有在电量稳定的状态才适合校准否则会把真实电流当成零偏消掉。第二个是容量老化。Q_nom不是一个常量它随循环次数增加而下降。严谨的做法是定期做一次满充满放标定把积分得到的实际容量更新到算法里。我的方案支持通过上位机写入实际容量值同时在每次充满判据成立时把安时积分结果强制归一到100%消除累积误差。3.3 卡尔曼滤波在STM32F4上的工程化卡尔曼滤波的原理大家都清楚但落地到MCU上有几个实际工程点需要处理。我采用的是扩展卡尔曼滤波EKF状态量是SOC和极化电压输入量是电流观测量是端电压。状态方程离散化后SOC的预测就是上一时刻SOC减去电流积分与容量之比极化电压预测项包含一个由RC参数决定的时间常数衰减项。测量方程就是端电压 OCV(SOC) 极化电压 欧姆内阻×电流。核心难点是测量方程的雅可比矩阵需要计算dOCV/dSOC。我把OCV-SOC数组的导数也预先算好存在另一个const数组里插值得到当前梯度。这样在STM32F4上就避免了运行时求解偏导数的复杂运算。STM32F4带有FPU单精度浮点运算足够快。EKF里的矩阵运算维度很小我用C语言手写没有引入通用矩阵库反正就是2x2和1x2的运算量。整个EKF一步迭代在168MHz主频下运行时间不到几十微秒1秒的周期里非常充裕。这里要提醒一点卡尔曼滤波的Q和R参数不是随便设的。Q设得小滤波增益低SOC变化迟缓但抗扰能力强Q设得大跟踪速度快但容易被噪声带偏。我测试中Q设太小时从静置切到放电状态SOC要几分钟才能跟上真实值表现就是显示值掉得慢、突然跳一下。最后我是在不同工况下反复试出来的折中值并且让Q随电流大小动态调整大电流工况下信任安时积分小电流/静置工况下信任电压测量。4. 均衡策略的工程实现什么时候均衡才不算瞎折腾4.1 被动均衡电路与MOS控制细节SOC均衡和SOC估算完全不同它是要真正干预电池状态的。我的方案选择被动均衡理由很简单电路简单、控制可靠、成本低对中小容量电池组完全够用。主动均衡效率高但电感或变压器的能量转移控制逻辑复杂在紧凑的板子上也不易布局。被动均衡的电路拓扑是每串电池并联一组均衡电阻 均衡MOS。MOS管由STM32F4的GPIO控制或者由AFE芯片内部的均衡开关控制。均衡电阻阻值决定均衡电流我用的典型值是51Ω对应单串3.2V电压下约63mA的均衡电流。也有人用10Ω电阻做到300mA级别但散热和功耗考验比较大16串同时均衡时电阻网络总功耗可能超过10W板子会明显发热。我使用的是AFE芯片内置均衡MOS只需通过I2C/SPI写入均衡控制寄存器即可开启对应通道省去了外置MOS驱动电路。实际测试中内置MOS的导通电阻和额定电流需要确认部分AFE的均衡电流上限只有几十毫安不适合大容量电芯。大容量电芯做均衡时可以考虑外置MOS并联多组电阻的方案。4.2 均衡判据压差、SOC差、温度、状态机均衡不能不分时机地一直开着。均衡开启时机不对不仅浪费能量还会让SOC本来偏高的串被强行拉低到错误值。我设计的均衡状态机分成三个阶段充电均衡、静置均衡、放电不均衡。充电阶段是均衡的最佳窗口因为充电末期电压被充电机抬升到较高水平最高单串电压已经接近充电截止电压此时把偏高电芯的能量通过电阻放掉能减缓它到达截止电压的速度让其他电芯继续充电。静置阶段也会做小幅均衡目的是修正静置电压差异但这个阶段均衡电流不能太大避免把电芯压到均衡曲线以下。开启均衡的条件我在代码里做成同时满足多项最高单体电压高于某个平台值比如3.40V、最高与最低单体压差大于30mV、被均衡串的温度低于设定阈值比如45℃、电池处于非放电状态且电流小于设定值。只有这些条件全部满足均衡状态机才允许进入均衡流程。为什么要在充电阶段才均衡如果静置时某串电压偏高就拼命均衡很容易造成虚均衡这串电芯的电压偏高可能只是静置时间不够、极化未消除而不是真的SOC偏高强行均衡会把它拉到不健康的低SOC状态。4.3 均衡结束条件与异常保护均衡不能无休止地进行。我设置了几个结束条件任何一个满足就停止整组均衡或关闭该串通道。单体压差收敛到阈值以下例如10mV以内说明不一致已经修正充电过程结束均衡必须同步停止防止把高SOC电芯放过头被均衡串电压降到与最低串电压一致此时继续均衡意义不大甚至会引入反向差异温度超限均衡电阻发热严重时立即关闭转化为告警事件上报均衡连续运行超过预设时长例如2小时即使压差还没收敛也要强制停一段时间避免电阻长期发热我把这些条件全部挂在1秒的周期任务里检查每次均衡开关操作后更新AFE寄存器并在内存中保留均衡记录方便通过上位机查看哪一串被均衡过、均衡了多久。这个记录对后续定位电芯老化非常有用——经常被均衡的串大概率容量偏低需要重点关注。5. 参数整定与实测调试记录5.1 从仿真到真电池的差距我先在PC端的仿真模型里用理想数据跑SOC估算逻辑把EKF的增益参数和OCV表调到自洽但移植到STM32F4真机上后问题马上就来了。最大的差距是真实电压数据里带着噪声和极化干扰。仿真里我给OCV查表输入的是一个精确值真机上输入的是经过64次平均的采样值仍然有大约2mV的毛刺。这个毛刺对端电压观测方程的影响不大但在计算dOCV/dSOC时会放大——曲线平坦区段的导数很小微小电压误差会换算成较大的SOC修正量。解决思路是让EKF在静置和动态工况下使用不同的R参数。静置时端电压可信R设小一些让滤波器更多信任电压观测动态时极化模型不完美R设大一些更多信任安时积分。同时我限制了单次EKF修正SOC的最大幅度比如单次不超过3%防止个别异常采样点把SOC打飞。5.2 典型调试问题跳变、振荡、均衡失效调试阶段我遇到过一个很典型的SOC跳变问题电池从放电切到静置显示SOC会在几秒内从52%跳变到58%再弹回54%。排查下来原因是我在滞回过渡和EKF修正两部分同时对OCV做了调整两个修正量叠加导致过冲。后来我把滞回过渡改成纯曲线插值不再直接修正SOC只影响测量方程的OCV值SOC的修正完全交给EKF的状态更新逻辑问题就消失了。均衡振荡的案例也值得分享。最初我的均衡开启条件里压差阈值是30mV关闭条件是10mV。实际运行时某串电芯被均衡到与最低串只差8mV均衡关闭但因为它自放电率稍高电压慢慢回落半小时后压差又到28mV均衡重新开启。这样的振荡导致均衡电流频繁通断对MOS寿命不利。我加了时间延迟均衡关闭后至少要等待10分钟才能重新开启并且关闭阈值提高到15mV让均衡留出一点余量。还有一个均衡失效的情况在充电阶段开启均衡后均衡电流会叠加到充电电流里导致被均衡电芯所在回路的充电电流反而略高出现越均衡越慢的现象。后来我把充电阶段均衡的判定策略做了调整只在接近充电截止时开启均衡配合充电机降流阶段才能保证均衡效果可观测。5.3 参数整定的实践清单最后分享一份我在调试过程中沉淀下来的参数整定清单直接按这个顺序过能少走不少弯路。先校零后调增益任何电流采样校零不完成后面所有积分逻辑都不可信SOC初始值用静置OCV对表不要用上次下电保存值直接续着用除非确认电池没有明显自放电OCV-SOC表的标定必须用同一批次电芯不同厂家的电芯曲线差异足以改变整个SOC行为EKF的Q和R参数用日志记录法来调跑实际工况记录电压残差残差偏大说明R偏小或模型不准SOC过冲说明Q偏大均衡开启后要在日志里记录均衡通道和时长隔段时间对比一下长期被均衡的串大概率容量衰减后续维护时优先排查电池组静置下的压差正常应在10mV之内超过20mV要检查连接片压降、采样线虚接和电芯本身差异别一上来就调均衡参数整套系统在STM32F4上运行稳定后我做了一个小实验把均衡功能关闭充满后静置24小时记录各串压差再把均衡打开跑一轮完整充电同样静置24小时。压差从关闭时的37mV收敛到12mV满充容量利用率提高了约6个百分点。这个数据侧面说明了SOC估算和均衡策略配合的价值。目前在琢磨的是把主动均衡方案做一个简化版样机利用STM32F4的定时器输出可控PWM驱动电感式能量转移电路想看看效率能把被动均衡的发热损耗优化到什么程度。这个坑估计又要踩几个月后面有结论了再来跟大家细聊。