前段时间在做一台家用户外储能备电系统的电池管理部分,最让我头疼的就是电池包里那两节串联磷酸铁锂的电压差。系统平时由适配器或光伏输入充电,两节电池串成一组,理论上走的是同一个充电电流回路,但用不了多久,充电末端两节电池的电压差就会逼近 80mV。为了把压差压到 30mV 以内,我最终采用了 MP2642GR-Z 充电管理芯片加 PIC18F46K42 主控的组合,把两节串联电池的充电管理和均衡逻辑完整做了一遍。整套方案从选型、硬件、固件到联调,踩了不少坑,也总结出不少可复用的经验,这里完整记录下来,给正在做储能、备用电源或 2S 电池包均衡的工程师做个参考。
1. 这个项目要解决什么问题:串联电池的"木桶效应"与均衡的必要性
1.1 两节串联电池为什么会越用越不一致
我实际使用的电池是两节 32650 规格磷酸铁锂,单节标称容量 6Ah,组成 2S1P 电池包后标称电压 6.4V。刚装配时我特意测量过两节电池的开路电压,差距不到 3mV,内阻差异也控制在 3mΩ 以内。当时我一度认为,串联电池均衡只是产品说明书上的一个名词,实际做起来应该不会太难。结果循环二十几次之后,充电末端两节电池的电压差就能到 80mV,这让我意识到必须认真对待。
两节电池串联在一起,回路中流过的充电电流完全一致,但每节电池实际接收到的电荷量并不相同。决定"谁多充一点、谁少充一点"的因素主要有四个:
- 内阻不一致:内阻偏大的那节在充电时端电压上升更快,更容易先碰到截止电压,但真实充进去的电量反而少;
- 容量不一致:容量偏小的那节相对更快充满,大电流充电时这个差异会被进一步放大;
- 自放电率不一致:即使静置不工作,每节电池每天自己漏掉的电量也不同,自放电大的那节下轮充电时会先吸收电流去补亏空;
- 温度分布不一致:电池组里靠近发热元件的那节电池,内部化学反应速率更快,充放电特性也会偏移。
这些差异在出厂时就有,循环使用后还会逐渐累积。电池老化不是同步的,所以"新电池压差小、旧电池压差越来越大"几乎是必然规律。想在源头上完全消除差异不现实,能做的就是靠均衡把差异控制在不影响系统工作的范围内。
1.2 不均衡在储能/备用电源中的放大后果
如果只是做低成本的消费类产品,压差大一点也许影响不明显。但储能和备用电源恰好是最不能忍受电压差的场景。
先看放电。两节电池串联向外放电,哪节电压低就先到放电截止电压。为了不让电池过放,主控必须切断整个回路。这时候电压高的那节其实还有不少剩余容量,但已经放不出来了。备用电源在市电断电的瞬间需要立刻顶上,如果某节电池在静置期间被自放电拖到过低电压,整个系统的备电时间会直接缩水一大截。
再看充电。充电时电压高的那节先到截止电压。如果保护逻辑简单,直接停止充电,那电压低的那节永远充不满;如果继续充,先满的那节就会过充。磷酸铁锂体系过充到一定程度会析锂、产气,直接影响安全,这个风险必须堵死。
还有一个容易被忽略的地方是长期浮充场景。备用电源通常常年插电在线,电池长期处于满充或接近满充状态。此时哪怕压差只有 20mV,长期下来,容量偏低的那节电池也会一直承受相对更高的电压,加速老化和气体析出。日积月累,整个电池包的寿命会明显变短。
因此我在项目里定了几个很直接的目标:
- 充电过程中,两节电池压差稳定控制在 30mV 以内;
- 静置 24 小时后压差不超过 20mV,若超过则自动进入维护均衡;
- 具备过充、过放、过流、过温保护,异常时 MCU 主动切断充电并上报状态。
1.3 设计目标与选型思路
围绕这几个目标,我在选型时对比了三种方案:纯模拟均衡芯片方案、纯 MCU 方案、MCU 加充电管理芯片方案。
纯模拟芯片方案的均衡阈值和时序通常是固定的,应对两节电池没问题,但以后想换电池化学体系或调整均衡策略,就得重新设计换芯片,灵活性太差。
纯 MCU 方案则是让单片机直接做降压充电控制,既要管环路补偿,又要做电流检测和电感控制,工作量很大,风险也高,不适合快速出项目。
最后定下来的是第三种:MP2642GR-Z 负责充电管理和电池电压监测,PIC18F46K42 负责整体策略控制和均衡执行。
选 MP2642GR-Z,是因为它面向 2 节串联电池应用,充电电压、充电电流都能通过 I2C 配置,还带输入限流和电池温度检测相关引脚。充电环路这种容易出问题的部分交给成熟芯片,MCU 只负责决策和控制,工程风险大大降低。
选 PIC18F46K42,是因为它带硬件 I2C 模块、12 位 ADC、多个 PWM 输出,还支持低功耗睡眠。备用电源大部分时间在线待机,MCU 休眠电流只有微安级别,这对整机待机功耗非常关键。再加上这类芯片的资料和例程丰富,遇到问题能快速排查。
下面按硬件、固件、联调和场景适配的顺序,把这套系统的具体做法拆开讲。
2. 系统硬件搭建:从电池包到 MP2642GR-Z 再到 PIC18F46K42 的信号链路
2.1 整体信号链路
系统里的主要节点包括:电源输入、MP2642GR-Z、电池包、PIC18F46K42 和均衡执行电路。
电源输入来自 12V 适配器或光伏输出,经过 MP2642GR-Z 的降压环路给电池包充电。MP2642GR-Z 自身引脚直接检测电池包正极、中间点和负极,因此它知道每一节电池的电压情况。
PIC18F46K42 和 MP2642GR-Z 之间通过 I2C 连接。MCU 周期性读取电压、电流、状态寄存器,写入充电目标电压和充电电流等参数。同时,MCU 自己的 ADC 还接了一组分压电阻直接采样每节电池电压。这不是冗余设计,而是必要的校验手段:如果 I2C 读回的数据和 ADC 采样结果偏差过大,说明某一边出了问题,系统应当报警而不是继续充放电。
两节电池正极与中间点之间、中间点与负极之间,各并联一路均衡放电回路。每路由一个 P 沟道 MOSFET 和一个功率电阻串联组成,MCU 用 PWM 或 GPIO 控制开关。哪节电池电压高,就把它的多余电量通过电阻定时放掉。
整个系统共地,MP2642GR-Z 的 GND、电池负极、MCU 的 GND 都连在一起。这里必须强调,芯片地到电池负端的走线要短、要粗。大电流在 PCB 地线上产生的压降会让芯片检测电压偏离实际值,这是很多电源类项目量产后才发现的问题。
2.2 MP2642GR-Z 周边电路设计
MP2642GR-Z 周边元件不算多,但每颗电容电阻的位置都有讲究。
输入侧我用了 10µF 陶瓷电容和 0.1µF 高频去耦电容并联,紧贴芯片 VIN 引脚。这个位置不能省,降压充电芯片的输入电流是断续的,输入电容一旦离远,环路稳定性就会受影响,严重时会出现振荡。
电感按芯片手册推荐的电流纹波率选型,我最后用了 6.8µH、额定电流 2A 的一体成型电感。电感的饱和电流一定要大于最大充电电流加纹波裕量,否则大电流下电感值会下降,纹波电流飙升,发热和噪声都会变大。
电池电压采样引脚最好从电池端子直接引出,不要和其他大电流走线共用铜箔。我加了一颗 1kΩ 串联电阻和一颗 100nF 对地电容做 RC 滤波,时间常数很小,不影响采样实时性,但能明显抑制开关噪声。
充电电流检测我用了一颗 10mΩ、1% 精度的合金检流电阻。这里有个容易被忽略的点:检流电阻的温度系数非常关键。普通厚膜电阻在大电流下发热后阻值会漂移,MCU 读到的电流和实际电流能差 5% 以上。换成合金电阻后,温漂明显改善,电流读数稳定很多。
温度检测用一颗 10kΩ NTC,贴在电池侧面并用胶固定。NTC 和电池之间不要垫太厚的绝缘胶带,否则热传导变慢,过温保护可能形同虚设。
2.3 PIC18F46K42 的采样与均衡执行电路
PIC18F46K42 的供电和 ADC 参考电压都是 3.3V。电池包最高电压在磷酸铁锂体系下约 3.65V 乘 2 等于 7.3V,不能直接进 ADC,必须先分压。
我用的分压网络是 100kΩ 对 47kΩ,分压比约 0.32。7.3V 对应 ADC 输入约 2.3V,留了 1V 以上裕量。两颗电阻都选 1% 精度,而且为了两节电池的采样比例一致,我特意挑了同一批次的电阻,避免分压比差异引入额外误差。
分压网络之后加了一颗 1µF 采样电容,配合 MCU ADC 内部的采样保持器,能有效降低源阻抗带来的采样误差。这颗电容不能省,否则 ADC 读数会偏低且抖动明显。
均衡执行电路是容易翻车的地方。我第一版用了 N 沟道 MOSFET 做低边开关,结果发现均衡电阻接在电池中间点和负极之间没问题,但接在正极和中间点之间时,N-MOSFET 需要栅极电压高于电池正极才能完全导通,MCU 的 3.3V 根本驱动不了。后来改成 P 沟道 MOSFET 加简单电平转换电路,MCU 输出低电平时导通。这个细节如果不提前考虑,就得飞线返工。
均衡电阻我选了 10Ω、2W 的功率电阻。按最恶劣情况计算,电池端电压 3.6V 时,均衡电流能达到 360mA,电阻瞬时功耗约 1.3W。2W 的功率余量够用,但发热不小。布局时我把均衡电阻放在电池包外侧,对应区域的 PCB 铺铜帮助散热,并远离 NTC。
2.4 实际焊接与布局中的注意点
这一部分经验是返工两次换来的,单独拎出来说。
第一,采样线要用开尔文接法。我第一版 PCB 把电池电压采样点画在了大电流走线上。充电电流 1A 时,采样点附近地线压降有 30mV 左右,MCU 读到的电压和万用表测到的电池端子电压差很多,均衡逻辑被错误数据带着跑。后来把采样线从电池接线端子根部单独引出,问题才解决。
第二,MP2642GR-Z 的散热焊盘必须接大块铜皮。虽然充电芯片效率不低,但 1A 充电时损耗也有几百毫瓦。散热面积不够会触发内部过温保护,表现为充电电流突然掉下来,排查起来很费劲。
第三,均衡电阻不要贴电池太近。均衡电阻工作几分钟表面温度就能到六七十度,贴着电池会拉高电池温度,NTC 可能误报过温,电池本身也会加速老化。
第四,MCU 的 I2C 上拉电阻不能省。有些评估板内部自带上拉,容易让人形成路径依赖。自己画 PCB 时不加上拉,I2C 在稍长的走线下通信很不稳定,会间歇性丢字节。我用 2.2kΩ 电阻上拉到 3.3V,100kHz 和 400kHz 速率都实测通过。
3. 固件逻辑:PIC18F46K42 怎样"管"住 MP2642GR-Z
3.1 I2C 初始化与读写封装
PIC18F46K42 的 I2C 外设配置相对简单,主模式只需设置波特率和使能模块。我习惯先写一个底层读写函数,上层所有与 MP2642GR-Z 相关的操作都封装在这两个函数里。
I2C 通信最容易出错的是地址格式。芯片手册里给出的地址通常是 7 位地址,但代码里真正发送的字节是"地址左移一位再加读写位"。我第一次直接把 7 位地址当 8 位地址发出去,结果对方完全没有 ACK。排查了很久才发现是地址格式搞错了。所以初始化完成后,第一件事是读取芯片的 ID 或版本寄存器,能稳定读回固定值,才说明通信链路真正建立。
// I2C 写寄存器封装示例 // 具体寄存器地址与器件地址请以数据手册为准 uint8_t mps_write_reg(uint8_t reg_addr, uint8_t val) { i2c_start(); if (i2c_write(MP2642_ADDR_W)) { // 写地址 i2c_stop(); return 1; } if (i2c_write(reg_addr)) { i2c_stop(); return 1; } if (i2c_write(val)) { i2c_stop(); return 1; } i2c_stop(); return 0; }完整通信逻辑我还加了超时和重试机制。I2C 偶尔会因为噪声产生 NACK,或从机内部忙而不响应。我设置的策略是每笔读写最多重试三次,重试间隔 2ms,连续失败就上报通信故障,让系统进入保护状态,而不是带着错误参数继续充放电。
3.2 充电参数配置
MP2642GR-Z 的充电参数配置,我按下面的流程处理:
- 上电后先将芯片置于待机状态,不立即开始充电;
- 读取 ID 寄存器,确认通信正常;
- 配置输入限流,按适配器能力设置为 1.5A;
- 配置充电目标电压,磷酸铁锂两节串联设置为 3.65V 乘 2,也就是 7.3V;
- 配置充电电流为 1A;
- 配置充电截止电流为 100mA,充电电流降到该值即认为充满;
- 使能充电,回读所有配置寄存器确认写入值正确。
这里要特别提醒,目标电压不能只填一个总电压。两节电池串联时,芯片必须同时知道中间点电压。所以在电池包正极、中间点、负极三根线都接好之前,不要使能充电。我第一次只接了两根线做调试,芯片读不到中间点电位,状态寄存器直接报错。
磷酸铁锂和三元锂离子电池的充电截止电压差别很大,同一个充电芯片靠配置寄存器区分。我的板子电池类型固定,所以直接把配置写死在初始化里。如果产品要兼容两种电池体系,需要用 MCU 引脚或外部存储芯片切换配置,而不是只靠软件默认值。
3.3 均衡策略状态机
均衡不是上电就一直开。一直开均衡意味着一直耗电、一直发热,备用电源场景完全不能接受。我把均衡逻辑做成了状态机。
系统状态分为四类:
- IDLE:空闲态,不充电不放电不均衡,MCU 进入低功耗睡眠,每 24 小时被定时器唤醒一次检测电压差;
- CHARGING:充电态,MP2642GR-Z 正在充电,MCU 周期性读取两节电池电压,若压差超过 30mV 且高电压侧已接近满充,切入均衡态;
- BALANCING:均衡态,只对电压高的那节电池打开放电回路,用 50% 占空比的 PWM 控制均衡 MOSFET,限制平均均衡电流,每 10 秒检测一次压差,压差小于 10mV 并保持 30 秒后回到充电态;
- FAULT:故障态,任一电池电压超限、温度超限、通信异常时进入,关闭充电和均衡,并上报故障。
为什么均衡要在充电末端做,而不是一开始就做?原因是电池的电压容量曲线在平台区非常平缓,磷酸铁锂尤其明显。在平台期,几 mV 的电压差根本反映不出真实容量差异,做了均衡也起不到作用。到了充电末端,电压随充电深度快速上升,谁的容量小、谁充得快立刻一目了然。这时对电压高的电池放电,才能真正让两节电池在同一时刻充满。
放电末端也一样。如果放电过程中出现压差,更适合在放电结束后、静置期间做补充均衡。放电过程中做均衡意义不大,因为放电本身就是在缩小容量差,额外放电反而可能导致低电压侧先触及截止值。
均衡 PWM 占空比不建议直接拉满到 100%。持续大电流放电会把电池端电压直接拉低,MCU 会误以为电池电压已经正常,实际上 SOC 差异没被拉平。用 50% 占空比配合 10 秒周期的检测,能让电池在放电间隙恢复极化电压,电压读数和均衡效果都更真实。
3.4 电压/温度采样与滤波
PIC18F46K42 的 ADC 是 12 位,理论分辨率足够,但实际采样值抖动比较大。原因有两个:一是充电过程中电池电压本身有波动,二是分压网络输出阻抗偏高。
我采用的滤波策略是:每个通道连续采集 16 次,去掉最大值和最小值,剩余 14 次取平均。这样既能滤掉尖峰,又不会像单纯滑动平均那样反应迟钝。滤波后再做一次过采样处理,等效分辨率还能再提高一点。
另一个容易被忽略的点是 ADC 参考电压来源。如果直接用 3.3V LDO 输出做参考,LDO 的精度和温漂都会直接变成采样误差。我在产品里用了精度 1% 的电压基准源,或者至少用 0.1% 精度的电阻分压后接到 MCU 的 VREF+ 引脚。储能产品对采样误差敏感,这一处不能省。
温度采样相对简单,NTC 电阻和固定电阻分压后进 ADC。我用查表法把 ADC 值换算成温度,注意 NTC 的 B 值必须和实际物料对应,否则 40°C 之后的误差会越来越大。
4. 联调过程中的实测数据与反复调整
4.1 第一次上电:I2C 读不到寄存器值
第一版硬件焊好后上电,MCU 的 I2C 扫描函数直接返回失败,收不到任何 ACK。
我先用示波器钩住 SCL 和 SDA。波形显示 SCL 有正常的沿,但 SDA 在地址阶段的表现和预期不符。核对代码才发现问题出在地址位拼写上:我把 7 位地址左移一位之后又补了一个额外的位,相当于把地址错了一倍。这是非常低级但很常见的 I2C 地址翻车现场。
修正地址格式后,通信立刻正常,读回 ID 寄存器值稳定。这个教训让我在后续代码里加了一个开机自检流程:ID 读不对就直接报通信故障,不进入充电流程。这个自检看起来简单,但能挡住芯片虚焊、地址位顺序错误、上拉电阻缺失等一连串隐蔽问题。
4.2 充电电流和预期不符
配置完成后真正开始充电,第二个问题浮现。寄存器里设置充电电流 1A,但实测只有 400mA 左右。
我先回读配置寄存器,确认写入正确。再检查检流电阻,用万用表分别测电阻两端电压和回路电流,发现电阻值正常。最后排查到输入侧:适配器带载后电压从 12V 掉到 10.8V。虽然芯片在宽输入电压范围内都能工作,但输入限流优先,输入电流受限后,充电电流自然上不去。
换成输出能力更强、带载压降更小的适配器后,充电电流恢复到了 900mA 以上。这个案例说明,配置寄存器和硬件实际能力是两个维度。MCU 读回的状态只是芯片的期望值,真实电流还取决于输入电源和电池状态。
同一次调试中,我还发现 ADC 读到的充电电压持续比万用表高 30mV。量了 PCB 地线,问题来自充电电流在地线铜箔上产生的压降,MCU 的参考地和电池负极电位不一致。最终是通过修改 PCB 布线解决的。前期调试时我暂时用软件校准处理,按电流比例扣除地线压降,但量产前必须改板,软件补偿不能长期兜底。
4.3 均衡效果实测
均衡逻辑调好后,我做了模拟实验:把两节电池分别充到不同状态,人为制造约 60mV 压差,然后开启充电均衡。
实测数据如下:
| 时间点 | BAT1 电压 | BAT2 电压 | 压差 | 状态 |
|---|---|---|---|---|
| 均衡开启前 | 3.520V | 3.460V | 60mV | 人为制造不均衡 |
| 均衡开启 3 分钟 | 3.500V | 3.470V | 30mV | 均衡工作正常 |
| 均衡开启 6 分钟 | 3.490V | 3.480V | 10mV | 达到收敛条件 |
| 关闭均衡后 | 3.490V | 3.485V | 5mV | 进入正常充电 |
从曲线看,均衡电阻把高电压侧的多余电量转化为热量,低电压侧继续以正常电流充电,两节电池的电量差距被逐步抹平。整个过程中,均衡电阻表面温度从室温升到约 45°C,属于可接受范围。
但我也发现,只靠充电末端均衡无法彻底解决自放电率差异。充满电静置 24 小时再测,压差又回到 25mV 左右。这说明均衡不能只做一次,备用电源场景必须周期性维护。后来我加入了每 24 小时自动唤醒巡检的功能,压差超过阈值就启动维护均衡。实测长期运行下,电池组的压差能稳定在 15mV 以内。
4.4 功耗与热设计
均衡电阻的功耗和温升,是选择均衡方案时必须算清楚的账。
以 10Ω 电阻为例。假设均衡开启时电池电压 3.5V,单电阻功耗约是 3.5 的平方除以 10,也就是 1.2W。电池电压回落到 3.3V 时,功耗降到 1.1W。日常均衡状态下电阻功耗在 1W 左右,短时间不会超过 2W 额定值。但如果电池异常,电压冲到 3.8V,功耗会到 1.4W,长期工作温度会偏高。
所以均衡控制必须加两条保护:一是 PWM 限流,把平均功耗控制在 700mW 以内;二是 NTC 温度超过 55°C 时暂停均衡,等温度降下来再继续。这两条看似简单,对长期可靠性帮助很大。
如果后续电池容量做大,需要更大的均衡电流,建议直接上主动均衡。主动均衡通过电容或电感把能量从高电压电池转移到低电压电池,而不是把能量全部变热,效率和温升表现都好得多。代价是电路复杂度和成本上升。小容量两节电池用被动均衡完全够用,没必要一开始就上主动均衡。
5. 在储能/备用电源场景下的特殊考量
5.1 备用电源长期静置后的均衡策略
备用电源和消费电子最大的区别,就在于它大部分时间不干活。电池长时间搁置,自放电差异会慢慢累积,真正需要放电时才发现容量不够。所以必须有一套"静置维护"机制。
我的做法是:MCU 进入低功耗休眠,用外部 32.768kHz 晶振驱动的定时器保持计时,每 24 小时唤醒一次。唤醒后打开 ADC 电源,采样两节电池电压并计算压差。压差大于 30mV 时开启均衡 15 分钟,然后再次检测;压差小于 20mV 就继续休眠。整个巡检过程功耗很低,对电池容量几乎没有影响。
静置维护还有一个容易漏掉的细节:如果电池已经因自放电被拖到过放保护阈值以下,不能盲目均衡。我在逻辑里加了一步判断,电池电压低于 2.8V 时不开启均衡,先把系统切换到小电流恢复充电模式,等电压回到安全区间再正常处理。
5.2 与上位机/管理系统的数据交互
储能系统通常需要一个上位机面板或远程监控,至少要能看到电池电压、充电电流和均衡状态。我用 PIC18F46K42 的 UART 口做了一个简单的上报协议,每 1 秒上报一帧数据。
帧格式不复杂:帧头、长度、电池 1 电压、电池 2 电压、温差、充电电流、均衡状态、CRC 校验。上位机收到后绘制两节电池的实时电压曲线,可以直观看到均衡过程。
这段逻辑本身不难,但有个工程细节值得注意:UART 发送和 I2C 读取不能放在同一个中断里抢占资源。我在 MCU 里分配了不同优先级,I2C 通信优先级更高,UART 发送排队执行。否则在充电电流频繁变化时,I2C 偶尔会被 UART 卡住,导致寄存器读取超时,进而触发误报警。
5.3 批量一致性与测试
如果这套方案要走向产品,电池来料筛选比均衡算法本身更重要。均衡只能缓解差异,不能消除差异。电池一开始差异就很大,再好的均衡电路也补不回来。
我的筛选标准如下:
| 筛选项目 | 标准 |
|---|---|
| 内阻极差 | 小于 5mΩ |
| 容量极差 | 小于 3% |
| 常温静置 72 小时压差 | 小于 5mV |
测试流程上,每套电池模组出厂前都要经过上电自检、充电均衡测试、放电容量测试和 72 小时静置老化测试。这些项目里最不能省的是静置老化和循环后的压差复测。很多电池问题只有经过几天静置才会暴露,靠短时间抽检根本发现不了。
5.4 后续扩展方向
两节电池只是这套系统的最小单元。如果以后要做 3S 或 4S 配置,MP2642GR-Z 本身未必够用,但 PIC18F46K42 这边的均衡状态机、电压采样策略、静置维护逻辑都可以直接复用,只需要把分压网络和均衡电路改成对应节数。
如果要做更大的储能容量,我更倾向于引入主动均衡。比如用电感储能转移电荷的方式,均衡电流能从几百毫安提升到数安培,且基本不发热。PIC18F46K42 有足够的 PWM 外设驱动这类拓扑,只是算法从"放电消耗"变成"能量搬运",复杂程度会高一个台阶。
通信方面也可以扩展。现在的 UART 上报协议在后期可以升级成 Modbus,或者加 BLE、WiFi 模块,储能系统集中管理时需要看到每一组电池包的电压和温度。这些扩展对现有硬件影响不大,也是当初主控选型时预留外设资源的原因。
这套系统我前后跑了两个多月,最深的体会是:均衡这件事,芯片和算法只占一半,另一半是采样精度和硬件布局。采样点不干净,算法再努力也是拿错误数据做正确决策;均衡电阻功率留足余量,状态机别急着切换,这些细节决定了方案能不能长期稳定运行。如果这个项目记录能帮你少走一点弯路,我就觉得非常值得了。