记得前年给一个户外储能柜做备用电源板,最初只给两串磷酸铁锂配了最简单的电阻被动均衡。当时觉得,才两节电池,内阻差异再大也不至于出问题。结果连续循环测试到第三个月,有一组电池看起来电压都正常,但放电容量只有标称的六成左右。拆开一量,一节电芯 3.62V,另一节却已经 3.85V。这件事让我把“双串电池均衡”提到了正经关注的位置。
最近一版方案,我改成了用 MP2642GR-Z 做电荷搬移的主动均衡通道,配合 STM32L081CB 做采样、策略和状态管理。这套组合在储能和备用电源这种长期带电、高可靠性要求的场景里,表现比我预想的稳。这篇文章把整个设计过程、关键电路、固件逻辑以及调试时踩过的坑都整理一遍,希望能给同样在做小容量电池管理模块的朋友一个可以复用的参考。
1. 双串电池组的均衡困局:两节电芯也不省心
1.1 两节电池为什么会出现压差
串联电池组里,充电电流对所有电芯是一样的,但电芯之间没有完全相同的。从出厂开始,容量和内阻就有离散性,再加上摆放位置、散热条件、老化速度不同,自放电率也各有差异。
打个比方:两节电芯像两个人一起跑步,配速不一样但脚被绑在一起。步数一样,消耗的体力却不同。电池里的“体力”就是荷电状态,两节电芯的荷电状态慢慢拉开,表现在端电压上就是压差。
在不同后备电源和储能场景里,这个差异会被进一步放大。储能系统经常小倍率浮充,长期悬挂在高压区,自放电速率不一致会产生持续的“暗差”;备用电源则更多是待机,低倍率充电把你维持在那里,偶尔大电流短时放电,内阻不一致导致动态压差更明显。
1.2 不均衡的后果比想象中严重
很多人觉得,只要两节电压差不超过 100mV,用着也没事。但问题不在当下,而在循环后的累积。
常见的失效逻辑是这样的:每次充满,高容量或低自放电的那节电芯先到充电截止电压,充电器必须停止或进入恒压模式。此时低容量电芯可能还没有充满,整组电池的电量被“最高的那节”卡住。放电时反过来,容量低的那节先到欠压保护点,整组放电也必须停止。
结果就是:可用容量约等于最差电芯的容量。一个月两个月可能只损失百分之几的容量,但一年下来,容量衰减速度和压差扩大形成恶性循环。更严重的是,如果均衡一直不动作,充电末端电压失控,过充引起析锂或气胀,这就不是损失容量的问题,而是安全问题了。
1.3 储后备电和备用的特殊性
储能和备用电源系统跟消费电子不一样,它长期挂在固定电压上,一年 365 天在线。消费电子充电 2 小时就拔掉,电池均衡窗口很短;储能系统则动不动浮充几周甚至几个月,压差会被慢慢放大的机会更多。
备用电源还有一个特点:放电往往是突然的大电流冲击。比如某个监控系统断电后切到电池,瞬时电流可能到 0.5C 甚至 1C。内阻较大的旧电芯此时压降明显,系统可能误判欠压,而实际荷电状态并不低。动态的压差需要通过均衡改善的是静态荷电差异,如果不区分这两种情况,很容易做出错误策略。
所以,两串电芯虽然数量少,该有的均衡机制一个都不能省,只是规模可以做得更简单。
2. 方案拆解:MP2642GR-Z 与 STM32L081CB 的分工逻辑
2.1 为什么不用传统被动均衡方案
被动均衡的原理通俗讲就是:给电压高的电芯并一个电阻,把多余能量放掉,等它降到跟低压电芯差不多后再继续充电。这种方案成本低,也确实有大量产品在用。但有三个问题在这个场景里很致命:
一是速度太慢。以 50Ah 的磷酸铁锂为例,如果两节电芯的荷电状态相差 2%,也就是 1Ah 的能量,按 0.05A 的均衡电流算,需要整整 20 小时。被动均衡电阻一般不可能用太大,不然发热比电池自发热还严重,根本顶不住。
二是能量浪费。放掉的能量以热的形式消散,在户外储能柜这种小空间里,热量管理本身就很麻烦。
三是不治本。放电均衡只能抑制电压差扩大,无法把能量从高电芯转移到低电芯。如果两节电芯本身容量衰减有差异,被动均衡永远补不齐。
2.2 MP2642GR-Z 在这个设计里的角色
MP2642GR-Z 是一颗集成度比较高的电池充放电管理芯片,带有双路均衡通道。在我们的工程里,它主要负责能量转移的执行层:当软件判断需要均衡时,将较高电压电芯的一部分电荷,以开关变换的方式搬到较低电压电芯上。这比电阻放电效率高得多,实际测试也有 85% 以上的搬移效率。
打个比方,被动均衡是拿一个小漏斗把高处水桶的水舀到低处,少还漏;而 MP2642GR-Z 相当于一台小水泵,直接在两个桶之间定量转移。转移的电流大小、启停时机、目标方向,全部由 MCU 通过控制引脚下发,芯片负责把“指令”变成真实的电流动作。
芯片同时承担充电路径管理,在储能系统里太阳能模板或适配器输入后,它能跟 MCU 配合做简单的恒流、恒压充电控制。这样可以省掉一路独立的充电管理 IC。
不同封装的引脚定义和寄存器细节会有差异,实际选型时要以对应数据手册为准。我这里主要描述的是项目的功能划分和系统角度,跟具体版本无关。
2.3 STM32L081CB 负责什么
真正决定均衡“怎么均衡”的,是 STM32L081CB。这颗 MCU 是低功耗 Cortex-M0+ 内核,主频最高 32MHz,对于均衡控制这种任务富裕程度很高。它跑着几个关键任务:
第一个是电压、电流、温度的采集计算。内嵌 12 位 ADC,配合内部参考电压 VREFINT 可以做到对电源电压变化的补偿,采样精度足够支撑 10mV 级别的均衡判断。
第二个是均衡策略状态机。什么时候开始均衡、均衡电流多大、什么时候停止、异常时怎么退出,都是用软件实现。这样做的好处是后期可以针对不同电芯化学体系灵活调参数。
第三个是日志记录。STM32L081CB 内置一块真正的 EEPROM,不依赖 Flash 模拟,写均衡动作次数、故障事件、电芯压差曲线都很方便。备用电源设备往往要长期无人运行,有个非易失日志对维护很关键。
选择它还有一个原因:超低功耗待机电流非常小。在备用电源系统长期停电、完全由电池自供电的场景,MCU 睡眠期间的功耗直接决定电池能撑多久。这颗芯片的低功耗定时器唤醒模式非常匹配这个需求。
MP2642GR-Z 和 STM32L081CB 的关系可以简单画成:芯片负责“干活”,MCU 负责“判断和记录”。判断错了干活也白干,MCU 承担的是策略大脑的角色。
3. 硬件电路实施:采样链路、功率回路和保护闭环
3.1 电压采样电路:精度第一关
均衡的核心数据是每节电芯的端电压。这个数据错了,后面的判断全是错的。
两个电芯串联,如果以系统负极为参考点,第一节电芯的电压可以直接用一个电阻分压网络拉到 MCU 的 ADC 引脚;但第二节电芯不能直接分压,因为它的采样点叠在第一节电芯电压之上。工程上有两种常见做法:一种是直接差分采样,用运放做减法;一种是做双路分压后,在 MCU 端做减法处理。
我实际用的是双路分压后在 MCU 里做减法。第一节电芯电压直接采样,第二节做成“第二节+第一节”的总电压采样,然后软件里用总电压减第一节电压,间接得到第二节电压。这个方案省掉运放成本,但有一个坑:两个分压电阻的比列误差会被减法放大。所以分压电阻统一用 0.1% 精度,并且在生产时做一次性校准。
考虑到磷酸铁锂电芯电压范围约 2.5V 到 3.65V,两串总电压最高约 7.3V。分压比我选了 2:1,ADC 引脚最高只到 3.65V,还有余量。ADC 的参考电压用 3.3V,12 位分辨率对应一个 LSB 约 0.8mV,理论上够用,实际经过分压电阻误差和噪声影响后,整体采样精度在 ±5mV 以内,作为均衡判断已经足够。
采样引脚对地加 100nF 电容做滤波,同时串联 1kΩ 电阻做保护。如果电池出现较大的地弹或静电干扰,串阻能限制进入 MCU 引脚的电流,避免损坏 ADC 通道。
3.2 均衡功率回路的搭法
功率部分围绕 MP2642GR-Z 展开,外围主要是储能电感、开关管、续流路径和电池连接器。
以我们项目为例,均衡通道的电感选 10μH,DCR 尽量控制在 30mΩ 以下,因为均衡电流大概在 0.5A 到 1A,电感损耗不能忽略。开关频率由芯片和 MCU 配合决定,我们设置在 300kHz 左右,既能兼顾体积和效率,又没有高到干扰采样电路。
这里有一个容易被忽略的点:均衡通道的布局要走短而粗的功率回路,把它和首片的模拟采样区域隔开。我第一版 PCB 上功率电感和采样分压电阻离得太近,结果均衡启动后 ADC 读数出现明显的周期性跳动,后来做了调整才消除。开关节点上再用一个小电阻加并联的 RC 吸收网络处理振铃,能明显降低电磁干扰对采样的影响。
控制部分把 MP2642GR-Z 的使能和均衡方向控制引脚接到 MCU,同时加一个下拉电阻保证 MCU 未初始化时均衡通道处于关闭状态。这一点很重要,后面还会展开说。
3.3 保护电路:不能只靠 MCU
MCU 会因为各种原因跑飞、死机、甚至被调试器一下暂停。如果均衡通道只有软件能关闭,出一次异常可能就是电池损坏事故。所以我在电路层面做了几道硬保护。
首先,电源输入和电池两端都加保险丝,额定值按最恶劣工作电流的 1.5 倍到 2 倍选。其次,电池到均衡电路之间加 PTC 限流元件,防止短路时 PCB 走线成为严重事故。TVS 保护管加在电池端口,吸收瞬态冲击。
芯片本身有故障输出引脚,接一只 NTC 热敏电阻检测功率器件温度。当温度超过设定阈值,硬件上直接封锁均衡通道,哪怕 MCU 还在错误地在输出高电平,通道也进不来。
还有一个简单的“看门狗”逻辑:用 MCU 的一个专用 IO 输出心跳信号,接到功率链路控制逻辑里。当这个信号频率正常时,均衡使能有效;MCU 异常停止,心跳消失,通道在几百毫秒内自动关闭。这个设计成本极低,但避险价值很大。
4. 固件实现:测量校准、状态机与均衡控制策略
4.1 内部参考电压校准:算对电压的前提
STM32L081CB 的 ADC 参考电压默认是模拟电源 VDDA。但模拟电源不是绝对稳定的,尤其是电池供电的系统,电压会随负载波动。如果直接用 3.3V 当作基准,读数会跟着电源漂。
正确的做法是利用芯片内置的 VREFINT 通道。这个通道的输出是一个相对固定的电压,出厂时有校准值。通过读 VREFINT 的 ADC 值,可以反推出当前真实 VDDA 电压,进而修正所有其他通道的换算。换算公式大概是这样:
uint16_t get_vdda_mv(void) { // 读取内部参考电压通道的ADC原始值 uint16_t raw = adc_read_channel(ADC_CH_VREFINT); // VREFINT典型值约 3000mV,具体以芯片校准值Trimmed为准 uint16_t vrefint_offset_mv = 3000; // VDDA = VREFINT_mV * 4095 / raw return (uint16_t)((3000ul * 4095ul) / raw); }实际工程中我把 VREFINT 的换算过程和电芯电压采样绑定在一起:每次采样电芯电压前先读一次 VREFINT,换算当前真实参考电压,再计算电芯电压。这样即使电源电压在充电负载和放电负载之间切换,也能保持测量一致性。这是我在调试阶段被坑过很多次才加的修正,后面误区里会讲细节。
4.2 采样滤波和电压获取
MCU 的 ADC 单次采样受噪声影响比较大,尤其是均衡功率通道切换时,地线上会有 10mV 级别的波动。我采用采样 16 次去掉最大最小值后取平均的方式。这个方法比普通均值滤波更能抗尖峰,计算量也小。
每个均衡周期,软件先做一次完整的电压采集,算出两节电芯的压差:
#define CELL1_CH ADC_CHANNEL_1 #define CELL2_CH ADC_CHANNEL_2 int16_t v1, v2; // 单位mV int16_t diff_mv; v1 = get_cell_voltage(1); v2 = get_cell_voltage(2); diff_mv = (int16_t)(v1 - v2);注意 v2 如果是“总电压减 v1”得到的,必须确保 v1 和总电压是同一次采样周期完成,否则电池在动态负载下会产生时间差导致的伪压差。
4.3 均衡状态机设计
均衡控制的状态机我分成四个状态:待机、充电均衡、空闲均衡、故障等待。
判断逻辑如下:
#define EQ_START_OFFSET_MV 30 // 压差超过30mV启动 #define EQ_STOP_OFFSET_MV 10 // 压差降到10mV停止 #define EQ_HYSTERESIS_MV 15 // 迟滞回差 static uint8_t eq_state = EQ_IDLE; void battery_equalize_task(void) { int16_t diff = get_cell_diff_mv(); int16_t temp = read_ntc_temp(); // 温度过高或低电压场景不均衡 if (temp > MAX_EQ_TEMP || cell_min_mv() < CELL_LOW_LIMIT_MV) { set_balance_channel(EQ_DISABLE); eq_state = EQ_FAULT_WAIT; return; } switch (eq_state) { case EQ_IDLE: if (diff > EQ_START_OFFSET_MV) { set_balance_channel(EQ_BALANCE_CELL2); // 把能量搬到低压电芯 eq_state = EQ_BALANCING; } else if (diff < -EQ_START_OFFSET_MV) { set_balance_channel(EQ_BALANCE_CELL1); eq_state = EQ_BALANCING; } break; case EQ_BALANCING: if (abs(diff) < EQ_STOP_OFFSET_MV) { // 持续200ms确认压差稳定再退出,防止瞬时干扰导致频繁开断 if (check_stable_200ms()) { set_balance_channel(EQ_DISABLE); eq_state = EQ_IDLE; } } break; default: // 延时冷却后复位到普通待机 if (wait_eq_cooldown()) { eq_state = EQ_IDLE; } break; } }这里的要点不是代码本身,而是启动阈值和停止阈值之间必须有迟滞。如果没有这个迟滞,压差在阈值边缘上下抖动时,均衡通道会以秒级频率反复开关,对 MOSFET 和电感都是一种冲击,极容易引起啸叫和过热。
4.4 均衡允许时间限制
主动均衡电路也不能无限时运行。电池在长期浮充状态下,压差可能永远也到不了绝对相等的理想状态,如果软件一直试图把压差压到 5mV 以下,均衡电路会一直发热,而且两侧电芯会在“微过充”和“微欠充”之间反复震荡。
我加了一个“单次均衡最长允许时间”,默认 15 分钟,超时后强制停止,等下一轮电压判断周期再决定是否继续。这样设计可以避免均衡通道长时间满载工作,也避免 MCU 逻辑因某种测量偏差陷入死循环。
EEPROM 里会记录每次均衡的开始时间、结束时间、起始压差、结束压差。虽然在单片机里做数据统计稍显基础,但有了这些数据,现场维护时能很快判断到底是哪个环节的问题,比靠维修人员盲猜高效得多。
4.5 低功耗模式与备用电源的长期待机
备用电源的一个关键指标是自身功耗。系统正常运行时,MCU 可以跑在低频运行模式,定时唤醒做一次电压巡检和均衡判断,然后继续睡眠。STM32L081CB 支持低功耗定时器唤醒,配合 RTC,可以把整机待机功耗控制在微安级别。
均衡动作只发生在充电期间或压差确异常时,平时 MCU 不必一直跑着 ADC 和状态机。这个思路跟消费电子完全不同,消费电子追求响应速度,备用电源追求的是停电后还能坚持监控多久。
5. 实测阶段:从调试台看到的“假均衡”与自激振荡
5.1 内部基准漂移带来的假均衡
第一版固件没有做 VDDA 补偿,直接用 3.3V 固定参考去换算电压。恰好在调试那几天实验室的交流供电电压偏低,电源适配器输出的 3.3V 实际只有 3.25V。计算结果整体偏移接近 2%,听起来不多,但在双串减法里,两节电芯经过分压、采样、减法后,误差叠加出来可能达到 30mV 以上。
这就出现了非常讽刺的现象:实际两节电芯压差只有 10mV,软件却算出 40mV,于是系统一直执行均衡,把本来很均衡的电池越搬越偏。直到我接上高精度台式万用表对照,才发现软件读数和真实电压差了很大。
解决问题就是增加 VREFINT 校准,并且每块板子出厂前做一次 ADC 偏置标定,把两点校准参数写进 EEPROM。之后软硬件的电压读数就能稳定在 ±5mV 以内,“假均衡”彻底消失。
5.2 均衡通道的自激振荡
主动均衡的本质是一个闭环电流控制。电流从高电压电芯搬向低电压电芯,搬归搬,低压电芯电压会升高,高压电芯会降低,压差逐渐减小。如果停止阈值设置得太靠近测量噪声区,就会出现一个典型的自激振荡:
压差 12mV 时软件停止均衡,但因为负载或自恢复效应,电压又回到 15mV,系统再次启动均衡。如此反复,均衡通道的开关频率变得不可控,电感开始发出可听见的啸叫。
我把停止阈值提高到 10mV 并加 200ms 稳定确认后,这个问题就消失了。后来在量产阶段也确认过,对磷酸铁锂这种放电曲线平台极平的电化学成分,追求 5mV 级别均衡没有实际意义,因为电池本身的开路电压与荷电状态对应关系在那一段非常平缓,电压差小不等于荷电状态已均衡,反而让系统一直处于紧张状态。阈值合理即可,留点余量。
5.3 连接器压降造成的假压差
备用电源系统的电池连接往往不是 PCB 直连,而是通过端子、线束、可能还有断路器接进去。如果采样点取在均衡电路板的连接器根部,而均衡电流又在同一路径上流进流出,大电流通过线束电阻产生的压降会被 ADC 当作电池电压的一部分。
0.5A 均衡电流在接触电阻 20mΩ 的连接器上就能产生 10mV 压降。这个值看似小,但足够干扰均衡判断。解决方法是“开尔文接法”:把采样线独立成两条细线,直接连接到电池端子附近,不让电流流过采样线路。这是很经典的技巧,但在小模块设计里经常被忽视。
实测中我碰到的现象是:均衡动作前后,软件读到的压差变化很大,但电池端用万用表量根本没那么大变化。排查后发现是采样路径和功率路径共用了一段 PCB 铜皮,跑铜皮上的压降进入了采样。这个教训也写进了硬件设计规范。
5.4 均衡效果的验证数据
我在实验室用两节同批次磷酸铁锂电芯做过一组对比测试。初始条件:一节充满至 3.62V,另一节放到 3.48V,压差 140mV。开启主动均衡后,均衡电流约 0.8A,20 分钟内压差降到 25mV,40 分钟到达 10mV 以内。同样条件下用 50mA 被动均衡,理论耗时需要超过 3 小时还没法真正搬移能量。
这个数据基本验证了主动均衡在该场景的价值:哪怕只有两串电池,能量搬移式的主动均衡能让系统在较短时间内回到健康状态,减少电芯长时间处于“被约束”的高压或低压区。
6. 走向现场:安全冗余、长期可靠与多串扩展视角
6.1 安全层级要明确:硬件保护优先级高于软件
这套系统最终会去长期无人值守的场合,我对安全层级的排序是:硬件保护第一,芯片内部保护第二,软件保护第三。
所谓硬件保护,就是不依赖 MCU 程序的固定电路行为。比如均衡使能脚上的下拉电阻,比如温度超限时直接断开的硬件比较器回路。这些动作即使软件跑飞、调试器还插着、看门狗失灵,也依然有效。
软件里不能只有“均衡策略”这一层,还要有独立的“运行健康检查”任务,周期检查 ADC 值是否合理、均衡通道是否异常导通、EEPROM 写入是否频繁到超寿命。一旦发现异常,第一时间切到故障等待状态,并把故障等级记录到日志里。
6.2 对“均衡不彻底”要保持平常心
很多刚接触均衡的人会陷入一个执念:必须把两节电池的电压差压到 1mV 以内才算均衡成功。实际上,考虑到电芯的自放电率差异和温度差异,这种“绝对均衡”本身就不存在,甚至还会造成不必要的循环损耗。
我最终的验收标准不是压差,而是“连续浮充三个月后,两节电芯的荷电状态差控制在 3% 以内”。只要这个目标达成,10mV 或 25mV 的电压差都可以接受。把目标定在正确维度上,固件和硬件选型都会轻松不少。
6.3 从双串到更多串:这套架构可以怎么复用
虽然标题里只说两串,实际做产品时我考虑的扩展方向是四串、六串甚至更多串储能簇。基于 MP2642GR-Z 加上 MCU 这套架构,扩展到多串时有两条路径。
一种路径是每两到三串配一个 MP2642GR-Z 通道,MCU 通过多通道控制实现逐组均衡。这种做法的优势是模块化强,均衡电流分散,散热压力小。另一种路径是使用带通信接口的均衡前端,由 STM32L081CB 统一管理,芯片之间的协作通过状态机调度。这里 MCU 的 EEPROM 依然可以承担均衡日志和校准数据的统一存储。
不管走哪条路,采样精度、迟滞阈值、温度保护、硬件优先关闭逻辑这几个设计原则都可以平移过去。底层跑通后,换电芯化学体系也只是调参数的事,架构不需要重写。
6.4 一个实际的体会
这套方案最终在样机上跑了 3 个月。说实话,最让我印象深刻的不是主动均衡把压差压得多快,而是排查假均衡问题时的思路转变。拿万用表实测电芯端子电压,和 MCU 软件读数比对,是每个做采样系统的人应该重复无数次的动作。均衡算法再漂亮,采样数据不对,算法就是建立在流沙上。
如果你也在做类似的双串电池管理,建议先把电压采样精度的校准和验证做扎实,再考虑要不要上主动均衡。很多时候不是芯片不够好,而是你还没把肉眼可见的数据弄准之前,就开始让芯片替你做判断了。