玩过电池系统的朋友应该都有这种体验:两块出厂时完全一致的串联电池,用上半年就开始闹分歧。同一时刻量电压,一节还稳稳停在4.0V,另一节已经跌到3.6V。放在储能系统或者备用电源里,这个问题会被放大一整圈——整组电池的可用容量由最弱的那一节决定,而不是最强的那节。所以均衡不是可选项,是保命项。
这次做的是一个2S(两节串联)电池主动均衡小系统,功率核心用MP2642GR-Z,控制核心用STM32C031C6,目标场景是储能机柜里的电池模组、便携户外电源、以及小型UPS备用电池。这套组合能做的事情很简单也很有用:实时比较两节电池电压,把高电压电池里多出来的能量搬到低电压电池里,而不是像被动均衡那样用电阻放热烧掉。适合正在做BMS均衡控制板、或者第一次接触主动均衡的技术人员参考。
下面是我从硬件选型到固件调通的全过程,没有任何藏着掖着的东西,踩过的坑也一并列出来。
1. 为什么2S电池组必须做主动均衡:痛点与选型逻辑
1.1 不均衡的三大来源:制造、温度、老化
先说一个很多人刚接触电池系统时容易忽略的事实:所谓“同一批次”的两节电芯,出厂时也不是完全一样的。制造工艺总有公差,正负极材料克容量、卷绕松紧度、电解液浸润程度都会导致初始容量差异,通常在同批次里就能差出1%到3%。内阻更是如此,同一厂家同规格的两节电池,内阻差个两三毫欧非常常见。
第二个来源是温度梯度。在储能模组里,中间电池往往比两端散热更差,温度高一点,化学反应速率就快一点,自放电和内阻变化也就不一样。备用电源这种常年浮充的场景更明显,浮充电压给到两节串联电池上,温度高的那节承受的有效电压偏高,析锂副反应也更快,容量衰退自然领先一步。
第三个来源是循环老化的路径差异。两节电池在不同放电深度下反复使用,健康状态开始分化,SOH掉得快的那一节约等于提前退休。这几个因素叠在一起,压差随着时间会缓慢放大。储能系统里如果两节电池压差到了200mV以上,系统只能按低电量那节提前停止放电,容量利用率非常难看。在备电系统里更致命:平时市电正常你不会发现,真到断电要顶着的时候,整组电池的有效支撑时间可能直接打七折,这是运维事故的雷。
1.2 被动均衡与主动均衡:成本、效率、应用场景
老式的均衡方案是被动均衡,原理很简单粗暴:给每节电池并一个放电阻,谁的电压高就放谁的,把多余电量变成热耗掉。这种方案电路便宜、控制逻辑简单,在18650小容量消费电子电池里很常见。但它有两个问题:均衡电流小,通常做到100mA左右就算不错;能量白白浪费,高热环境对布局也不友好。
主动均衡的思路完全不同,它把高电压电池的电量通过功率变换电路转移到低电压电池里,不是从外部引入能量,也不是烧掉,而是“搬运”。均衡电流可以做到1A以上,能量利用效率高,发热低,对长期运行的储能设备友好得多。所以在大容量储能电芯、备用电源后备电池这种场景里,主动均衡几乎是标准答案。
这里简单对比一下两者的适用面:
| 对比维度 | 被动均衡 | 主动均衡 |
|---|---|---|
| 工作原理 | 电阻泄放多余能量 | 电感/变压器转移能量 |
| 典型均衡电流 | 50~150mA | 0.5~3A |
| 能量去向 | 变成热量 | 转移到相邻电池 |
| 效率 | 低 | 较高(通常70%以上) |
| 电路复杂度 | 低 | 中 |
| 成本 | 低 | 中 |
| 适合场景 | 小容量消费电池 | 储能、备电、大容量动力电池 |
这次选MP2642GR-Z做主动均衡,而不是单纯在STM32旁边并两个电阻,核心原因就是2S系统在储能和备用电源场景里往往搭配50Ah以上的大电芯,100mA被动均衡对几十Ah级别的容量差来说,一晚上也校正不了多少,纯属隔靴搔痒。
1.3 系统分工:MP2642GR-Z与STM32C031C6各自边界
这套设计里两颗芯片的职责分得很清楚。MP2642GR-Z管“能量搬运”这种脏活累活,它内部有功率级和控制电路,只需要外面挂一个耦合电感和少量阻容,就能实现双向反激均衡电流。换句话说,高压侧高压侧电流脉冲怎么切、什么时候切、怎么把磁场能量放到相邻电池,这颗料自己就能搞定,MCU不需要干预高频开关细节。
STM32C031C6则负责“观察和决定”,用12位ADC采集两节电池电压和温度,跑一个状态机判断要不要均衡、往哪个方向均衡、什么时候结束,再把使能和方向信号送给MP2642GR-Z。之所以不用纯模拟比较器来实现这个逻辑,是因为实际均衡过程需要滞回控制、超时保护、温度降额这些复杂决策,用MCU做状态机能把这些边界条件处理得干净利落。
选STM32C031C6还有一个现实原因:成本。Cortex-M0+内核、48MHz主频、32KB Flash、8KB SRAM,做这种单串到两三串的均衡控制器绰绰有余,而且深度睡眠电流很低,很契合备用电源长期待机、偶尔工作的使用习惯。
2. MP2642GR-Z 均衡核心解析:工作原理与外围设计
2.1 反激式主动均衡:能量如何从高电压池搬到低电压池
理解MP2642GR-Z怎么干活,先要理解反激式均衡的基本拓扑。以2S电池组为例,上面一节叫Cell1,下面一节叫Cell2,两节串联,中间节点是公共点。反激电路的核心是一个耦合电感,原边接Cell1,副边接Cell2,匝比做成1:1。
当检测到Cell1电压高于Cell2时,芯片先导通原边的开关管,让Cell1的电流灌进电感,电感里的磁场能量积累起来。经过一个短暂时间后关断原边开关,导通副边开关,积蓄的磁场能量就通过副边释放到Cell2上。这一开一关在几十到几百kHz的频率下反复进行,宏观上就形成了一股从Cell1流向Cell2的均衡电流。反过来也一样,Cell2高就反向工作,把能量从Cell2送回Cell1。
这个过程的本质就是一个可逆的DC-DC变换器,只不过它工作在两节电压非常接近的电池之间,压差往往只有几十毫伏到几百毫伏,所以它需要能在低压差下稳定传递能量。反激拓扑的好处是升降压灵活,不要求原边副边电压严格相等,加上变压器或耦合电感的隔离作用,可以在两节电池之间建立清晰的能量通路。MP2642GR-Z内部把开关管和控制逻辑集成好了,外部不需要再加功率MOSFET,外围电路能压到很少。
有人会问,为什么不直接用开关电容那种电荷泵均衡?开关电容方案的效率在低压差时也不错,但它要达到同样的均衡电流,电容体积和开关切换频率都不低,控制起来也不如集成电源芯片自由。反激方案在2S相邻均衡这种场景里是最成熟、最稳的选择,这也是我把这颗料放进方案里的原因。
2.2 外围关键参数:电感、限流电阻、开关频率
MP2642GR-Z的外围电路比想象中简单,但几个关键参数还是得认真算。首先是耦合电感。2S场景里两个电池电压非常接近,所以电感匝比通常选1:1,电感量根据芯片开关频率和需要的均衡电流来定。频率越高,电感可以做得越小,但开关损耗会涨;均衡电流要求越大,电感量就要往下压以保证每个开关周期内能建立足够的励磁电流。
以常见的500kHz左右开关频率、目标均衡电流1A来估算,电感量可以落在10μH到22μH这个区间。电感还有一个容易被忽略的参数:饱和电流。峰值励磁电流一般会到平均电流的1.5到2倍,所以电感饱和电流至少要留到2A以上,否则均衡电流还没到位,电感先饱和了,表现为电流上不去、芯片发烫、啸叫,严重的还会把功率管带走。
其次是限流或者说峰值电流设定。芯片通常会提供一个ISET引脚或者通过外部电流检测电阻来设定最大均衡电流,选它的原则是不要超过电感饱和电流的70%,同时要留够温升裕量。储能系统长时间均衡时发热必须考虑,1A均衡电流配一颗小尺寸电感,表面温度很可能冲到60到70摄氏度,不加以限制就会变成热失控风险。
最后是输入输出电容。两节电池的电压都比较低,但反激工作的开关电流脉冲很陡,没有低ESR陶瓷电容做旁路,电压尖峰很吓人。一般原边副边各放一颗10μF/16V的X7R陶瓷电容,再加上一小颗100nF高频去耦电容,就能把噪声压住。元件布局时电容尽量靠近芯片电源脚和地脚,走线不要太长。
2.3 与STM32C031C6的接口方式
MP2642GR-Z和MCU的交互,在我的设计里用最直接的GPIO方式。芯片提供使能脚、方向脚、状态回读脚,三根信号线分别接到STM32C031的普通IO上。MCU控制均衡启停时,先把方向引脚拉到目标电平整,再拉高使能脚,等到状态回读脚给出正常工作的反馈后,就进入均衡状态。
这里有一个值得提的事情:逻辑电平匹配。MP2642GR-Z的工作电压如果高于3.3V,而STM32C031C6的数字IO是3.3V供电,两者之间就不能直连,需要考虑开漏加电阻上拉或者加一路电平转换。具体以实际选型版本的数据手册为准,原理上这层电平匹配必须做对,不然偶尔能工作、温度一变就出错,非常难受。
另外,如果选用带I2C接口的版本,控制路径更优雅:MCU可以通过寄存器读取芯片内部状态、设定均衡电流上下限,还能拿到故障标志位。但这类寄存器级的完整控制流程不是三言两语能写清楚的,这次博文先按最通用的GPIO控制思路来讲,后面有时间我再单独把寄存器版本的适配过程补上。
3. STM32C031C6 控制侧设计:采样、判决与守护
3.1 电压采样电路:不要把电池正极直接接ADC
不少第一次做电池检测的人会直接拿电阻分压去采电池正极,再接给MCU的ADC。2S电池组总共电压最高能到8.4V,远超STM32C031C6的3.3V ADC输入范围,所以必须先把电压按比例拉低。这次我用了两个分压网络,分别采集总电压和中间节点电压,然后在MCU内部做减法算出每节电池的电压。
具体做法:总电压BAT+和中间节点BAT_MID各用一个分压电阻网络,把电压除以4后再送给ADC。比如总电压用300kΩ串100kΩ,中间节点同样用300kΩ串100kΩ,采样点分别接到ADC通道0和通道1。这样最高8.4V只会在采样点产生2.1V,低于3.3V,安全。换算式子不复杂,电压换算关系如下面伪代码所示:
vref = 3.3f; ratio = 4.0f; // 300k / (300k + 100k) adcV = adc_code * vref / 4096.0f; vTotal = adcV_ch0 * ratio; // BAT+对GND vMid = adcV_ch1 * ratio; // MID对GND vCell1 = vTotal - vMid; vCell2 = vMid;但要注意一个问题:分压电阻的误差会让减法结果放大。两路分压比例如果差0.5%,在4.2V电池电压上就会带来约21mV的误差。如果均衡启动阈值设成50mV,这点误差还能接受;但想做得更准,就要用0.1%精度电阻,或者出厂时做一次两点校准,把每块板的实际分压比存到Flash里。我实测下来的建议是:做量产板一定加校准,否则不同板子之间的均衡阈值差异会造成和电池本身不一致的混乱现象。
分压采样点还要加RC低通滤波。我在ADC引脚前各放了一组100Ω串联电阻加100nF对地电容,截止频率大约16kHz,能滤掉大部分反激开关纹波。更讲究的做法是在软件里做中值滤波或者多次采样平均,再配合一个单调递减的转速判据,避免均衡器把噪声当压差反复启停。
3.2 均衡控制状态机:滞回、超时与保护
均衡逻辑我写成了一个简单的状态机,状态包括待机IDLE、测量MEASURE、正向均衡BALANCE_FWD和反向均衡BALANCE_REV。平时系统待在IDLE,MCU进睡眠,由定时器周期性唤醒进入MEASURE;或者外部有命令过来再启动测量。
进入MEASURE后,MCU连续采集十几次电压,做排序后取中间值再平均,得到相对稳定的V1和V2。如果两节电池压差大于50mV,且温度、电压都在安全范围内,就决定开均衡:V1大于V2就进BALANCE_FWD,把能量从Cell1搬到Cell2;反之进BALANCE_REV。
均衡工作中的停止条件也很关键。我设了一组滞回窗口:压差降到20mV以下才停,而不是一到50mV就停。如果不做滞回,均衡器会在阈值附近反复开关,每次开关都会带来电压测量扰动和电流冲击,长期来看非常伤均衡电感。超时保护也要有,我设置了最长30分钟的单周期均衡时间,到点就强制关闭回归IDLE,避免异常工况下均衡器一直不停,把低电池电压反冲到过压。
温度保护同样写在状态机里。均衡电感、芯片和电池的温度都要参与判决,超过55℃就暂停均衡,降到45℃以下再恢复。这个温度回滞能避免热振荡,尤其是在机柜里长时间运行的时候,这个保护实际上是在保命。
3.3 低功耗设计:储能备用系统最容易被忽视的一环
储能系统对自身耗电很敏感,一个均衡板子如果待机干掉200μA,几千套设备加起来就是不小的损耗,而且备用电源本身要求在市电断开后能靠电池撑很长时间,均衡电路不能成为拖后腿的负载。
STM32C031C6在这一点上很适合均衡控制场景。IDLE状态里我让它进入Stop模式,关闭ADC和大部分外设,定时器定时60秒唤醒一次去测电压。实测下来,MCU这部分的睡眠电流不到5μA,加上LDO自身静态电流和分压电阻的漏电流,整板待机可以压到20μA上下。
分压电阻有一个很大的“消费陷阱”。很多工程师选型时只关心精度,忽略了阻值太小会造成持续的分流损耗。我用的300kΩ加100kΩ组合,在8.4V总电压下漏电流只有21μA,可以接受;如果换成10kΩ加3.3kΩ,分压漏电流会飙到600μA以上,这个数字在待机电流预算里就是灾难。所以给MCU供电的低压差线性稳压器也要选静态功耗低、带使能管理的型号,不用均衡时直接把后级电源切断一部分也可以。
4. 从原理图到固件:完整实操记录
4.1 硬件搭建顺序
一个完整的2S均衡板,按我的习惯分三步搭。第一步先把MP2642GR-Z的功率部分搭好,包括耦合电感、输入输出电容、电源去耦电容,然后接上两节串联电池,先不装MCU,直接用信号发生器或者手工跳线给EN和DIR信号,确认均衡电流能建立起来。这是最基础的功率级验证,能尽早暴露电感选错、电流方向接反这类问题。
第二步把STM32C031C6的最小系统搭上,包括3.3V供电、调试接口、复位电路。先烧一个最简单的ADC轮询程序,打印两节电池电压,验证分压电阻的匹配程度和采样噪声。如果这一步看到的电压波动超过20mV,先别急着写均衡逻辑,回头查滤波电容和分压网络。
第三步才把MP2642GR-Z的控制引脚和MCU的GPIO连起来,跑完整状态机。这样做的好处是每次只引入一个变量,出了问题能快速定位。直接把所有东西一次焊完再调试,概率上会浪费大量查错时间。
4.2 固件核心实现
我的固件逻辑主要围绕状态机展开,主循环每隔一定时间运行一次状态机,ADC采样用定时器触发。重点代码结构如下:
typedef enum { STATE_IDLE, STATE_MEASURE, STATE_BALANCE_FWD, STATE_BALANCE_REV } BalState; volatile BalState balState = STATE_IDLE; volatile uint16_t balTimer = 0; // 主循环周期10ms void balance_task(void) { switch (balState) { case STATE_IDLE: // 60秒唤醒一次进入测量 if (wakeup_flag) { set_en(0); // 关均衡 balState = STATE_MEASURE; } break; case STATE_MEASURE: // 采集滤波后的V1、V2、T read_battery_voltage(&vCell1, &vCell2); read_temperature(&temp); if (temp > 55.0f) { balState = STATE_IDLE; break; } // 滞回判断 if ((vCell1 - vCell2) > 50.0f) { set_dir(0); // 定义0方向为Cell1->Cell2 set_en(1); balTimer = 0; balState = STATE_BALANCE_FWD; } else if ((vCell2 - vCell1) > 50.0f) { set_dir(1); set_en(1); balTimer = 0; balState = STATE_BALANCE_REV; } else { balState = STATE_IDLE; } break; case STATE_BALANCE_FWD: case STATE_BALANCE_REV: // 周期性监控电压和温度 if (vDiff_between_cells() < 20.0f) { // 已均衡 set_en(0); balState = STATE_IDLE; } else if (balTimer > 180000) { // 30分钟超时 set_en(0); set_error_flag(); balState = STATE_IDLE; } else if (temp > 60.0f) { set_en(0); balState = STATE_IDLE; // 等温度恢复 } break; } }这段代码只是一个精简版本,实际项目里我还会把ADC采样放到中断里、引入低通滤波数组、把过压和欠压检查也加进状态机。但核心思路就是这个:状态的迁移条件必须加滞回,超时必须兜底,温度必须实时参与决策。
有一点要提醒:如果均衡方向定义反了,整个系统会越均衡越偏。全部调试完成后,要专门用一个已知不平衡的电池组验证方向逻辑。我是通过人为给Cell1充电多一点,让压差拉到明显水平,然后看均衡一段时间后是不是Cell1下降、Cell2上升;方向反一接,你会发现电压差越来越大,这时不要改代码,先去查方向定义。
4.3 实测数据与复盘
调通之后我做了一组模拟实验。选两节标称3.2V的磷酸铁锂电池,先把其中一节单独充到3.55V,另一节放到3.20V,压差约350mV。接上这套均衡板,设定均衡电流目标1A,然后每隔一分钟记录一次电压和压差。
实际运行数据如下表:
| 时间(min) | Cell1(V) | Cell2(V) | 压差(mV) | 状态 |
|---|---|---|---|---|
| 0 | 3.55 | 3.20 | 350 | 启动均衡 |
| 5 | 3.49 | 3.26 | 230 | 均衡中 |
| 10 | 3.42 | 3.30 | 120 | 均衡中 |
| 15 | 3.37 | 3.33 | 40 | 均衡中 |
| 18 | 3.35 | 3.34 | 10 | 停止均衡 |
从350mV压差到20mV以内,大约花了16分钟,均衡电流均值约0.8A。整个过程中电感表面温度上升了约22℃,环境温度25℃时最高摸起来温热,属于正常范围。这里能看出主动均衡的效率:如果是被动均衡,1A电流下每天要白白烧掉好多瓦能量,且要达到同样的校正效果需要两倍以上的时长。
另外我还复测了一次极端情况:让两节电池的压差达到600mV以上再启动均衡,这时候低电池电压偏低,均衡电流反而上不去,因为反激电路需要一定的原副边压差来传递能量。最终用时比350mV那次更长,但状态机通过超时和温度保护正常顶住了,没有损坏硬件。
5. 常见问题与排查技巧实录
5.1 高频问题速查表
这次调试前后踩了一些坑,整理成一张速查表,方便遇到问题时照着查:
| 现象 | 可能原因 | 处理办法 |
|---|---|---|
| 开启均衡但电流没有建立 | 使能方向电平未就绪 | 先拉方向引脚,再拉使能 |
| 电感啸叫 | 电感量过小或饱和 | 换更大饱和电流电感 |
| 均衡电流和设定差距大 | 限流电阻偏大 | 重新核算ISET电阻阻值 |
| 电压采样跳动超过50mV | 分压点滤波不够 | 加RC滤波或软件滤波 |
| 压差降到阈值附近反复启停 | 滞回窗口太小 | 加大停止压差,比如从50mV降到20mV再停 |
| 待机电流异常偏高 | 分压电阻取值太小 | 改用300kΩ以上阻值 |
| 均衡一段时间后反而压差变大 | 均衡方向定义反了 | 检查DIR引脚电平逻辑 |
| 温度一高均衡就自己断掉 | 温度保护阈值偏低 | 确认传感器位置,适当调整阈值 |
每一条都是实际能遇到的,尤其是方向反了这种问题,不接成回路做完整状态机验证,光看电压读数是发现不了的。
5.2 踩坑实录:噪声、误判与修复
第一个坑是分压采样噪声。第一次用示波器看分压点波形,发现均衡开启时采样点上有几百毫伏的毛刺,幅度和反激开关频率同步。这导致MCU里读出来的电压一会高一会低,状态机在40mV和80mV压差之间来回切换,均衡干脆就没法收敛。解决办法是给分压点的ADC通道加了一阶RC低通滤波,同时在软件里做了顶格和底格的中值裁剪,毛刺被削掉之后系统马上稳定了。后来的经验是:任何靠近功率级的模拟采样,都必须用示波器实际看波形,不看的迟早要吃亏。
第二个坑是均衡方向定义。虽然代码里注释了0方向是Cell1到Cell2,但我最初接线时把MP2642GR-Z的方向控制引脚标号看反,导致状态机认为自己在均衡,实际能量在反向搬运。结果第一次带电池测试,原本360mV压差的电池组被“越平均越差”,电压很快朝反方向拉开。排查时先用电压表发现方向反,再对照手册检查接口定义,最后修正接线和软件定义,问题解决。这个坑让我学到一个教训:主动均衡的方向逻辑必须在低压小电流下先做极限验证,不要直接上大电流实测。
第三个坑是超时保护被误触发。一开始我把超时设成10分钟,想着均衡动作不该太久。但实测里遇到大容量电池时,均衡电流在低压差阶段会自然下降,10分钟根本不够把压差从120mV拉到20mV。结果均衡器每次都在快完成时被强行关闭,压差回弹后又重新启动,整个均衡过程拖得很长。后来把超时改成30分钟,就不存在这个问题了。超时保护是必须的,但它的职责是挡住真正的硬件异常,不是限制正常均衡过程。
写在最后:两节串联的主动均衡看着简单,真正把采样、滞回、方向、保护一圈理顺之后,你会发现在多串系统上做的事情其实大同小异。我后来把这套状态机逻辑移到4S电池组的项目上,核心框架没大改,只是把均衡对象从固定的一对电池改成了循环检测相邻电池对,然后让均衡通道互斥运行。所以这套经验你拿去用,后面往更多串数扩展时也顺路。别忘了一件事:多留调试日志。均衡器什么时候启动、运行多久、停止原因是什么,这些数据对长期追踪电池健康状态非常值钱。