1. 从两个串联电芯说起:为什么被动均衡在储能BMS里依然是主流选择
储能系统和备用电源系统里,电池组几乎都是“一串多并”的结构。拿最常见的48V备用电源来说,通常是15串磷酸铁锂或者13串三元,而每一串内部又可能并联若干电芯。问题就出在这里:串联的每一节电芯,出厂容量、内阻、自放电率都有微小差异,用久了差异还会被放大。充电时,容量小的那节先到上限电压,BMS如果继续充,它就过充;放电时,容量小的那节先到下限,BMS如果继续放,它就过放。整组电池的可用容量,被最弱的那节电芯卡死。
均衡要解决的就是这个“木桶短板”问题。方案分两大流派:被动均衡和主动均衡。被动均衡说白了就是给每节电芯并一个电阻加开关,谁电压高了就让谁通过电阻放电,把多出来的能量以热量形式消耗掉。主动均衡则是把高电压电芯的能量搬到低电压电芯去,效率高但电路复杂、成本高、故障点多。
在储能和备用电源这类场景里,我个人的经验是:被动均衡依然是绝大多数项目的首选。原因很实在——成本低、可靠性高、控制逻辑简单、不需要额外的储能元件(电感、电容、变压器)。储能系统动辄几十上百串,每串都上主动均衡,BOM成本会失控;备用电源系统常年浮充,电芯差异本来就小,被动均衡那点发热量完全可以接受。所以标题里“对两个串联电池单元进行均衡”这个需求,本质上是一个小串数、低成本、高可靠的均衡电路设计问题。
那为什么选MP2642GR-Z这颗芯片?它是一颗集成度很高的电池管理AFE(模拟前端),支持多串电池的电压采集和被动均衡控制。配合STM32F745VG这颗Cortex-M7内核的高性能MCU,可以做到采样、判断、均衡、保护一条龙。下面我就把这套方案从芯片选型、硬件设计、均衡策略到代码实现,完整拆一遍。
2. MP2642GR-Z 与 STM32F745VG 的分工:谁干什么,为什么这么分
2.1 MP2642GR-Z 在均衡回路里的角色
MP2642GR-Z 是一颗多串电池管理AFE,核心能力包括:多通道电芯电压采集、内部均衡开关驱动、过压欠压保护、温度监测接口,以及和主控之间的通信接口(通常是SPI或I2C)。在均衡这件事上,它负责的是**“执行层”**——也就是真正去打开或关闭某节电芯的均衡MOSFET。
它内部集成了均衡开关,外部只需要在每节电芯两端接一个均衡电阻。当某节电芯电压超过设定阈值,MCU通过通信接口告诉AFE“打开第N节的均衡开关”,AFE就把对应电芯的均衡电阻接入回路,电芯通过电阻放电。整个过程MCU不直接驱动功率器件,只发指令,这样MCU的GPIO不会被大电流干扰,系统更稳。
这里有个关键点:MP2642GR-Z的均衡开关是内置的,但均衡电阻是外置的。电阻选多大,直接决定均衡电流和发热量。这个后面会详细算。
2.2 STM32F745VG 为什么适合做均衡主控
STM32F745VG 是STM32F7系列里的高性能型号,Cortex-M7内核,主频能到216MHz,带FPU和DSP指令,Flash 1MB,SRAM 320KB。拿它做BMS主控,性能是绰绰有余的。但选它不只是因为性能,更关键的是外设资源:
- 多路SPI/I2C:和AFE通信,如果系统有多颗AFE级联,SPI的片选管理很方便。
- 多路ADC:可以采集均衡电阻附近的温度、系统总压等模拟量。
- 多路定时器:做均衡的PWM控制或者超时保护。
- CAN接口:储能系统里BMS和PCS、EMS通信,CAN几乎是标配。
- 足够的GPIO:控制继电器、风扇、指示灯等外围。
用F745做均衡主控,逻辑上就是:周期性读取每节电芯电压 → 判断哪节需要均衡 → 通过AFE打开对应均衡开关 → 监控温度和总压 → 异常时关闭均衡并报警。这个流程不复杂,但细节很多,下面逐层展开。
2.3 两颗芯片的通信接口设计要点
MP2642GR-Z 和 STM32F745VG 之间通常走SPI。SPI的好处是速度快、时序确定,适合周期性轮询电芯电压。接线上有几个坑我踩过:
- 片选信号要加下拉:AFE的CS如果浮空,上电瞬间可能误触发,导致配置寄存器被写乱。加一个10k下拉到地,稳。
- SPI时钟极性相位要匹配:MP2642GR-Z一般支持SPI Mode 0或Mode 3,具体看数据手册。STM32的SPI配置里CPOL和CPHA设错,读出来的电压全是0或者乱码。
- 通信线要远离均衡电阻:均衡电阻工作时会发热,走线太近会引入热噪声,虽然SPI是数字信号,但长期高温会加速线材老化。布局时SPI走线尽量走内层,包地处理。
3. 两个串联电芯的被动均衡电路:电阻怎么选,热量怎么算
3.1 均衡电阻的取值逻辑
两个串联电芯,每节标称3.7V(三元)或3.2V(铁锂),均衡电阻接在电芯正负极之间,通过AFE内部开关控制通断。电阻取值要平衡两个矛盾:均衡电流越大,均衡越快,但发热越大。
先看均衡电流。假设电芯电压4.0V,均衡电阻R,均衡电流I = V/R。如果R取100Ω,I = 40mA;R取33Ω,I ≈ 121mA;R取10Ω,I = 400mA。
对于两个串联的小电池组,我的经验是均衡电流取50mA到150mA之间比较合适。太小了均衡慢,一节电芯差100mV可能要均衡好几个小时;太大了电阻发热严重,PCB局部温升会影响旁边电芯的电压采样精度。
以100mA为目标,电芯4.0V,R = 4.0V / 0.1A = 40Ω。标准阻值选39Ω或43Ω。选39Ω时,I ≈ 102mA。
3.2 电阻功率计算与降额
功率P = V² / R = 4.0² / 39 ≈ 0.41W。这是持续均衡时的功耗。但实际均衡不是一直开着的,占空比取决于电压差。不过设计时按最坏情况算,电阻额定功率至少要1W以上,而且要做降额。
我一般选2W的金属膜电阻或贴片合金电阻,实际功耗0.41W,降额到20%左右,温升可控。如果用0805或1206的贴片电阻,额定功率只有0.125W或0.25W,直接烧。必须用2512封装或者直插的2W电阻。
注意:电阻的温漂会影响阻值,进而影响均衡电流。金属膜电阻温漂一般50ppm/℃,合金电阻能到20ppm/℃甚至更低。如果对均衡一致性要求高,选合金电阻。
3.3 散热与布局的实操经验
两个电芯的均衡电阻,功耗加起来不到1W,看起来不大,但如果是密闭的备用电源机箱,热量散不出去,局部温度能到70℃以上。我做过一个项目,均衡电阻贴着电芯布置,结果电芯NTC采到的温度比实际电芯温度高了8℃,导致温度保护误触发。
后来改布局:均衡电阻远离电芯和NTC,放在PCB边缘,背面铺铜散热,必要时加过孔到内层地平面。如果空间允许,电阻之间留至少5mm间距,不要并排紧贴。
还有一个细节:均衡电阻的走线要开窗露铜,增加散热面积。很多新手直接盖绿油,热量全憋在电阻下面。
4. 均衡策略:什么时候开,什么时候关,怎么防止来回震荡
4.1 电压阈值的设定
均衡的触发条件通常是:最高电芯电压 - 最低电芯电压 > 阈值,并且最高电芯电压 > 均衡起始电压。两个条件同时满足才开均衡。
阈值怎么定?太小了频繁开关,均衡开关寿命受影响;太大了均衡效果差。对于两个串联电芯,我一般设30mV到50mV。起始电压设3.9V(三元)或3.4V(铁锂),也就是电芯接近充满时才均衡,避免在放电中途做无意义的均衡。
这里有个反直觉的点:不是电压差一超过阈值就立刻开均衡。因为电芯在充放电过程中,电压本身就在动态变化,内阻导致的压差可能瞬间超过阈值,但那是暂态,不是真正的容量差异。所以要做滤波和延时确认。
4.2 滤波与延时确认的实现
STM32F745VG 读AFE的电压,我一般做两级处理:
第一级:滑动平均滤波。每节电芯连续采8次,去掉最大最小,剩下6次取平均。这样能滤掉ADC的随机噪声。
第二级:持续时间确认。电压差超过阈值后,不是立刻开均衡,而是连续确认比如10秒,10秒内每次都超过阈值,才真正打开。关闭时同理,电压差降到阈值以下并持续10秒,才关闭。
这个逻辑用STM32的定时器中断实现最方便。比如1秒进一次中断,维护一个计数器,超过10次就动作。
4.3 防止均衡震荡的滞回设计
如果只用单一阈值,会出现这种情况:电压差降到49mV,均衡关;过一会又升到51mV,均衡开。来回震荡,均衡开关频繁动作,寿命骤减。
解决办法是滞回:开启阈值设50mV,关闭阈值设20mV。也就是电压差超过50mV才开,开了之后要降到20mV以下才关。中间30mV的区间是“保持当前状态”。这样就不会在阈值附近反复横跳。
代码里用一个状态变量记录当前均衡是开还是关,然后根据状态选择不同的比较阈值。
5. 基于STM32F745VG的均衡控制代码框架
5.1 电压采集与数据管理
先定义数据结构。两个电芯,用数组存电压、均衡状态、温度。
typedef struct { float voltage[2]; // 两节电芯电压 float temperature[2]; // 两节电芯温度 uint8_t balance_state[2]; // 0=关闭 1=开启 uint32_t balance_timer[2]; // 均衡持续时间计数 } BatteryPack_t; BatteryPack_t pack;采集函数通过SPI读MP2642GR-Z的电压寄存器,转换成实际电压值。MP2642GR-Z的电压寄存器一般是14位或16位,LSB对应比如0.1mV或0.2mV,具体看手册。转换公式:
float raw_to_voltage(uint16_t raw) { return raw * 0.0001f; // 假设LSB=0.1mV }读回来之后做滑动平均。我一般用一个环形缓冲区存最近8次采样。
5.2 均衡决策函数
决策函数每秒调用一次,输入是当前电压,输出是均衡开关指令。
#define BALANCE_ON_THRESHOLD 0.050f // 50mV #define BALANCE_OFF_THRESHOLD 0.020f // 20mV #define BALANCE_START_VOLTAGE 3.900f // 三元电芯 #define CONFIRM_COUNT 10 // 连续10秒确认 void balance_decision(void) { float vmax = fmaxf(pack.voltage[0], pack.voltage[1]); float vmin = fminf(pack.voltage[0], pack.voltage[1]); float diff = vmax - vmin; uint8_t high_cell = (pack.voltage[0] > pack.voltage[1]) ? 0 : 1; for (int i = 0; i < 2; i++) { if (pack.balance_state[i] == 0) { // 当前关闭,判断是否开启 if (diff > BALANCE_ON_THRESHOLD && vmax > BALANCE_START_VOLTAGE) { pack.balance_timer[i]++; if (pack.balance_timer[i] >= CONFIRM_COUNT && i == high_cell) { pack.balance_state[i] = 1; pack.balance_timer[i] = 0; afe_set_balance(i, 1); } } else { pack.balance_timer[i] = 0; } } else { // 当前开启,判断是否关闭 if (diff < BALANCE_OFF_THRESHOLD || vmax < BALANCE_START_VOLTAGE) { pack.balance_timer[i]++; if (pack.balance_timer[i] >= CONFIRM_COUNT) { pack.balance_state[i] = 0; pack.balance_timer[i] = 0; afe_set_balance(i, 0); } } else { pack.balance_timer[i] = 0; } } } }这段代码的核心是状态机+滞回+延时确认。注意i == high_cell这个条件,只有高电压那节才开均衡,低电压那节不开。
5.3 安全保护:温度、总压、通信超时
均衡不是无条件开的。必须加保护:
- 温度保护:电芯温度超过45℃或低于0℃,禁止均衡。均衡电阻附近温度超过85℃,立即关闭所有均衡。
- 总压保护:总压超过充电上限或低于放电下限,禁止均衡。
- 通信超时:如果STM32和AFE通信连续3次失败,关闭所有均衡,进入安全状态。
这些保护逻辑放在均衡决策之前,任何一条不满足,直接强制关闭所有均衡开关。
uint8_t balance_safety_check(void) { if (pack.temperature[0] > 45.0f || pack.temperature[1] > 45.0f) return 0; if (pack.temperature[0] < 0.0f || pack.temperature[1] < 0.0f) return 0; if (total_voltage > MAX_TOTAL_VOLTAGE) return 0; if (total_voltage < MIN_TOTAL_VOLTAGE) return 0; if (afe_comm_fail_count >= 3) return 0; return 1; }6. 实测中遇到的三个坑和我的处理方式
6.1 均衡开启后电压采样跳变
第一次测试时发现,均衡一打开,被均衡那节电芯的采样电压立刻掉了20mV。一开始以为是电芯真的在放电,后来才想明白:均衡电流在走线和AFE内部开关上产生了压降,AFE采到的电压是“电芯电压减去均衡回路压降”,所以读数偏低。
这个问题的处理方式有两种:一是均衡开启时,对均衡那节电芯的电压做补偿,补偿值等于均衡电流乘以回路电阻;二是均衡开启后,暂时用均衡前的电压做决策,等均衡关闭后再更新。我选的是第二种,简单可靠。具体做法是:均衡状态为1时,电压值保持上一次均衡关闭时的值,不更新。
6.2 两节电芯均衡不同步导致的总压波动
两个电芯如果同时开均衡,总压会瞬间掉一点,因为两路均衡电流同时拉。如果系统对总压敏感(比如备用电源的浮充电压控制),这个波动可能触发误报警。
我的处理是分时均衡:同一时间只开一节电芯的均衡,两节轮流开,比如第一节开1秒,关;第二节开1秒,关。这样总压波动减半,而且均衡效果几乎不受影响,因为均衡是长时间过程,不差那1秒。
6.3 均衡电阻发热导致NTC误报
前面提过,均衡电阻贴着NTC,温度采高了。除了布局上分开,软件上也可以做补偿:根据均衡状态和持续时间,对NTC读数做一个修正。但这是治标,治本是布局分开。我最后的方案是NTC用引线拉到电芯表面,均衡电阻留在PCB上,物理隔离。
7. 这套方案能扩展到哪里,以及选型时的几个判断依据
两个串联电芯的均衡是最小系统,但这套架构可以往上扩。MP2642GR-Z本身支持多串,STM32F745VG的SPI可以挂多颗AFE级联。如果做15串的48V储能,就是7颗或8颗AFE级联,STM32轮询读取所有电芯电压,均衡逻辑从2节扩展到15节,核心代码框架不变,只是数组变大、决策循环变长。
选型时我的判断依据是:
- 串数少、成本敏感:被动均衡+AFE内置开关,MP2642GR-Z这类芯片最合适。
- 串数多、对效率有要求:考虑主动均衡,但BOM和复杂度会上一个台阶。
- 主控性能:STM32F745VG对于纯均衡控制是过剩的,但如果还要跑CAN通信、SOC估算、数据记录,F745的余量就很舒服。如果只做均衡,F103也能凑合,但ADC精度和通信外设会紧张。
最后说一个实际体会:均衡策略的参数没有万能值。50mV阈值、100mA电流、10秒确认,这些是我在备用电源场景下的经验值。如果你的电芯一致性特别好,阈值可以降到20mV;如果电芯老化严重,阈值可能要放到80mV,否则均衡永远追不上差异。参数要跟着电芯状态走,最好在BMS里留一个参数配置接口,现场能调。