前一阵整理一套小型备用电源的主控板时,遇到一个绕不开的问题:两串磷酸铁锂电池出厂明明是配对的,跑了不到三个月,中间抽头两侧的电压差就跑到了 80mV 以上。如果放着不管,充电时电压高的那节电芯会先触发过压保护,整组电池的实际可用容量会越用越小。后来用 MP2642GR-Z 这颗主动均衡芯片配合 PIC18F45K42 单片机重新做了均衡控制,才把这个问题基本压住。这套方案很适合储能系统、小型 UPS、太阳能直流备用电源这类两串电池场景,本文就把硬件搭建、控制思路和调试过程完整拆开讲一讲。
1. 两串电池为什么会失衡,以及为什么必须主动处理
1.1 失衡的根源:容量、内阻与温度的相互放大
两节电池串联工作时,流过它们的电流完全相同。按说充进去、放出来的电荷量都一样,为什么电压会越来越不一致?
问题在于“电量相同”不等于“状态相同”。电池的实际容量会因为制造公差、循环老化而出现差异,内阻也会随温度和使用历史发生漂移。假设 B1 的实际容量只有 B2 的 95%,那么在放电时,同样的电流下 B1 的电量下降速度更快,端电压掉得更快;充电时 B1 又比 B2 更早到达充电上限。自放电率不一致也会在静置时逐渐拉开两者的荷电状态。温度的影响更加隐蔽,散热条件差的电芯温度更高,内阻更低,反而更容易过充,形成恶心循环。
拿水桶来类比会更直观:两个水桶并排放,用同一根水管同时注水和放水,但桶底裂缝大小不同、桶的直径也不同,注入相同水量后,水位必然一高一低。一个已经溢出来了,另一个可能还没满。电池组里的“溢出”,就是过充。
1.2 不平衡带来的实际后果
最直接的影响是整组电池的可用容量被最差的那节电池锁死。充电时只要有一节电芯到达电压上限,充电器就必须停机,另一节电芯即使还没充满也只能陪跑。放电时同样如此,电压最低的电芯先触底,整个系统便无法继续供电。
长期过充会带来正极材料结构破坏、电解液氧化分解,甚至析锂;长期过放会造成负极铜箔溶解、容量不可逆衰减。对于备用电源来说,设备长期挂在浮充状态,静置时间远大于工作时间,自放电差异会持续累积电压偏差,如果不做均衡,电池组寿命会明显缩短。
1.3 被动均衡与主动均衡的取舍
传统做法是给每节电芯并联一个放电电阻,充电时把电压高的电芯多余电量以热量形式耗散掉,也就是被动均衡。它电路简单、成本低,但有两个明显缺点:一是发热集中,电池仓散热压力大;二是只能“放掉”,不能把能量转移给低电量电芯,均衡效率不高,放电和静置状态下基本无法工作。
主动均衡则不同,它通过功率变换电路把高电量电芯的能量搬运到低电量电芯,能量没有被浪费,发热也小得多。MP2642GR-Z 就是一颗专门做两节串联电池主动均衡的芯片,再加上一颗 PIC18F45K42 做系统监控和策略控制,就能实现一套比较完整的电池均衡系统。
2. MP2642GR-Z 的工作原理与硬件搭建要点
2.1 电感电荷搬运:一次均衡周期里发生了什么
MP2642GR-Z 的核心工作方式可以理解为电感电荷搬运。芯片内部集成了功率开关管,外部只需要一颗储能电感,就能在 B1 和 B2 之间双向转移电荷。
如果 B1 电压比 B2 高,芯片内部会让电感从 B1 侧储能,再把储存的能量释放到 B2 侧。这个过程以一定频率反复进行,每个周期搬运一小份电荷,宏观上就形成了一股从 B1 流向 B2 的均衡电流。反过来,如果 B2 电压高于 B1,功率级就反向工作,电感从 B2 汲取能量,向 B1 释放。
这种拓扑相当于一个双向 Buck-Boost 变换器,芯片内部的开关管替代了分立方案里的 MOSFET,驱动、逻辑控制、电压检测都集成在芯片内部,外部电路非常简洁。均衡电流大小由电感量、开关频率和占空比共同决定,芯片会通过内部协议限制最大电流,防止电感失控饱和。
2.2 围绕 MP2642GR-Z 的最小系统连接
搭建最小系统时,第一步要把两节串联电池的节点接到 MP2642 对应的检测端和功率端。典型接法是:B1 正极接电池组正极,B1 负极/B2 正极作为中间抽头,B2 负极接电池组负极地。外部电感接在芯片的开关节点和中间抽头之间,芯片的电源端和检测端分别跨接两个电芯。
I2C 接口只需要两根线,SDA 和 SCL 分别接 PIC18F45K42 的对应引脚。两条线都要接上拉电阻,阻值一般取 2.2kΩ 到 4.7kΩ,具体取决于总线电容和通信速率。芯片的 EN 使能引脚由单片机控制,FAULT 开漏输出引脚接单片机的外部中断或者普通 IO,用于上报异常。
我比较坚持的一点是:电池组的采样线要尽量短,并且从电池端子独立引出,不要在 PCB 上和其他功率走线共享。因为均衡电流会带来地电位偏移,共享走线会污染电压检测结果,影响均衡判断。
2.3 电感、电容与 PCB 布局的实战选择
电感是这套方案里最重要的磁性元件。电感量太小时,均衡纹波电流大,开关管应力高;电感量太大,均衡电流上不去。以 0.5A 级别的均衡电流为例,4.7µH 到 22µH 都是常见取值,但必须确认电感的饱和电流高于均衡电流峰值,否则均衡电流一旦增大,电感量会断崖式下跌,芯片会误判甚至过流。
我在样板上来回换过几次电感,最后选了饱和电流 2A 以上、DCR 尽量小的一颗功率电感。DCR 太大会白损耗能量,发热也会从芯片转移到电感上。电容选择上,输入和输出端各放一颗低 ESR 陶瓷电容,容量不需要太大,几微法到二十几微法都可以,靠近芯片引脚放置。
PCB 布局方面,开关节点是 di/dt 最大的地方,走线必须短而粗,尽量减少回路面积。不要把 I2C 线平行贴着开关节点走,否则 SDA 上会看到明显的开关噪声。电池电压采样走线可以考虑在单片机侧加一组 RC 滤波,时间常数大约 1ms 到 10ms,不影响均衡判断速度,但能滤掉不少开关纹波。
3. PIC18F45K42 在系统里的三层职责
3.1 选型逻辑:为什么不是随便拿一颗 MCU 应付
MP2642GR-Z 自己就能完成基本的功率级均衡,那为什么还要加一颗 PIC18F45K42?因为实际产品里需要的不只是“搬电”,还需要系统级的判断和保护。
PIC18F45K42 的集成外设在处理这类任务时非常顺手。它自带多路 IOC、I2C 主模式、ADC 模块、DAC 模块、窗口比较器等,不需要额外加独立 ADC 或比较器芯片。单片机可以直接通过内部 5V 供电运行,IO 电平与 MP2642 的逻辑电平匹配,省掉了电平转换电路。
另外这系列单片机的引脚映射功能很有用,外部中断、I2C、定时器都可以分配到不同引脚,画 PCB 时布线自由度更高。做均衡控制并不需要很强的算力,关键是外设搭配合理、休眠功耗低、温度范围宽,这些正是它擅长的事情。
3.2 I2C 通信与寄存器读写示例
MP2642 通过 I2C 接口把两个电芯的电压、芯片状态、故障标志交给单片机,同时接收单片机的启动、停止、模式配置命令。单片机作为主设备,在初始化阶段完成 I2C 外设配置,速率建议先用 100kHz 跑通,再视情况提升到 400kHz。
#include <xc.h> #define MP2642_ADDR 0x60 // 实际地址以芯片手册为准 #define MP2642_REG_CTRL 0x00 #define MP2642_REG_VCELL1 0x02 #define MP2642_REG_VCELL2 0x04 #define MP2642_REG_STATUS 0x06 void i2c_write_reg(uint8_t reg, uint8_t val) { i2c_start(); i2c_write((MP2642_ADDR << 1) | 0); i2c_write(reg); i2c_write(val); i2c_stop(); } uint8_t i2c_read_reg(uint8_t reg) { uint8_t val; i2c_start(); i2c_write((MP2642_ADDR << 1) | 0); i2c_write(reg); i2c_restart(); i2c_write((MP2642_ADDR << 1) | 1); val = i2c_read(0); // 最后一个字节回 NACK i2c_stop(); return val; }这里特意把“读最后一个字节时回 NACK”写了出来,因为这是 I2C 通信最常见的卡壳点。如果读时序不对,单片机会一直收不到完整寄存器数据。
3.3 模拟量采集与均衡使能控制
I2C 只能拿到电芯电压和芯片状态,系统温度、总包电压这些信息还是得靠单片机 ADC 采集。我在电池附近放了一个 NTC 热敏电阻,通过分压网络接到 PIC18F45K42 的 ADC 引脚,每隔几百毫秒读一次温度。温度超过 55°C 时禁止启动均衡,超过 65°C 时强制关闭均衡。
EN 引脚的控制逻辑也要注意细节。上电阶段需要先让单片机完成初始化、读一次电池电压,确认没有过压故障后再把 EN 拉高。如果上电瞬间就拉高 EN,芯片会在电压检测尚未稳定时开始工作,容易产生一次不必要的大电流冲击。
FAULT 引脚建议连接到单片机的外部中断引脚,同时开启内部弱上拉。FAULT 一旦拉低,单片机立即进入故障处理状态,而不是等着下一次轮询才发现问题。测试中发现,轮询间隔 500ms 时,FAULT 导致的问题往往会延迟一个周期才被处理,对于电池保护来说这个时间太长了。
4. 均衡策略与状态机:别让电压搬运器傻跑
4.1 何时均衡、何时停止、何时强制禁止
均衡不是电压差超过 0V 就一直开着,那样反而会引入不必要的循环损耗。实际策略需要设定开启阈值、关闭阈值和禁止条件。
我用的参数供参考:电芯静置电压读取,压差大于 20mV 时开启均衡,压差降到 10mV 以下时停止;充电过程中允许均衡,但均衡电流要限制得比充电电流小;放电状态下只在轻载时均衡,重载时关闭。禁止条件包括:总电压超过过压保护点、单节电压超过 3.65V(磷酸铁锂上限)、温度越限、均衡连续运行超过设定时间。
设置回差的目的是避免均衡控制频繁启停。如果没有回差,压差在阈值附近抖动时,芯片会反复启动和停止,每次启动都会带来一次电感电流冲击,长期看对器件寿命不利。
4.2 状态机划分与迁移条件
软件结构拆成几个状态:待机、电压检查、均衡中、故障、故障锁存。状态转移逻辑不复杂,但必须把所有异常路径都处理干净。
typedef enum { ST_IDLE, ST_VOLTAGE_CHECK, ST_BALANCING, ST_FAULT, ST_FAULT_LATCH } sys_state_t; sys_state_t current_state = ST_IDLE; void state_machine(void) { uint16_t v1 = read_cell_voltage(MP2642_REG_VCELL1); uint16_t v2 = read_cell_voltage(MP2642_REG_VCELL2); int16_t diff = (int16_t)(v1 - v2); switch (current_state) { case ST_IDLE: if (voltage_valid(v1, v2)) { current_state = ST_VOLTAGE_CHECK; } break; case ST_VOLTAGE_CHECK: if (abs(diff) > BAL_ON_MV) { enable_balancer(); current_state = ST_BALANCING; } else { current_state = ST_IDLE; } break; case ST_BALANCING: if (fault_flag) { disable_balancer(); current_state = ST_FAULT; } else if (abs(diff) < BAL_OFF_MV) { disable_balancer(); current_state = ST_IDLE; } break; case ST_FAULT: fault_flag_reset(); current_state = ST_FAULT_LATCH; break; case ST_FAULT_LATCH: // 等待人工复位或断电重启后才可恢复 break; } }故障锁存状态是必须的。一旦发生过压、过温这类危险故障,系统不能自己悄悄恢复正常,否则故障源还在,反复进入故障状态反而会让 MOSFET 和电感承受更大压力。维护人员通过按键或者上位机指令才能清除锁存,这样更安全。
4.3 故障保护与 I2C 看门狗
芯片自带的 FAULT 引脚只能反映芯片内部的异常,系统级的过压、欠压、过温还需要单片机结合 ADC 采样综合判断。最常见的是充电状态下的过压风险:如果 B1 电压已经接近 3.6V,B2 还在 3.4V,这时开启均衡虽然能拉低 B1,但如果充电电流远大于均衡电流,B1 的电压依然会继续上升。因此充电时的策略是:检测到任意单节电压超过 3.55V,先把充电回路断开,再做均衡,而不是边充边搬。
I2C 通信也可能失效。MP2642 万一内部总线卡住,单片机必须能发现。我在主循环里加了一个“通信看门狗”:如果连续 5 次读取寄存器都没有收到有效应答,就判定通信异常,关闭均衡并进入故障锁存。这个逻辑成本很低,但能避免单片机因 I2C 卡死而失去对均衡器的控制。
5. 实测定标与调试中踩过的坑
5.1 测试平台与数据记录
搭建了一套简易测试台:两节磷酸铁锂电池,实际容量 6Ah 左右,先故意放电制造约 80mV 的压差,然后连接均衡板,静置状态下观察电压变化。测试过程中用万用表定期记录中间抽头两侧电压,同时读单片机内部寄存器里的均衡状态。
一组比较典型的数据:
| 时间(分钟) | B1 电压(V) | B2 电压(V) | 压差(mV) | 均衡状态 |
|---|---|---|---|---|
| 0 | 3.312 | 3.230 | 82 | 未启动 |
| 1 | 3.310 | 3.235 | 75 | 均衡中 |
| 5 | 3.305 | 3.249 | 56 | 均衡中 |
| 15 | 3.293 | 3.270 | 23 | 均衡中 |
| 25 | 3.287 | 3.278 | 9 | 均衡停止 |
均衡电流大约 0.5A,从 82mV 压差收敛到 10mV 以内,花费了二十多分钟。对备用电源场景来说,这个速度完全可以接受,毕竟设备大多数时间都在静置,并不赶时间。
5.2 三个高频问题:I2C 波形、SW 节点振铃、均衡电流偏小
第一个遇到的坑是 I2C 通信时好时坏。用示波器看 SDA 波形,上升沿很缓,像是被电容拖住了。排查下来是上拉电阻取了 10kΩ,总线电容又偏高,导致边沿不达标。把上拉电阻换成 2.2kΩ,并且把 I2C 连线缩短到 10cm 以内,问题消失。
第二个问题是开关节点 SW 的电压振铃。均衡电流切换到续流阶段时,SW 节点会看到明显的高频阻尼振荡,振铃峰值接近电池电压的两倍。处理方法是加了一个 RC 吸收电路,电阻 10Ω、电容 1nF,放在开关节点对地之间,振铃明显收住。这也是电源设计里的老办法,虽然会损耗一点效率,但换来的是更低的 EMI 风险。
第三个问题比较隐蔽:均衡电流比理论值小了不少。检查发现,我用的电感额定电流其实标的是 1.5A 峰值,但均衡电流波动峰值已经接近电感饱和临界点,电感量下降导致电流上不去。换成饱和电流 2.5A 以上的电感后,均衡电流恢复正常。选电感时不能只看平均电流,还要看峰值电流和纹波电流叠加后的最大值。
5.3 从“能均衡”到“可靠均衡”的改进记录
最初版本只在压差超过阈值时启动均衡,压差回来就停止。实测过程中发现两个问题:一是电池从放电状态进入静置后,电压会有一个缓慢的回弹过程,如果立刻做均衡判断,很容易被这个动态过程误导;二是均衡停止后,电池电压仍然会缓慢变化,可能出现刚停止又满足启动条件的情况。
改进措施是引入“稳定等待”逻辑:进入静置状态后,先等待 5 分钟,连续读取三次电压,每次间隔 1 秒,确认压差方向稳定后再决定是否开启均衡。停止均衡时也一样,确认压差连续 30 秒低于关闭阈值才真正关断。这样虽然少了一些均衡时间,但避免了无效启停和误动作,系统整体稳定性明显提升。
另外还加了一条“均衡超时保护”:无论压差是否恢复到目标范围,单次均衡最多持续 60 分钟,到点必须停止并重新评估。这是为了防止某些极端情况下均衡一直无法收敛,芯片长时间满载工作带来发热风险。事后复盘,这条超时保护在后期测试中确实多次派上用场,至少三次避免了故障状态下的持续搬运。
最后分享一个我调试这套均衡系统时的习惯:永远不要让均衡器在单片机完全失控的情况下工作。每次修改软件后,先跑一遍故障注入,人为模拟过压、温度异常、I2C 断开,确认系统都能在几百毫秒内关闭均衡并进入锁存状态,再去做长期均衡测试。电池系统的可靠性往往不是来自均衡效率,而是来自边界条件下的自我保护能力。