上个月我在调一台2S磷酸铁锂后备电源样机,遇到的麻烦归根结底就俩字:均衡。10Ah电芯,5A满载放电,放到中段时两节电池之间的压差被拉到0.4V以上,电压低的那节先触发欠压保护,整机直接关机,实际放出的能量连七成都没到。后来我把方案从传统的电阻耗散均衡改成了主动电荷搬运:用MP2642GR-Z做均衡核心,由TM4C123GH6PZL负责电压采样和均衡调度。折腾了两周把整条链路跑通,效果很直观——初始150mV的静置压差,均衡大约两个小时压进10mV以内。这篇文章就把整套2S储能/备用电源均衡系统的硬件设计、外围参数、固件逻辑和实测结果完整过一遍,给正在做小型BMS的工程师一个可以直接参考的样本。
1. 为什么2S储能系统里的均衡,不能继续全靠"烧电阻"
1.1 长期待机的储能系统,压差是怎么悄悄拉开的
很多人觉得串联电池只有两节,均衡随便做做就行,但实际上储能和备用电源场景恰恰是最需要认真对待均衡的。后备电源绝大多数时间处于浮充或静置状态,电芯之间的自放电差异会一天天积累。不同电芯的SEI膜质量、内部自耗电流都不一样,静置一个月容量保持率差1%~3%很常见。
如果两节电芯分别用在不同温度梯度下,差异还会进一步放大。备用电源设备内部,电池附近往往有功率器件,靠近发热源的那节电芯温度高一些,自放电更快,性能衰减也更快。等系统真正需要放电时,原本只差一点的SOC会因为极化电压不同被放大到可观的水平。
磷酸铁锂的SOC-OCV曲线在中间平台区非常平缓,电压只差十几毫伏,对应SOC可能已经差了好几个百分点。这意味着"看起来压差不大"并不代表荷电状态一致,而SOC不一致才是放电容量损失的根源。2S系统虽然只有两节电芯,但每节承担了一半的串联容量,单节落后对整机可用容量的影响是成比例的,远不像12S系统里单节落后那样可以靠其他电芯分摊。
1.2 被动均衡的"电阻放热"方案够用吗
传统被动均衡的思路很简单:每节电池并联一个电阻和一个开关,电压高的那节通过电阻把多余能量放掉。这样做控制逻辑非常省事,MCU只要检测到压差超阈值就导通对应的放电MOS,压差回到阈值以下就关断。
但被动均衡有两个硬伤在储能场景里很致命。第一是能量损失,均衡电流做大了(几百毫安),热量需要散出去,而储能设备的电池仓往往是密闭环境,散热条件差;均衡电流做小了(几十毫安),对大容量电芯来说基本是安慰剂,10Ah电芯相差1%SOC就是0.1Ah,30mA均衡电流要三个多小时才能补回来,而这个过程还在持续发热。第二是能量去向本身就不合理,高荷电电芯的能量被白白浪费掉,低荷电电芯一点好处没拿到。
第二个问题在放电末端体现得非常明显。电压高的电芯还有电,电压低的电芯已经接近欠压阈值,整机因为这个被迫提前关机。被动均衡对这种情况无能为力,因为它只是把高电芯的能量烧掉,电压会掉得更快。
1.3 为什么这次选了MP2642GR-Z,而不是自己做DCDC均衡
自己搭电感式主动均衡(buck-boost结构)不是不可以,但要处理的事情太多:半桥MOS驱动、电感选型、峰值电流控制、环路补偿,还要考虑防止电感饱和。在2S这种小系统里,这些工作量几乎和电池组本身一样大,性价比非常低。
MP2642GR-Z这类开关电容均衡方案把最麻烦的开关时序集成在芯片内部了。外部只需要一颗飞跨电容,芯片自动检测两节单元的电压差,通过内部的开关阵列周期性切换电容的连接位置,把高电压单元的能量搬运到低电压单元。MCU要做的只剩两件事:决定什么时候允许均衡,以及监控均衡期间有没有异常。这种"控制与功率分离"的架构也方便调试,功率部分出了问题不会波及主控,主控崩溃也不会让均衡电流失控。
从成本和体积上看,开关电容方案不需要电感,外围元件数量少,PCB面积能压到很小。对于一个2S电池包来说,多出来的这些元件成本完全在可接受范围内,换来的是能量不浪费、发热量大幅降低、均衡完成后电芯状态一致性好得多。
| 方案 | 外围复杂度 | 能量去向 | 散热压力 | 适用规模 |
|---|---|---|---|---|
| 被动均衡(电阻耗散) | 低 | 浪费 | 大 | 过充保护为主 |
| 自制电感式主动均衡 | 高 | 转移 | 小 | 多串大容量 |
| 开关电容主动均衡(MP2642GR-Z) | 低 | 转移 | 小 | 2S~4S小系统 |
2. MP2642GR-Z的电荷搬运原理与外围参数设计
2.1 开关电容均衡的物理过程:从高节到低节的"舀水"
要理解这颗芯片的工作方式,先想一个简单的场景:两个水槽水位不同,你想用小桶把高水位水槽里的水舀到低水位水槽里。桶在水槽A装水,提到水槽B倒掉,再回到水槽A装水,如此反复。只要两个水槽还有水位差,桶每次都能舀到一些水;水位越接近,每次舀到的水越少。
开关电容均衡就是干这个事。第一阶段,内部开关把飞跨电容CP接到电压较高的电芯两端,电容被充到与高电芯两端相同的电压,相当于桶装满了水。第二阶段,开关切换,电容改接到电压较低的电芯两端,因为电容两端的电压比低电芯高,电荷自然通过开关网络流向低电芯,相当于把水倒进了低水槽。芯片内部以一定频率反复执行这两个阶段,每次转移的电荷量大约是CP乘以两节电芯的实时压差ΔV。
这个机制有个非常讨喜的特性:天然自收敛。压差越大时每次搬运的电荷越多,均衡速度快;压差变小后每次搬运的电荷变少,速度自然降下来。它不会像某些闭环控制那样因为过度纠正产生反向压差,停止过程非常柔和,对电芯没有伤害。
另一个好处是均衡方向是自动的。电容每当被并到高电压单元两端才会被充满,切到低电压单元端才会放电,无论哪节电压高,能量总是从高往低走,不需要MCU判断方向。MCU只需要给一个使能信号,芯片自己处理细节。
2.2 外围元件选型与参数计算
MP2642GR-Z的外围电路非常精简,但每个元件都有讲究。飞跨电容是核心元件,它的大小直接决定单次转移电荷量。电容越大,单次搬运电荷越多,均衡速度越快,但开关切换瞬间的电流冲击也越大,对PCB布局的要求越高。
| 元件 | 推荐值 | 说明 |
|---|---|---|
| 飞跨电容CP | 10µF~22µF,X7R,25V以上 | 紧靠芯片布局,ESL要小 |
| 输入旁路电容 | 10µF陶瓷 + 100nF高频电容 | 放在电池组输入两端 |
| MCU使能控制 | GPIO直接驱动或加电阻分压 | 确认EN引脚电平范围 |
| 采样分压电阻 | 0.1%精度,温漂50ppm以内 | 采样误差必须控制 |
| 采样RC滤波 | 100Ω + 100nF | 抑制均衡开关噪声 |
飞跨电容的耐压要留足余量。2S磷酸铁锂最高约7.3V,三元锂最高约8.4V,常规选25V问题不大。如果设备存在电池反接风险,或者均衡器输入侧可能有较大的瞬态电压,直接上50V耐压更稳妥,成本差异很小。
去耦方面,在电池组输入两端放10µF和100nF的组合是基本功。10µF应对均衡器工作时产生的低频电流脉动,100nF应对高频开关尖峰。位置要尽量靠近芯片的电源引脚,中间不要穿太多过孔。使能引脚方面,TM4C123GH6PZL的GPIO是3.3V电平,需要确认芯片EN引脚是否兼容3.3V逻辑。如果EN高电平阈值较高,或者绝对最大额定值低于3.3V,中间加一级三极管是更稳的做法。
这里提醒一句:具体参数范围最终以芯片官方数据手册的推荐电路为准,不同批次的内部开关频率和阈值可能有差异,选型后务必实测确认。
2.3 均衡电流的估算与收敛规律
开关电容的等效平均均衡电流可以用一个简单的公式估算:I_avg ≈ CP × f × ΔV。其中f是内部开关频率。举个例子,假设CP为10µF、开关频率100kHz、压差100mV,则均衡电流大约是10µF × 100kHz × 0.1V = 100mA。压差降到30mV时,同一套系统只有约30mA。
这说明均衡后半程会显著变慢。同样把压差从150mV拉到50mV可能只需要几十分钟,但要从20mV拉到5mV可能需要同样甚至更长的时间。工程上不需要强求完全均衡,设定一个合理的停止阈值(比如10mV)就足够了,后面的微小压差让电芯自平衡去处理。
这个特性对后备电源这种应用是友好的。后备电源不追求极快的均衡速度,它更在意均衡过程的平稳和不过度,开关电容天然能做到这一点。10Ah级别的电芯,初始压差150mV,最保守估算均衡所需时间在两三个小时左右,完全满足"夜间待机时慢慢均衡,白天不影响正常放电"的节奏。
3. TM4C123GH6PZL的采样精度与均衡调度逻辑
3.1 主控在系统里扮演什么角色
TM4C123GH6PZL是一颗Cortex-M4F内核的MCU,主频80MHz,带FPU,256KB Flash和32KB SRAM,内置12位ADC、多个定时器和UART,封装是LQFP100。用在小型BMS上,性能和资源都绰绰有余。
它的职责可以拆成四块:周期性采集两节电芯电压和温度;根据压差和故障状态决定均衡器的启停;记录均衡动作时间和故障历史;通过串口把状态上报给外部设备。它不参与电荷搬运本身,只控制MP2642GR-Z的EN引脚,相当于给均衡器装了一个闸门。这种做法的好处是如果均衡器异常,主控可以立即拉断使能,不留失控窗口。
用MCU而不是纯模拟电路做控制,主要是为了灵活。启动阈值、停止阈值、超时时间都可以通过修改参数调整,不需要重新设计硬件。调试阶段这些参数会有很大的改动空间,固件方案显然更适合。
3.2 电压采样拓扑与误差预算
2S电池系统的电压采样有个容易忽略的问题:每节电芯的共模电压不同。Cell2的正极是系统GND,采样容易;Cell1的负极是系统GND,但正极电压是两节电芯电压之和,超过MCU的ADC输入范围,不能直接采样。
常规做法是用高精度电阻分压,把Cell1和Cell2分别分压到ADC可接受的范围内。Cell2可以直接从中间节点分压;Cell1需要从Cell1正极分压,然后减去Cell2的采样值,即两次采样结果相减。这里有个精度陷阱:相减之后,两次采样误差会叠加。
分压电阻的精度直接决定均衡控制的可靠性。单片电芯电压3.2V,如果分压电阻用1%精度,分压点电压误差可能到32mV,这已经超过合理的均衡停止阈值,会造成控制逻辑频繁误启动或误停止。所以分压电阻选0.1%精度、温漂50ppm以内是必要的。
还要注意分压电阻本身是电池组的持续负载。如果总阻抗只有几万欧姆,从电池组正极到地的静态电流会到几百微安,长待机场景下这就是白白消耗。一个实用技巧是用MCU的GPIO作为分压网络的电源开关,只在采样瞬间给分压网络供电,平时保持断开。这一小段代码能省掉大量待机电量。
ADC参考电压同样值得关注。TM4C123GH6PZL的ADC参考可以使用内部3.3V电源,但对均衡这种需要精确比较压差的应用,更稳妥的方案是给VREFA引脚接独立的稳压源,并加RC滤波,避免数字电路开关噪声干扰参考电压。如果预算有限,用内部参考也不是不行,但需要做软件校准,把每个通道的增益误差和偏置误差标定出来。
3.3 控制逻辑:滞回阈值、调度时间与状态机
均衡控制的核心是滞回比较加超时保护。启动阈值和停止阈值必须分开,否则压差在阈值附近波动会导致均衡器反复启停。我常用的一组参数是:启动阈值30mV,停止阈值10mV。30mV的选择依据是既不会误触发(噪声叠加后通常不超过5mV),又能尽早介入;10mV的停止阈值保证均衡完成后电芯状态足够接近。
用状态机管理均衡流程比直接在主循环里写if语句清晰得多。空闲态、均衡态、故障态三个状态,加上一个周期性的定时中断作为调度帧,就能覆盖所有场景。每个调度帧里做一次采样、一次滤波、一次状态转移判断。
下面这段代码展示了核心的状态机逻辑,使用周期为100ms的定时器驱动:
typedef enum { BMS_IDLE, BMS_BALANCING, BMS_FAULT } bms_state_t; volatile bms_state_t bms_state = BMS_IDLE; static uint32_t balance_ticks = 0; void bms_tick_100ms(void) { float v1 = read_cell1_voltage_mv(); float v2 = read_cell2_voltage_mv(); float delta = fabsf(v1 - v2); uint8_t fault = check_faults(v1, v2); if (fault) { balancer_disable(); bms_state = BMS_FAULT; return; } switch (bms_state) { case BMS_IDLE: if (delta > BALANCE_START_MV) { balancer_enable(); balance_ticks = 0; bms_state = BMS_BALANCING; } break; case BMS_BALANCING: balance_ticks++; if (delta < BALANCE_STOP_MV) { balancer_disable(); bms_state = BMS_IDLE; } else if (balance_ticks > BALANCE_TIMEOUT_TICKS) { balancer_disable(); set_fault(FAULT_BALANCE_TIMEOUT); bms_state = BMS_FAULT; } break; case BMS_FAULT: if (fault_cleared()) { bms_state = BMS_IDLE; } break; } }代码里的超时计数很重要。均衡器连续工作超过设定时间(比如2小时)压差还没有收敛到停止阈值以下,说明电芯本身已经出现不可逆的容量或内阻差异。继续均衡只是反复搬运能量,没有实际价值,这个时候应该置故障并停止,同时把状态记录下来供维护人员判断。
4. 实测数据、PCB布线与噪声对抗的复盘
4.1 实测均衡曲线:150mV压差的收敛全过程
测试样机是一台2S磷酸铁锂后备电源,电芯额定容量10Ah。为了让试验有可比性,我先人为制造不均衡:把Cell1充满静置到3.38V,Cell2放到约70%SOC静置到3.23V,初始静置压差约150mV。开启均衡系统后每10分钟记录一次数据。
| 时间(min) | Cell1电压(V) | Cell2电压(V) | 压差(mV) | 均衡状态 |
|---|---|---|---|---|
| 0 | 3.382 | 3.232 | 150 | 启动 |
| 10 | 3.374 | 3.240 | 134 | 运行中 |
| 30 | 3.351 | 3.256 | 95 | 运行中 |
| 60 | 3.322 | 3.278 | 44 | 运行中 |
| 90 | 3.305 | 3.291 | 14 | 接近停止 |
| 105 | 3.298 | 3.290 | 8 | 停止 |
实测数据清楚展示了开关电容均衡的减速特性:前30分钟压差下降55mV,中间30分钟下降51mV,最后30分钟只下降36mV。后半段每次搬运的电荷量减少了,速度自然放缓。均衡停止后,系统带载运行3小时,两节电芯压差始终保持在15mV以内,说明均衡结果没有被轻微极化差异破坏。
4.2 PCB布线的三个高频错误和我踩过的坑
第一次打样时我犯了三个典型错误,都是在均衡启动后才暴露出来的,提前写出来帮大家少走弯路。
第一个错误是飞跨电容离芯片太远。我最初把电容放在板子边缘,走线绕了小半圈,结果均衡启动时用示波器测CP引脚的波形,能看到明显振铃,幅度接近几百毫伏。这是回路寄生电感过大造成的,开关瞬间的di/dt在寄生电感上感应出了反电动势。整改办法很简单:飞跨电容必须紧贴均衡芯片的同侧放置,走线短粗,中间不要有过孔。
第二个错误是电池采样线走了功率路径。我最初为了布板方便,把采样分压电阻的采样点接在均衡器输入电容同一段铜箔上。均衡器工作时这个节点有脉冲电流流过,铜箔存在电阻,采样点电压就叠加了脉冲噪声。整改方式是让采样线从电池端子单独走细线,形成开尔文连接,采样路径上的任何电流都不经过采样点。
第三个错误是模拟地和功率地在芯片附近直接大面积连成一片。均衡器的开关电流在地铜箔上会产生地弹电压,这个电压叠加在ADC参考地和采样地之间,直接污染了所有采样通道。最后把功率器件的接地脚集中到一点,用0Ω电阻或磁珠连接到模拟地平面,采样数据才干净下来。
4.3 均衡噪声污染ADC采样的完整排查链路
均衡启动后,串口日志里的电压读数出现±30mV抖动,均衡停止后恢复正常。这个现象很典型,完整排查过程值得记录,因为它同时涉及硬件布局和软件策略。
第一步用万用表直接在电芯端测量,确认电池电压本身没有波动。万用表读数是稳定值,说明抖动来自测量链路而不是电芯。第二步用示波器探ADC引脚,发现采样瞬间有约100mV的尖峰振铃,频率和均衡器开关频率一致,这就锁定了干扰源。第三步检查布局,发现飞跨电容回路面积过大、采样线距离功率走线太近,噪声通过寄生耦合进入了采样引脚。第四步压小回路面积,把采样线单独走远,振铃幅度降到20mV以内。最后再加一道软件防线:ADC采样触发时间避开均衡器的开关切换瞬间,并且对连续采样做中值滤波。
这套流程的关键经验是:硬件问题不要指望软件硬扛。先通过布局和走线把干扰源压住,软件滤波只做最后兜底,两者配合才能得到稳定可靠的数据。
5. 固件保护联动:采样滤波、故障判定与安全退出
5.1 采样滤波:先让数据可信,再谈均衡
ADC采样原始数据直接用于控制会有两个问题:一是均衡器开关噪声带来的尖峰,二是大分压电阻配合ADC内部采样电容充放电造成的读数建立时间不足。硬件RC滤波只能压掉一部分,拿到固件里的数据仍然需要做软件处理。
我常用的组合是5点中值滤波加滑动平均。中值滤波对尖峰特别有效,它不会像均值滤波那样把尖峰摊到多个采样点上;滑动平均则进一步平滑剩余的小幅抖动。需要注意滤波窗口不要开得太长,否则真实电压变化也被抹平了,均衡停止后压差已经回到10mV以内,采样数据却迟迟反映不出真实情况,导致控制滞回。一般来说,5点中值加8点滑动平均就足够,每个调度帧重新计算一次。
采样时刻也要讲究。均衡器工作时,开关状态切换的瞬间会产生噪声尖峰,如果ADC刚好在这个时刻触发采样,即便滤波也难以完全消除。我的做法是在调度帧里先延时一小段时间(比如500µs)避开均衡器动作沿,再开始采样。多花这几百微秒对控制周期几乎没有影响,但采样数据质量会明显提升。
5.2 过压、欠压、过温、超时如何与均衡互锁
均衡器不是独立工作的部件,它必须嵌入整个BMS保护体系里,任何异常都能把它拉停。不同的异常条件对均衡动作的反应不同,下面按我的项目逻辑逐一说明。
过压保护要区分场景。如果是充电状态下某节电芯电压已经接近充电上限,应当优先停止充电,均衡器继续动作没有问题——它在把高压电芯的能量搬出去,对降低高压电芯的过压风险反而是帮助。但如果是均衡器自身导致某节电芯电压异常升高(比如另一节电芯接入故障),就要立即禁用均衡并报故障。
欠压保护更谨慎。放电状态下若某节电芯接近欠压阈值,系统先断负载。此时如果压差还很明显,允许均衡器继续工作一小段时间——它把稍高电芯的能量转移到低电芯,低电芯的电压会略微回升,这对系统恢复是有利的。但如果两节电芯都已经接近欠压阈值,均衡已经没有实际意义,直接拉停。
过温保护最简单:均衡电流虽然不以散热为主要目的,但内部MOS和电容的损耗仍然会发热。电池温度超过设定值(比如55℃或60℃)时强制拉断EN引脚,等温度回落到安全区间后再恢复正常控制逻辑。
均衡超时保护很容易被忽略,但这个最重要。如果均衡持续两小时压差仍超过30mV,说明两节电芯的容量或内阻差异已经超过均衡器能纠正的范围。继续运行只会反复搬运能量,没有任何实际收益。此时记录故障码、停止均衡,并通过串口把提示打出来,提醒进行维护检查。
| 异常项 | 触发条件 | 保护动作 | 恢复条件 |
|---|---|---|---|
| 过压 | 单节 > 3.65V(LFP) | 禁止充电,允许均衡 | 电压回落到3.55V以下 |
| 欠压 | 单节 < 2.5V(LFP) | 断开负载 | 重新充电后清除 |
| 过温 | 电芯 > 55℃ | 停止均衡 | 温度回落到45℃以下 |
| 均衡超时 | 均衡 > 2小时且压差 > 30mV | 停止均衡,记录故障 | 维护后手动清除 |
5.3 一个可用的串口上报协议与调试技巧
BMS没有显示屏时,串口协议是必须的。我用的最小文本协议足够调试使用,也方便上位机解析,帧格式很简单:
<BMS>V1=3289,V2=3275,VBAT=6564,TEMP=28,BAL=0,FAULT=0\r\n字段含义分别是Cell1电压、Cell2电压、电池组总电压、温度、均衡器使能状态、故障码。每500ms发一帧在调试阶段可以改到100ms,方便观察均衡过程的细节。
这种纯文本格式的好处是用任意串口助手都能直接看,不需要专门写上位机。如果要做长时间记录,用Python脚本按行解析即可,二三十行就能搞定:
import serial ser = serial.Serial('COM3', 115200, timeout=1) while True: line = ser.readline().decode().strip() if line.startswith('<BMS>'): fields = dict(item.split('=') for item in line[5:].split(',')) print(f"V1={fields['V1']}mV V2={fields['V2']}mV ΔV={int(fields['V1'])-int(fields['V2'])}mV BAL={fields['BAL']}")调试均衡逻辑时,我建议在固件里加一个"强制均衡模式"的串口命令。正常控制流程下均衡器启停由状态机决定,但测试硬件时需要手动开启均衡、观察均衡电流和温度。强制模式绕过调度逻辑直接打开EN引脚,方便测量芯片的实际均衡电流和热特性。测试完成后再切回自动模式,这个开关让我在验证PCB布局时省了很多时间。
最后说个我调试时踩过的阈值细节:最开始我把均衡停止阈值设成5mV,结果压差已经在采样噪声范围内反复波动,均衡器频繁启停,日志记录里全是无效动作。后来把启动阈值定在30mV、停止阈值定在10mV,加上2小时超时保护,整机运行稳定了很多。不同电芯的一致性水平不同,如果你手里的电芯品质更好,阈值可以适当收紧;如果一致性差,记得把超时提示做好,别让均衡器空转。这套"开关电容均衡芯片做主功率、MCU做调度和保护"的组合,后续要扩展到3S或4S系统时,控制逻辑的大框架基本不用变,只需要增加采样通道和对应的保护阈值。