以前做专门给储能柜用的备用电源控制板时,A同学递给我一套2S磷酸铁锂模组,说用了三个月,其中一节明显鼓包。拆开后先量电压:一节3.31V,另一节只有3.05V。问题不在电芯本身,而在两节串联电池的荷电状态早就跑偏了,保护板上的被动均衡又跟不上节奏,高电压那节一直在过充边缘反复试探。后来我直接用 MP2642GR-Z 搭配 STM32F303RE 做了一版针对两节串联电池的主动均衡模块,板子在储能和备用电源系统里连续挂了几个月,效果很稳。这篇就把硬件连接、采样方案、软件状态机、实测数据和踩过的坑一次性说清楚,给正在做2S模组均衡、或者准备做BMS最小单元的朋友做个参考。
1. 两节电芯为什么会越用越岔:先说透均衡的必要性
1.1 初始差异在串联回路里会被循环放大
很多人以为同一批电芯出厂时是一致的,实际上容量差0.5%、内阻差几个百分点、自放电率不同都是常态。串联电路里充电电流和放电电流处处相等,但每节电芯吸收或释放的能量并不相同。容量偏小的电芯会先充满、先放空,每个循环下来,两节电芯的荷电状态差就被放大一点。储能系统长期浮充,备用电源常年挂在线上,这种差异还会被充电末端陡峭的电压平台进一步放大。
我做过一个粗略测算:两节容量分别为100Ah和99Ah的铁锂电芯串联,理论上经过50次完整充放电循环,SOC差就能拉到5%以上,对应的电压差差不多有30到50mV。这种压差看起来不大,但对满充态的电池包来说已经相当危险。高电压电芯提前进入析锂或鼓包区间,低电压电芯还在半路,整个模组的可用容量被"木桶短板"卡死。
1.2 被动均衡为什么在2S模组里特别尴尬
最常见的均衡方案是电阻放电均衡。控制IC检测到某节电压偏高,就给它并联一颗放电电阻,把多余能量以热量形式放掉,电压低的那节什么都不做。这种方案电路简单、成本低,用在多串数的大电池包里也还有人沿用,但在2S系统里有个很现实的问题:均衡能量全部浪费掉了,而储能和备用电源恰恰是能量敏感场景。
更重要的是被动均衡反应太慢。假设压差50mV,均衡电流只有50mA左右,被放掉一个百分点电量可能需要几十分钟。而充电末期的电压变化速度往往比均衡速度快,电阻均衡根本追不上。等它把高压电芯压下来,低压电芯已经被充电电路顶到了过压保护点,整个模组只能停止充电。这就是最典型的"均衡了个寂寞"。
1.3 MP2642GR-Z 与 STM32F303RE 的分工逻辑
MP2642GR-Z 是开关电容式主动均衡芯片。它利用飞渡电容在两节电芯之间搬运电荷,把高电压电芯的能量直接送进低电压电芯,而不是变成热量烧掉。均衡能力由飞渡电容容值、内部开关频率和当前压差共同决定,整体效率远高于电阻均衡,发热也小得多。芯片本身有自主工作的能力——检测到压差后自己就能进入均衡状态,不需要外部干预。
但一个纯模拟芯片解决不了全部问题。它不会判断"现在是不是浮充阶段""温度是不是太低""压差是瞬时波动还是真实失衡"这些系统级策略。这些判断由STM32F303RE负责。F303RE是一款Cortex-M4F内核、带FPU的72MHz MCU,内部集成多路高速ADC、比较器和运算放大器,用来做电压采集、状态决策和故障上报正合适。简单说:MP2642GR-Z 管功率搬运,STM32F303RE 管策略决策。一个做执行,一个做大脑,两件事分开,系统才不容易乱。
2. 硬件搭建:从电池连接到MCU采样端的完整链路
2.1 2S电池组与均衡芯片的电气连接
两节电芯串联后存在三个必接的电气点:总正极、中间节点、总负极。节点关系和连接对象必须一开始就理清楚。
| 电气节点 | 电位范围 | 主要连接对象 |
|---|---|---|
| 总正极 | 5.0V至8.4V | 均衡器高端口、总压采样分压网络 |
| 中间节点 | 2.5V至4.2V | 均衡器中端口、Cell2采样参考端 |
| 总负极 | 0V | 均衡器低端口、MCU系统地、所有采样地 |
我在原理图上把这三个节点分别引到均衡器对应的功率端口,飞渡电容按数据手册推荐容值接好。这里最容易忽略的是:电池的中间节点并不等于系统地,它相对系统地有约3V电位差。后续所有采样电路和控制电路都要围绕这个事实设计,否则第二节电芯的电压根本测不准,均衡策略也就失去了数据基础。
2.2 两路分压网络:参数设计要覆盖最高总压
电压采样是这套系统的眼睛。STM32F303RE的ADC参考电压是3.3V,而2S三元锂电的总正极可能到8.4V,磷酸铁锂也能到7.3V,直接衰减一半都会超量程,所以两路采样网络必须分开设计。
中间节点那一路只测单节电芯电压,我用两颗100kΩ电阻做1/2分压,最高4.2V对应ADC引脚2.1V,留有足够安全余量。总正极那一路测的是两节电芯的串联总压,我用200kΩ上电阻加100kΩ下电阻做1/3分压,8.4V对应ADC引脚2.8V,同样低于3.3V。两路都并联一颗100nF电容到本地地,构成RC低通滤波器,也作为ADC采样时的电荷蓄水池。分压电阻的直流功耗很小:中间节点一路约21µA,总正极一路约28µA,对储能系统来说可以忽略。
2.3 MCU如何获得均衡控制权
MP2642GR-Z 可以自主均衡,但我们要的是"该均衡才均衡",所以必须让MCU拥有最终控制权。如果芯片自带使能引脚,直接用一个GPIO控制;如果手上的芯片不带外部使能,就在芯片电源输入端串一个P沟道MOS管,GPIO经过三极管驱动MOS管栅极。P-MOS栅极低电平导通,高电平或悬空时断开,MCU上电默认状态下均衡器保持断电,避免开机瞬间误均衡。
我同时把这个MOS通路设计成紧急熔断手段。软件一旦判到过温、过压或者均衡超时,直接拉高GPIO切断均衡器电源,既不依赖芯片内部逻辑,也不怕程序跑飞导致均衡失控。控制通路的状态读取我留了一个GPIO引脚,接在均衡器的状态输出上,方便记录均衡是否实际在运行,不接也不影响主功能。
3. 一个绕不开的设计题:怎么准确采出第二节电芯的电压
3.1 单端ADC直接采Cell2会产生共模问题
很多人第一次画2S采样电路时会想:我用一个分压网络跨在Cell2两端,分压点直接接ADC就行。这个思路在Cell1上没毛病,但在Cell2上行不通。Cell2的负端是中间节点,它对系统地有3V多电压;分压后的信号叠加在这3V共模电压上,输出可能到5V以上,而ADC的负输入是系统地,引脚根本承受不了这个电压。
换句话说,STM32F303RE的ADC是单端结构,你只能测量"某个节点相对地"的电压,不能直接测量"两个悬浮节点之间"的差分电压。Cell2的正负极都不在地电位上,必须换一种采样思路。
3.2 两节点差分计算法以及精度补偿
我在板上最终采用了最简单的两节点差分计算。一共采两路对地电压:中间节点分压值V_mid_adc和总正极分压值V_top_adc。真实电压分别为:
- V_mid = V_mid_adc × 2
- V_top = V_top_adc × 3
- Cell2电压 = V_top - V_mid
这个方案不增加任何运放器件,硬件可靠性很好,但代价是分辨率有所损失。总正极通道满量程对应9.9V实际电压,单个LSB约2.4mV;两个大数相减后量化误差还会叠加。为了把精度提回来,我让F303对每条通道连续采样32次,丢弃开头两次,剩余30次先取中位数再取平均值。实测过采样后两节电压差读数波动能稳定在±5mV以内,对均衡控制来说完全够用。
3.3 什么情况才需要上差分运放
如果模组以后要扩成3S、4S甚至更高串数,总电压继续升高,两节点差分计算的分辨率损失会越来越严重。这时候我建议改用真正的差分采样——用仪表放大器或运放差分配置把Cell2的差分电压直接转换成对地单端电压,再送进ADC。
STM32F303RE片内集成了运算放大器,可以配合外部精密电阻做差分转单端,省掉一颗独立运放。但内部运放的配置和校准会带来额外复杂度,我的建议是先把两节点差分计算版本跑通、跑稳定,再根据最终精度需求决定是否升级。毕竟均衡控制要的电压精度和电量计量要的是两回事,不能一概而论。
4. 嵌入式软件思路:采样滤波、均衡状态机与保护逻辑
4.1 F303内部ADC的采样配置细节
代码是工程里的实际逻辑简化示意,重点在于三个配置点:采样周期必须够长、连续转换模式要开启、通道切换后要有废弃采样值的动作。
static void adc_config(void) { ADC_InitTypeDef ADC_InitStructure; ADC_StructInit(&ADC_InitStructure); /* 关闭外部触发,使用连续转换模式 */ ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; /* 高阻分压网络要求最长的采样时间 */ ADC_InitStructure.ADC_SamplingTimeCommon1 = ADC_SamplingTime_601Cycles5; ADC_Init(ADC1, &ADC_InitStructure); ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 1, ADC_SamplingTime_601Cycles5); ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 2, ADC_SamplingTime_601Cycles5); ADC_Cmd(ADC1, ENABLE); } static void read_cell_voltages(uint16_t *v_mid_raw, uint16_t *v_top_raw) { uint32_t sum_mid = 0, sum_top = 0; uint8_t i; ADC_SoftwareStartConv(ADC1); for (i = 0; i < 32; i++) { while (!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)) { /* 等待转换结束 */ } if (i >= 2) { sum_mid += ADC_GetConversionValue(ADC1); } /* 再读取第二通道时同样做首值丢弃,代码省略实际DMA方式 */ } *v_mid_raw = sum_mid / 30; *v_top_raw = 0; }这里解释一个关键逻辑:为什么采样周期要拉到601.5个ADC时钟?因为分压网络源阻抗高达50kΩ到66kΩ,ADC内部采样电容充电需要时间。虽然外部的100nF电容分担了大部分瞬时电荷,但长采样周期仍能把残余误差压到最低。通道切换后的第一次转换结果通常会受电容电荷重新分配影响,所以我在每次循环里都丢弃前两次采样值。
4.2 均衡状态机的设计:滞回是防止抖动的关键
均衡不能简单地"压差超过阈值就开,低于阈值就关"。直接这么做会让均衡器在阈值附近反复启停,每次开关都带来一次采样毛刺和电流冲击。我用了一个带滞回的状态机:
| 状态 | 进入条件 | 主要动作 | 退出条件 |
|---|---|---|---|
| STANDBY | 上电或者保护复位 | 均衡器断电,LED慢闪 | 电池电压有效且温度正常 |
| MEASURE | 电压采集完成 | 连续采样并滤波 | 采样有效,进入决策 |
| BALANCE | 压差大于启动阈值 | 均衡器通电,记录均衡时长 | 压差低于停止阈值或超时 |
| FAULT | 过压、欠压、过温、超时 | 均衡器断电,LED常亮 | 人工复位或故障消除 |
核心决策伪代码也很直接:
typedef enum { STANDBY, MEASURE, BALANCE, FAULT } sys_state_t; void balance_decision(void) { float v1 = get_cell1_voltage(); float v2 = get_cell2_voltage(); float gap = fabsf(v1 - v2); if (state == MEASURE) { if (gap > BALANCE_START_MV && temp_ok() && voltage_in_range()) { balancer_enable(ENABLE); state = BALANCE; } else { balancer_enable(DISABLE); state = STANDBY; } } else if (state == BALANCE) { if (gap < BALANCE_STOP_MV || balance_timeout()) { balancer_enable(DISABLE); state = STANDBY; } } }启动阈值我设为20mV,停止阈值设为5mV。中间这15mV的滞回窗口避免了均衡器在临界点反复跳动,也给采样噪声留出了充足余量。另一个重要策略是:均衡只在静置或浮充阶段开启,充放电过程中不做均衡。原因很简单,充放电时电芯电压本身就在快速变化,压差信号混入了很强的动态分量,阈值判断很容易误动作。
4.3 保护逻辑:均衡器不能一开了之
均衡的本质是把多余电量搬走,但如果系统本身出了问题,均衡只会帮倒忙。我在这套板上做了四层基础保护:
| 保护项 | 设定阈值 | 动作 |
|---|---|---|
| 单节过压 | 3.65V(铁锂) | 停止均衡并告警 |
| 单节欠压 | 2.70V告警,2.50V锁定 | 停止均衡,禁止放电 |
| 模组过温 | 45°C | 暂停均衡,等待温度回落 |
| 均衡超时 | 240分钟 | 强制关闭均衡,置故障位 |
过压保护尤其要放在均衡启动之前判断:如果高电压那节已经到3.65V,此时不应该再把高电芯的能量搬给低电芯,而是应该直接告警。均衡超时这个参数很多人会漏掉,实际中我遇到过压差收敛很慢、芯片一直在临界状态空转的情况,没有超时保护的话,均衡器可能会一直满载跑到电池放空。
5. 实测数据与调参过程
5.1 测试平台与初始状态
调试用的测试条件我整理成了一张表,分别用一组老化电芯和一组新电芯验证均衡效果:
| 测试项目 | 老化电芯组 | 新电芯组 |
|---|---|---|
| 电池类型 | 磷酸铁锂2S | 磷酸铁锂2S |
| 标称容量 | 10Ah | 10Ah |
| 初始V1 | 3.354V | 3.372V |
| 初始V2 | 3.298V | 3.364V |
| 初始压差 | 56mV | 8mV |
| 环境温度 | 25°C | 25°C |
两组都让均衡器连续工作,MCU每秒记录一次电压,最终数据按时间序列拉出来。
5.2 老化电芯组的均衡收敛曲线
老化电芯组的数据很有代表性,我截取前120分钟的记录:
| 时间(min) | V1(V) | V2(V) | ΔV(mV) | 均衡状态 |
|---|---|---|---|---|
| 0 | 3.354 | 3.298 | 56 | 开启 |
| 30 | 3.360 | 3.329 | 31 | 开启 |
| 60 | 3.366 | 3.348 | 18 | 开启 |
| 90 | 3.370 | 3.359 | 11 | 开启 |
| 120 | 3.373 | 3.368 | 5 | 停止 |
前60分钟压差从56mV快速降到18mV,后60分钟下降速度明显变缓。原因在于MP2642GR-Z的均衡电流和压差成正比,压差越大,单位时间搬运的电荷量越多;压差缩小后搬运速率自然降低,最后收敛到5mV左右,低于我们设定的停止阈值,MCU断开均衡器。
新电芯组的压差本来只有8mV,开启均衡后大概15分钟就到了3mV,之后基本维持在4到5mV的水平,波动主要来自采样噪声。从数据看,主动均衡对老化电池的"修正能力"很强,对新电池则更多起到防患于未然的作用。
5.3 四个直接影响均衡效果的参数
第一个是启动阈值。设太高会让小压差长期得不到处理,设太低又容易被噪声误触发。对我来说20mV是一个适合铁锂体系的起始值,三元电池可以适当放宽到30mV,因为三元电芯在满充末端的电压变化更快。
第二个是停止阈值。停止阈值必须明显低于启动阈值,形成滞回。我用的5mV已经接近采样精度的极限,如果继续往下压,可能出现均衡器永远停不下来的情况。
第三个是采样滤波强度。32次采样加中值平均对噪声有很好的抑制,但代价是响应变慢。均衡控制对实时性要求不高,所以我宁可多采几次,也不愿意拿一个抖动剧烈的压差去做决策。
第四个是温度阈值。低温状态下电芯内阻变大,真实电压和开路电压之间存在很大偏差,这时候做均衡容易做出错误判断。我的经验是温度低于0°C时干脆禁止均衡,等温度回升再恢复,比直接加大均衡电流更安全。
6. 踩坑复盘:参考地、开关噪声与热设计
6.1 Cell2电压总是偏低:中间节点不能当地用
第一次打样回来,编好程序一测量,Cell2电压总是比万用表读数低30到50mV,而且随着均衡电流增大偏差会变大。排查了一整天才发现,问题出在PCB上Cell2采样分压网络的下端电阻被接到了系统地,而不是接到中间节点。
这是个非常容易犯的错误。从原理图上看,Cell2的分压网络跨在中间节点和总正极之间,下端应该接中间节点。如果它被错误地接到系统地,ADC读到的是总正极和系统地之间的电压,而中间节点本身就是悬浮的3V多,两节分压后的值自然对不上。实际教训是:每一路采样分压网络的地端必须跟着被采样节点走,不能想当然全接到总负极。布板时还要把采样线单独走细线,远离均衡器的功率回流路径,否则大电流瞬态会在采样地上制造压降,让ADC读数跟着跳。
6.2 均衡器一开,ADC采样数据像心电图
另一个让我折腾了很久的问题是:MP2642GR-Z一旦开始工作,MCU读到的电压值就开始乱跳,压差一会儿显示100mV,一会儿又只有5mV。这是开关电容均衡器的固有个性——内部MOS管高频开关,飞渡电容充放电瞬间会产生电流尖峰,如果采样时刻正好和开关沿撞在一起,ADC就会被污染。
解决套路是PCB和软件两头堵。PCB上我把采样区域的地独立铺了一块,和均衡器功率地单点连接;软件上则规定均衡器刚启动时先等50ms再开始采样,同时在每次状态切换后丢弃前两个采样值。更彻底的做法是用定时器触发ADC,让采样时刻和均衡器的开关频率错开,不过这个需要对芯片内部开关频率有准确掌握,做起来相对麻烦。
6.3 均衡芯片发热:铜皮就是散热器
负载均衡电流跑起来之后,MP2642GR-Z 芯片表面温度上升得比我预期快。连续均衡一个多小时,用手摸已经明显烫手,后来在芯片底部和四周加大了铜箔面积,并且打了一排过孔到背面覆铜,温度才算压下来。
这个问题的本质是均衡功率被电阻损耗了一部分,特别是在压差大、电流大的阶段,芯片自身功耗不可忽略。给开关电容均衡器做热设计时,不能按普通信号IC的标准对待,要留出足够散热空间。另外分压电阻尽量离芯片远一点,否则芯片发热会让采样电阻阻值漂移,直接影响电压测量精度。备用电源设备经常在密闭外壳里使用,热设计余量一定要比平时留得大。
实际上,我在这个项目里体会最深的一点是:主动均衡的核心价值不是让两节电池"看起来电压一致",而是让整个模组在几百上千次循环之后仍然能保持安全。MP2642GR-Z把能量搬移这个脏活累活干掉了,STM32F303RE把判断和保护的脑力活接住了,剩下真正决定成败的反而是地线怎么走、采样怎么滤、芯片底下有没有足够铜皮这些朴实细节。如果你也在做2S模组的均衡方案,建议先把这三件事处理干净,再去研究更复杂的均衡算法,大概率能少走不少弯路。