今年夏天在外面做储能产品的例行巡检有一组备用电源让我印象特别深两节串联电池静置一个多月再测电压一个3.43V一个2.91V压差超过500mV。最直观的影响是整个电池组的可用容量被那节低压电池掐掉了一大截——串联回路里电流处处相等谁电压先跌破保护整组都得停机。后来我把方案重新做成主动均衡一颗MP2642GR-Z负责在电池之间搬能量一颗STM32L041C6负责判断什么时候搬、往哪边搬、搬多少。这套组合在储能系统和备用电源上跑了几个月效果稳定今天就把从选型、电路设计到固件实现再到调试踩坑的完整过程写出来。1. 两节电池串联不均衡是怎么“拖垮”整组的先说原理。两节电池串联之后流过的电流完全相同但每一节电池的容量、内阻、自放电率不可能做到一模一样。出厂时的微小差异、使用中的温度分布差异、循环老化速度差异都会让两节电池的剩余电量逐步拉开。拉开之后高压那一节会先到达充电截止电压充电被迫停止放电时低压那一节会先到达放电截止电压放电被迫停止。整组电池的表现永远由最差的那节决定。从电压读数上也能看出这个问题。磷酸铁锂电池静置电压和剩余电量之间的关系很平缓可能200mV的电压差就对应百分之十几的电量差。对于10Ah级别的备用电池组来说这意味着几百毫安时的能量永远用不上每次放完电都白白闲置在高压电池里。均衡的本质就是让两节电池的电压差维持在较小范围把高压电池多出来的能量转移到低压电池去。如果不用主动均衡很多人会直接接一个功率电阻让高压电池通过电阻放电这种被动均衡电路简单但能量变成热量损失掉了而且均衡电流一大板子上还要专门处理散热。对比一下两种均衡方式在这个场景下的取舍项目被动均衡电阻耗散主动均衡能量转移能量去向变成热量散掉转移到低压电池继续参与循环均衡电流一般50~100mA受限于散热可以做到200mA以上效率约0%纯消耗80%~90%回收利用电路复杂度MOS管加电阻即可需要功率电感、开关管和控制逻辑成本低中等偏高适用场景小容量消费类电池储能、备用电源、长循环工况标题里的MP2642GR-Z就是一颗面向双电池组的主动均衡控制器。这类芯片内部通常集成了电感式能量转移拓扑的PWM控制电路外部搭一个功率电感和必要的开关管把电压高的那节电池的能量一点点“泵”到电压低的那节。原理上和开关电源的Boost/Buck一样只是变换器的一端不再是母线电源而是另一节电池本身。它的具体引脚和寄存器定义我不在这里背数据手册项目上一定要以官方文档为准。有人会问备用电源平时又不深度放电偶尔才有一次掉电切换有必要花成本做主动均衡吗非常有必要。存储和备用场景恰恰是主动均衡最能发挥价值的地方电池长时间小电流浮充或静置自放电差异会被成倍放大。等到真正需要它顶上去的时候如果其中一节已经先触发了欠压保护整个系统的备电能力就名存实亡了。这套方案的价值不在于把电压差压到零而是保证关键时刻每一节电池都能把电放干净。2. 把系统拆开看MP2642GR-Z搬能量STM32L041C6做调度硬件架构其实不复杂。2S电池组的正极、中间点、负极分别引出MP2642GR-Z跨接在两节电池之间负责能量的双向搬运STM32L041C6通过分压网络采集每节电池的电压通过使能脚、方向控制脚和状态脚与均衡器交互还顺带采集NTC温度。整机大部分时间处于低功耗状态主控定时醒来看一眼压差决定要不要开工。2.1 硬件连接的几根关键线MP2642GR-Z这类均衡控制器和主控之间的接口常见的就是使能、方向、状态这几路信号。使能脚控制均衡器是否启动方向脚决定能量从哪一节搬到哪一节状态脚或状态寄存器告诉主控当前是否在均衡、有没有故障。实际项目里主控和均衡器之间到底是纯引脚控制还是I2C寄存器控制要看具体芯片手册。我这里按引脚控制的方式展开因为这种方式最直接逻辑清晰也容易移植到任何MCU上。测试这块板子时我特别留意了使能信号的时序。有些均衡芯片要求使能信号拉高后必须保持一段时间内部软启动才会执行如果主控在初始化期间把这个脚拉高又立刻拉低均衡器可能直接进入异常状态。所以我习惯在代码里加一个延时确认均衡器进入工作状态后再继续后续操作。2.2 电源与电压采样设计STM32L041C6的供电我建议单独用一颗低压差LDO从电池组总电压降压到3.3V不要直接拿电池电压给MCU供电更不要用别的系统里的3.3V去“蹭”。电池电压范围本身就有波动储能系统里还可能有充电器的干扰电源不稳ADC参考电压就会漂后面所有电压计算全部作废。电压采样用电阻分压。以2S磷酸铁锂为例单节最高充满电压约3.65V总电压最高约7.3V。我用1MΩ上分压电阻和240kΩ下分压电阻分压系数大概是0.194。分压后的电压最高约0.7V远远低于ADC满量程完全安全。分压点并联一只0.1μF的C0G电容用来滤除高频噪声同时给ADC内部的采样电容一个稳定的电荷源。这里有一个容易忽略的细节分压电阻阻值不能随便选。阻值太小待机漏电流太大阻值太大ADC采样时会有明显误差。STM32L0系列在最高采样周期下内部采样电容充电时间大概是几微秒如果分压点阻抗过高采样结果会偏低。我的做法是把ADC采样时间配置到最长并且在软件上做多次采样取中间值这样即使阻值高一点也不会明显失真。2.3 为什么选STM32L041C6均衡控制器负责功率级的能量转移但判断要不要均衡、什么时候均衡、怎么均衡需要一个低功耗大脑。STM32L041C6是Cortex-M0内核主频最高32MHzFlash有32KBRAM 8KB封装是LQFP48。这些配置对一段均衡状态机和几路ADC采样来说完全够用而且它的低功耗模式表现相当不错Stop模式配合RTC定时唤醒待机电流可以做到微安级别。另一个关键点是它自带12位ADC和两个内置比较器。比较器在这里很有用可以在主控进入深度睡眠时通过硬件比较器监测电池压差是否超过预设阈值一旦超限就产生事件把MCU唤醒。这样既省电又不会漏掉需要均衡的时刻。加上LPUART、I2C、SPI这些外设以后想扩展通信、接显示屏或者和其他模块组网都很方便。如果系统需要更高的电池电压可以考虑把多个2S模块串联每个模块一套MP2642GR-Z加STM32L041C6的组合模块之间通过LPUART转485或者I2C组网通信。这种模块化思路在储能系统里很常见均衡逻辑完全隔离维护起来也省心。3. 固件落地采样、滤波和均衡状态机硬件搭好只完成了三分之一真正的逻辑全在固件里。我分三块来讲电压采样如何处理、均衡状态机怎么写、保护逻辑怎么加。3.1 电压采样分压网络加VREFINT校准分压网络送进ADC的电压换算关系比较简单。但实际项目中LDO输出电压会有偏差ADC参考电压也会随温度和负载漂移。如果直接按3.3V计算读数误差可能达到几十毫伏这对判断压差阈值来说太大了。我采用的办法是每次开机用内部参考电压通道做一次实时校准。STM32L0系列芯片内部有一个VREFINT参考电压出厂时校准值存在系统存储区里。每次采样时读取这个通道再用校准值反推当前的VDDA实际电压这样即使LDO输出不是精确的3.3V计算出来的电池电压也基本不受影响。/* * 简化示例读取两节电池电压并换算成mV * 分压系数 DIVIDER_RATIO 根据实际电阻标定 */ #define VREFINT_CAL ((uint16_t)(*(uint16_t *)0x1FF80078)) #define VREFINT_MV 1200UL #define DIVIDER_RATIO 194UL // 实际为 0.194, 按整数处理 static uint16_t adc_read_channel(uint32_t channel) { // 配置ADC通道、启动转换、等待EOC返回12位结果 // 具体寄存器操作按STM32L0标准库或HAL封装 return (uint16_t)adc_value; } static uint16_t calc_cell_mv(uint32_t channel) { uint16_t vref_raw adc_read_channel(ADC_CHANNEL_VREFINT); uint16_t cell_raw adc_read_channel(channel); // 当前VDDA实测值 uint32_t vdda_mv (VREFINT_CAL * VREFINT_MV) / vref_raw; // 分压后电压转换为原始电池电压 uint32_t cell_after_div (uint32_t)cell_raw * vdda_mv / 4095; return (uint16_t)(cell_after_div * 1000UL / DIVIDER_RATIO); }采样滤波上我没有用简单的平均值而是每路连续采5次排序后取中位数。这样能有效滤掉开关电源带来的尖峰干扰尤其是在充电器切换消隐的瞬间ADC读数会突然跳一大截平均值会被拉偏中位数则稳得多。3.2 均衡状态机与滞回控制软件核心是这个状态机。我在实际项目里把均衡过程拆成空载检测、启动均衡、正在均衡、冷却等待这几个阶段。空载阶段只要压差没超过启动阈值就待在低功耗模式里一旦压差持续超过阈值一段时间才进入启动流程均衡过程中如果温度超标或超时立即关闭均衡并进入冷却等待。阈值选择上最重要的是加滞回。启动阈值设成压差大于30mV关闭阈值设成压差小于10mV。中间留出的20mV死区非常关键否则压差在20mV附近波动时均衡器会反复启动、关闭方向还可能来回跳对电感和开关管的冲击都很大。typedef enum { BAL_IDLE 0, BAL_START, BAL_ACTIVE, BAL_COOLDOWN } balance_state_t; typedef struct { uint16_t cell1_mv; uint16_t cell2_mv; int16_t delta_mv; // cell1 - cell2 uint8_t temperature_c; uint16_t balance_elapsed_min; } balance_ctx_t; balance_state_t balance_update(balance_state_t st, const balance_ctx_t *ctx) { switch (st) { case BAL_IDLE: // 压差持续超过启动阈值且温度正常 if (abs(ctx-delta_mv) 30 ctx-temperature_c 45) { return BAL_START; } break; case BAL_START: // 启动前再次确认压差仍存在 if (abs(ctx-delta_mv) 30 ctx-temperature_c 45) { set_balance_direction(ctx-delta_mv 0); enable_balancer(1); reset_balance_timer(); return BAL_ACTIVE; } return BAL_IDLE; case BAL_ACTIVE: if (ctx-temperature_c 45 || ctx-balance_elapsed_min 30) { enable_balancer(0); return BAL_COOLDOWN; } if (abs(ctx-delta_mv) 10) { enable_balancer(0); return BAL_IDLE; } break; case BAL_COOLDOWN: // 散热延时例如强制等待60秒 if (cooldown_timer_done()) { return BAL_IDLE; } break; } return st; }方向锁定是一个比较容易被忽略的点。我的做法是进入START状态时就确定方向在后续整个均衡周期内不允许主控动态反转。只有等到均衡结束后重新进入IDLE下一次才会根据新的压差方向重新判定。这样避免了压差处于临界状态时均衡方向在两个周期之间来回切换导致电感电流突变的隐患。3.3 保护逻辑温度、超时和单次均衡量均衡过程中最怕的不是电压算不准而是PCB上的热量堆积。200mA均衡电流听着不大但长时间运行后功率电感、开关管和续流路径上的铜箔都会发热。我在板子上放了NTC温控阈值设在45度超过就强制停止均衡。温度回落再继续。这个阈值要留出一些余量夏季机柜内部温度本身就高阈值设太紧会导致均衡一直处于“开始就停”的死循环。除了温度我还给单次均衡加了30分钟的超时限制。即使温度没超标持续搬能量也不可取。均衡量太小没意义太大则说明电池之间的差异已经不是均衡能解决的。30分钟后如果压差还没拉回来固件会记录一条异常事件上报给上位机提醒检查电池组本身。4. 调试中反复踩的四个坑及排查思路这套系统从第一版打样到稳定运行中间踩了不少坑。我挑四个最有代表性的写出来每一个都是真实排查过的思路比结论更重要。4.1 ADC读数整体偏移问题出在VDDA第一版板子调试时采样电压和万用表实测值始终相差七八十毫伏而且差值不固定。我一开始怀疑是分压电阻精度不够特地换了0.1%的电阻重新标定结果还是偏。后来怀疑LDO输出电压不准用示波器一看3.3V输出的纹波确实有点大但也不至于偏这么多。最终定位到ADC参考电压上。LDO空载输出3.3V一旦ADC开始工作采样电容的瞬态抽流会让VDDA出现明显跌落。更麻烦的是跌落幅度还和采样频率、通道阻抗有关所以读数一会儿偏大一会儿偏小。解决方法是启用VREFINT校准把每次采样的VDDA实际值算出来再反推电压。校准之后读数与万用表的误差缩小到5mV以内。这个经验直接推翻了“LDO输出是精确3.3V”的假设凡是高精度采集场景都应该做实时参考电压校准。4.2 均衡器偶尔“罢工”使能信号电平太脏有段时间均衡器启动成功率不稳定十次里有两三次一点反应都没有。用逻辑分析仪抓使能信号发现MCU引脚输出的上升沿特别慢从低电平爬到高电平要好几微秒。原因是我一开始为了兼容开漏接法GPIO配置成了开漏输出并外接一个20kΩ下拉电阻。这个组合对上拉能力很弱均衡器侧的引脚又有漏电流电平就一直卡在中间区域。排查后把GPIO改成推挽输出去掉外接下拉电阻使能信号瞬间干净了上升沿小于1微秒均衡器启动成功率恢复到百分之百。之后我养成一个习惯凡是控制功率器件使能脚的信号都优先用推挽输出并且看示波器确认边沿质量。很多“偶尔失灵”的故障根子都在信号边沿上。4.3 压差临界时方向反复横跳第三版固件加入滞回逻辑之前均衡方向出现过反复横跳的现象。具体表现是压差在20mV附近波动时系统一会儿判断“高压电池在下面”一会儿判断“高压电池在上面”方向控制脚跟着来回翻转。芯片内部功率开关管的状态还没完全建立又被新指令打断EMI噪声和电感啸叫都很明显。解决思路前面已经提到过一是在状态机里增加方向锁定二是在采样层面做中位滤波让方向判断趋于稳定。还有一个工程细节方向切换必须严格遵守时序先关闭均衡器等待一个完整的关断周期再改变方向引脚最后重新使能。这个先后顺序不能省否则电感电流方向突变会产生很高的尖峰电压严重时可能击穿开关管。4.4 待机电流怎么也压不下去备用电源对整机待机功耗要求很高最初目标是不超过20μA。第一次实测整机待机电流接近200μA远超预期。我刚开始怀疑是MCU没真正进入Stop模式用电流表逐一排查后发现至少三分之一是MCU引脚悬空导致的漏电。原来LQFP48封装有不少未使用的引脚它们如果保持默认模拟复位状态还好一旦被代码初始化成GPIO开漏输出且电平不确定就会在芯片内部产生持续漏电路径。把未用引脚统一配置成模拟输入模式后MCU部分降到0.8μA左右。接着查分压网络两个1MΩ分压电阻长期挂在电池两端算下来漏电约13μA占了预算的大部分。最后用一颗低导通阻抗的MOS管把分压网络的地端隔离开只在采样时短时间接通待机漏电降到几乎为零。MOS管的导通时间只需要几十毫秒完全足够ADC完成一次稳定采样。5. 针对储能与备用电源的专项优化通用均衡方案可以直接用但储能和备用电源场景还有几个自己的“脾气”值得单独说说。5.1 待机功耗预算怎么算我把优化后的实测电流列在下面方便对照耗电项优化前优化后STM32L041C6 Stop模式RTC1.8μA0.8μA分压网络×2常通13.6μA几乎为0MOS管隔断均衡控制器关断漏电2μA2μALDO及其他8μA4μA合计约25μA约7μA备用设备的电池往往要静置几周甚至几个月这7μA虽然不大长期下来也要算进自放电。所以在最后定型时我做了两个改动一是MCU只在采样和处理均衡时醒来其余时间深度睡眠二是分压网络用隔离MOS管控制把静态损耗降到最低。5.2 定期强制均衡与老化监测储存场景还有一个容易踩的误区就是只靠压差触发均衡。电池自放电差异是一个缓慢持续的过程等压差累计到30mV再触发均衡虽然没问题但不够好。我后来加了一个“定时维护均衡”的功能每天某个时间点主控自动醒来不管压差是否超标只要温差、电压范围正常就开启一次短均衡持续几分钟然后回到睡眠状态。这么做的原理很简单相当于给电池组做“健康维护”。定期小剂量的均衡比等压差拉大后再大量转移能量温和得多也避免了压差长期偏大对正极材料结构造成不可逆损伤。同时固件会记录每次均衡前后的压差数据通过通信接口上报给上位机长期积累下来就能看出哪一节电池老化更快提前预警。5.3 与充电控制的联动浮充工况下充电器一直挂着充电控制模块会周期性判断电池是否需要补充。这套主动均衡方案和充电控制联动后效果比单独工作更好。充电末期电压高的电池先接近截止条件充电控制因此切断充电器整组的充电量被高压那节限制住。均衡器启动后把高压电池的能量转给低压电池高压电池电压下降低压电池电压上升整组最高的电压回落到截止线以下充电器又能继续给组内电池充入一部分电量。这个“充电-均衡-再充电”的循环在浮充期间可以反复进行几次最终两节电池都能尽量充满。对备用电源来说完全充满意味着真正的备电时间接近设计值而不是被电压差偷偷打七折。这里要提醒的是均衡电流一定不要大于充电电流否则可能出现“越均衡越掉电”的奇怪现象。我的习惯是均衡电流设置为充电电流的四分之一以下整体保持平稳。写在最后这套基于MP2642GR-Z和STM32L041C6的2S主动均衡方案原理、电路、固件、调优思路基本都讲透了。在实际量产阶段我还会再补充几项比如分压电阻的精度选择、均衡电流设定电阻的温漂系数、以及NTC摆放位置对温度滞后的影响。这些细节看着小却决定了长期运行的稳定性。最想说的还是那句老话均衡不是把两个电池电压强行掰成一样的魔术而是给串联电池组一个持续健康运行的条件。先搞明白为什么要均衡再动手做均衡方案才不会跑偏。
阅读完成 · 觉得有帮助?