上一套储能柜子调试到深夜,两个串联的磷酸铁锂电池单元压差到了80mV,容量偏小的那个先触发了欠压保护,整个备用电源链路直接切旁路。这种场景在储能和备用电源系统里太常见了,串联电池组的一致性问题是绕不开的坎。这个项目就是用一颗MP2642GR-Z功率芯片,配一颗MKV46F128VLH16做主控,针对两个串联电池单元做主动均衡,把“容量小的吃亏”这个问题从源头上解决掉。整篇内容包括方案选型逻辑、硬件参数计算、软件状态机设计,以及现场调试中踩过的坑,适合正在做BMS、储能控制器或者备用电源板的朋友参考。
1. 为什么储能系统需要做电池均衡:需求拆解与方案背景
1.1 串联电池组不一致性问题是怎么产生的
两个电池在出厂那一刻,容量、内阻、自放电率就不可能完全一致。哪怕同一批次、同一工艺,分容柜也会给出几个百分点的离散度。平时这个差异不明显,但电池进入循环之后,衰减速率不一样,容量差会被慢慢放大。储能系统的电池长期处于浮充和周期放电状态,高温季节还会加速这个分化过程。
串联回路里电流处处相等,充进去的电量、放出来的电量对每一节都相同,但容量小的那节SOC变化更快。放电末期,小容量单元先到下限电压,系统为了保护电池不得不整体停止放电,这时候大容量单元明明还有电量却用不出来;充电末期反过来,小容量单元先充满,继续充电就会过压,系统又得降低充电功率。一来二去,整组电池的可用容量被最短的那块板子锁死,这就是所谓的“木桶效应”。
在备用电源场景里这个问题更隐蔽。市电正常时电池浮充,压差一般不会太大,但等到真正停电切到电池放电时,差异立刻暴露。之前遇到的那台设备就是典型例子,两组串联磷酸铁锂,放电到一半,其中一个单元先掉到2.5V保护,另一组还有3.1V,带载能力直接腰斩。这样的故障如果发生在关键负载上,损失就不是一点半点。
1.2 被动均衡与主动均衡的取舍
均衡方案大体分两类:被动均衡和主动均衡。
被动均衡的做法是给每个电池单元并联一个放电电阻和开关,发现哪个电压高就把它多余的电量以热量形式放掉。优点是电路简单、成本低,缺点是效率差、发热明显。拿100Ah的磷酸铁锂电池来说,如果要纠正5%的SOC偏差,相当于要白白耗散掉几十瓦时的能量,放在储能机柜里就是实打实的热量负担,而且均衡电流通常只有0.1A到0.5A,一次均衡可能要持续十几个小时。
主动均衡则不同,它的核心思想是能量搬移:把高电压单元的能量转移到低电压单元,而不是烧掉。效率高、速度快、发热低,非常适合储能和备用电源这种单体容量大、对损耗敏感的场合。项目标题里同时出现了MP2642GR-Z和MKV46F128VLH16,前者是有功率变换能力的芯片,后者是负责采样和策略的MCU,很明显走的就是主动均衡路线,而不是简单并联电阻的被动方案。
2. 核心器件选型与系统架构设计
2.1 MP2642GR-Z 在系统里扮演什么角色
MP2642GR-Z在整个系统里定位是功率级核心,也就是“受控的能量搬运通道”。我把它理解成一个集成了功率开关、具备电流/电压调节能力的功率管理芯片,通过使能引脚和PWM/PFM控制信号来执行能量转移。MCU不会直接去搬电流,它只负责采样和发指令,真正干活的是这颗功率芯片。
主动均衡里有个基本动作:要从高电压单元取能量、经过功率级缓冲、再送进低电压单元。这期间需要控制电流大小,避免对电池造成冲击。MP2642GR-Z的使能脚很适合做开关控制,反馈回路的配置可以设定目标输出电压/电流,而MCU通过PWM调节控制参考,就能动态改变均衡电流。实测下来,这套控制方式响应够快,能让均衡电流稳定在目标值附近,不会有明显的过冲。
选这颗芯片而不是随便找一个普通DC-DC,主要看中几点:一是集成度高,外围器件少,在储能控制板上能省下不少布局面积;二是开关频率和效率在电池电压区间内有保障,均衡本身就是低功率场景,但如果损耗太大,转换过程产生的热量依然会让板子局部升温;三是使能时序简单,硬件上和MCU的GPIO对接非常直接,对系统的故障兜底处理很有利。
2.2 MKV46F128VLH16 为什么适合做主控
MKV46F128VLH16是面向功率转换和电机控制领域的微控制器,Cortex-M4F内核,带浮点单元,128KB Flash和16KB容量级别的RAM。做均衡主控需要什么?主要是高精度ADC采样、可控的PWM输出和稳定的实时控制能力,这些正好都是它擅长的方向。
先说ADC。均衡算法对单节电池电压的分辨率要求比较高,磷酸铁锂的电压平台很平,两三毫伏的差异就可能对应不小的SOC偏差,ADC位数不够或者采样抖动大,算法就没法正常工作。MKV46带有多个独立ADC模块,可以同时启动多通道采样,省去逐通道轮询的时间差,对串联电池组的电压测量特别有利。
再说PWM和定时器。均衡电流的闭环调节需要一路或者多路PWM信号,FTM定时器生成PWM非常方便,频率和占空比都能独立配置。另外Cortex-M4F的运算能力跑个滤波算法和状态机绰绰有余,中断响应也够快,不会出现采样数据还没取走就被均衡逻辑打断的尴尬。
选型时也想过用更低成本的通用单片机,但仔细算下来不划算。均衡逻辑本身不复杂,难的是保证长期运行的可靠性。KV系列在设计上就比较偏向功率控制场景,内部模块的配合成熟,官方例程也全,开发周期能缩短不少。对一个需要快速量产的项目来说,这比省那几块钱重要得多。
2.3 系统整体拓扑与信号流
整个系统的连接关系可以这样描述:两节电池串联之后,正负输出端连接到负载和充电回路,中间节点作为均衡能量搬移的桥接点。MP2642GR-Z跨接在两个电池单元之间,它的输入侧连接到电压较高的电池单元,输出侧经过储能电感和滤波电容连接到电压较低的电池单元。MKV46F128VLH16通过分压网络采集每个电池单元的电压,通过采样电阻和运放采集均衡电流,经过内部算法计算后,输出使能信号和PWM给MP2642GR-Z,控制能量搬移的方向和大小。
信号流向是单向且清晰的:电池电压 -> 分压电阻 -> ADC -> 软件滤波 -> 均衡状态机 -> PWM/使能 -> 功率级 -> 能量搬移。这样分层设计的好处是每一级都可以独立调试。硬件工程师可以先不烧录均衡算法,单独采集电压确认精度;软件工程师则可以用信号发生器模拟电压输入,验证状态机逻辑,而不用依赖真实电池。
另外还有两路温度采样,一路贴在电池表面,一路贴在功率级电感或者MOS附近。温度数据除了用于保护,也可以辅助判断均衡是否在正常工作,比如电流异常增大时功率级温度会快速上升,这比单纯看电流传感器更加直观。
3. 硬件电路细节与关键参数计算
3.1 电压采样电路,别让共地问题害了你
两节电池串联,中间的节点是浮动的,测量第二节电池电压时千万不要想当然地用单端分压直接接到ADC引脚。如果两节电池都是12V那种高压单元,分压比例设计不当,轻则采样不准,重则烧毁ADC输入。
以常见的磷酸铁锂单体为例,工作电压范围大约在2.5V到3.65V之间。我用的分压方案是100kΩ和100kΩ精密电阻,把电池电压衰减到一半。MKV46的ADC参考电压设为2.5V,这样单节电池满量程对应5V,覆盖磷酸铁锂的电压范围绰绰有余。12位ADC在2.5V参考下的原始分辨率约0.61mV,折算到电池端大约1.22mV,做两个串联单元的压差判断已经够用。
第二节电池的采样要特别注意参考地。我实际采用的是差分采样思路:第一节电池从正极到电池组负极直接分压,第二节电池的正极和负极分别经过高阻分压网络后,送入MCU的两个ADC通道,在软件里做差分计算。如果只用单端ADC,就必须加仪表差分放大器把第二节电压抬到地对地,否则会引入高达几百毫伏的共模误差。某次调试时就吃过这个亏,第二节电池电压显示比实际高了200多mV,均衡逻辑误判成严重过压,差点触发保护停机,后来换成差分采样才恢复正常。
分压网络后面必须加RC滤波,我用的1kΩ串联电阻加100nF电容,截止频率大约1.6kHz,可以有效滤掉功率级开关带来的纹波。这个RC参数不能随便加大,太大会拖慢采样响应,电池电压突变时跟踪不上,主动均衡启动瞬间容易误判。
3.2 均衡电流设计与功率路径计算
均衡电流选多大,直接关系到系统能在多长时间内把压差拉回来。电流太小,均衡形同虚设;电流太大,发热和电池应力都是问题。我按0.05C到0.1C的经验范围来取,对一个50Ah的磷酸铁锂电池单元,均衡电流设计在2A到3A之间比较合适。
这里可以估算一下均衡时间。假设两个单元压差是50mV,对应磷酸铁锂的SOC偏差大约1%到2%,折算成电量就是0.5Ah到1Ah。如果均衡电流2A,理想情况下需要15到30分钟搬移完成。这个时间对备用电源系统完全可以接受,通常备用电源在浮充状态下有大量空闲时间,均衡并不需要像快充那样分秒必争。
电流采样我用采样电阻加运放的方式,采样电阻取10mΩ,运放增益设置成50倍。2A均衡电流流过采样电阻产生的压降是20mV,放大后是1V,正好落在ADC比较舒服的量程范围内。计算公式是:ADC电压 = I * 0.01 * 50,反向推电流就是读取电压除以0.5。这个放大倍数可以留一点余量,比如设计满量程对应4A电流,万一需要调高均衡电流,不用改硬件。
MP2642GR-Z的均衡电流由MCU的PWM占空比控制。这里要提一个工程细节:不要在上下电瞬间让PWM输出满占空比,否则电感和电池回路会出现电流尖峰。软件里要做软启动,先输出小幅值PWM,然后逐步抬高到目标占空比,整个过程大概持续100ms到200ms。第一次调试时没注意这一点,实测电流波形有明显的过冲,峰值达到设定值的1.5倍,后来加了软启动斜坡才压下来。
3.3 保护与失效兜底逻辑
均衡期间必须有一套完整的保护逻辑,否则功率级一旦失控,不仅电池受损,整个储能系统都可能出问题。
我设了四层保护。第一层是电压保护,单节电池电压超过3.65V立即停止均衡并告警,低于2.5V禁止启动均衡。第二层是电流保护,实际均衡电流超过设定值120%时,切断PWM输出。第三层是温度保护,电池表面温度超过55℃或者功率级温度超过85℃时,要么降额要么停机。第四层是超时保护,一次均衡运行超过60分钟强制停止,防止状态机卡在异常状态里。
硬件层面的兜底也很关键。均衡使能信号在MCU侧加了下拉电阻,MCU没有上电、处于复位状态或者程序跑飞时,使能引脚默认拉低,MP2642GR-Z不会误启动。再加上外部看门狗,MCU死机后看门狗超时复位,复位期间均衡保持关闭,从根源上避免了失控风险。这个设计虽然简单,但在现场设备上价值极高,备用电源系统经常无人值守,硬件兜底比软件写的再多都踏实。
4. 软件控制策略与均衡算法实现
4.1 均衡状态机划分
均衡算法我习惯用状态机来组织,而不是用一堆if嵌套堆逻辑。状态机清晰、可调试、可扩展,现场出现问题也容易定位。
整个系统分五个状态:
- IDLE:空闲状态,每100ms轮询一次ADC,计算两个电池单元的压差。压差超过启动阈值并且持续确认后,进入START_DELAY。
- START_DELAY:启动延时状态。压差连续10次采样(也就是持续1秒)都超过启动阈值,才进入BALANCING。这是为了滤掉电池动态波动引起的误触发。
- BALANCING:均衡执行状态。打开MP2642GR-Z使能,输出PWM,实时检测压差、电流和温度。压差降到停止阈值以下或满足停止条件时,进入STOP_DELAY。
- STOP_DELAY:停止延时状态。压差连续30次采样低于停止阈值,回到IDLE;如果压差又反弹,重新回到BALANCING。
- FAULT:故障状态。任何保护条件触发后进入,记录故障码,只有人工复位或者主机通过通讯命令清除才能退出。
用状态机的好处是每个状态都有明确的进入退出条件,调试时打印状态切换日志,一眼就能看出均衡卡在了哪里。某个晚上现场报告均衡不工作,远程看日志发现状态一直停留在START_DELAY,原因是压差在45mV和55mV之间波动,始终无法连续1秒满足启动条件,后来调整了启动阈值并加了滤波才解决。
4.2 电压采样滤波与校准,别让电池的动态特性骗了你
电池电压不是静止的,充放电时的端电压和开路电压差别很大。如果直接用瞬时电压判断压差,启动阈值设得再合理也会被噪声干扰。
我采用了三层处理。第一层是每组ADC数据连续采10次,去掉最大值和最小值后求平均,滤掉偶发尖峰。第二层是一阶低通滤波,公式是:filtered = alpha * new + (1 - alpha) * filtered,alpha取0.1。这个参数经过实测,能在响应速度和稳定性之间取得平衡,电压突变时需要大概100ms到200ms跟上,但对2Hz以上的纹波衰减很明显。第三层是工况感知:如果系统正处在充电状态,端电压整体偏高,我会把压差的启动阈值适当抬高;如果系统正在放电,则压低阈值。简单说,判断均衡该不该启动,不能用瞬时电压比,要用“相对一致”的电压水平比。
开路的静置电压才是最真实的SOC参考。备用电源系统切换测试时,电池往往要静置一段时间,我额外写了一个逻辑:检测到系统无充放电电流持续10分钟,就进入静置电压评估子程序,这个时候测出来的压差最有代表性。有一次均衡完成后压差显示只有15mV,但撤掉均衡后半小时压差又反弹到45mV,原因就是磷酸铁锂的开路电压回弹效应,静置评估帮我避开了这个坑。
4.3 迟滞策略,避免均衡左右横跳
迟滞是均衡控制里必不可少的设计。启动阈值和停止阈值不能一样,否则系统会在边界处反复启停,像个水泵一样喘振。
我的参数配置是:启动阈值50mV,停止阈值20mV,重新启动阈值80mV。这个窗口的思想是,均衡启动后要把压差压到一个明显低于启动阈值的水平再停,停止后即使电压回弹,只要不超过80mV,就不重新启动。回弹空间留了30mV,足够避开磷酸铁锂的电压回弹特性。
迟滞策略具体执行时还配合了最小运行时间。一次均衡启动之后,不管压差是否已经降到停止阈值,至少运行5分钟才允许停止。这个设定的原因在于MP2642GR-Z每次启停都会有一个热循环,如果均衡刚跑几十秒就停,芯片和电感反复热胀冷缩,长期看会降低可靠性。多跑几分钟多搬点能量,反而对系统更有利。
4.4 均衡算法代码框架
核心控制逻辑用C语言来写,大致框架如下:
#define BAL_START_MV 50 #define BAL_STOP_MV 20 #define BAL_RESTART_MV 80 #define BAL_MAX_TIME_SEC 3600 #define BAL_MIN_RUN_TIME_SEC 300 typedef enum { IDLE, START_DELAY, BALANCING, STOP_DELAY, FAULT } bal_state_t; static bal_state_t bal_state = IDLE; static uint16_t start_delay_cnt = 0; static uint16_t stop_delay_cnt = 0; static uint32_t bal_elapsed_sec = 0; static uint32_t bal_run_time_sec = 0; void BatteryBalance_Control(void) { int16_t vcell1 = Get_ADC_Voltage(ADC_CH_CELL1); int16_t vcell2 = Get_ADC_Voltage(ADC_CH_CELL2); int16_t delta_mv = abs(vcell1 - vcell2); switch (bal_state) { case IDLE: if (delta_mv > BAL_START_MV) { start_delay_cnt++; if (start_delay_cnt >= 10) { bal_state = START_DELAY; start_delay_cnt = 0; } } else { start_delay_cnt = 0; } break; case START_DELAY: if (delta_mv > BAL_START_MV) { Enable_Balancer(BAL_CURRENT_2A); bal_run_time_sec = 0; bal_state = BALANCING; } else { bal_state = IDLE; } break; case BALANCING: bal_elapsed_sec++; bal_run_time_sec++; if (delta_mv < BAL_STOP_MV && bal_run_time_sec > BAL_MIN_RUN_TIME_SEC) { stop_delay_cnt++; if (stop_delay_cnt >= 30) { Disable_Balancer(); stop_delay_cnt = 0; bal_state = IDLE; } } else { stop_delay_cnt = 0; } if (bal_run_time_sec > BAL_MAX_TIME_SEC) { Disable_Balancer(); Set_Fault(FAULT_BAL_TIMEOUT); } break; case STOP_DELAY: if (delta_mv > BAL_RESTART_MV) { bal_state = BALANCING; } else { Disable_Balancer(); bal_state = IDLE; } break; case FAULT: break; } }代码里的Get_ADC_Voltage返回的是经过滤波和校准后的实际电压值,以mV为单位。Enable_Balancer和Disable_Balancer控制MP2642GR-Z的使能和PWM输出。这套代码经过实际项目验证,逻辑上比较可靠,关键的地方都加了注释,后续做四串、八串均衡时只需要扩展数组,状态机的框架可以直接沿用。
5. 实测过程中的典型问题与排查技巧
5.1 ADC采样值跳变,是均衡最让人头大的问题
均衡启动后,ADC读数在几十毫伏范围内乱跳,是整个调试过程中最折磨人的问题。一开始以为是分压电阻虚焊或者运放损坏,换了硬件还是跳。后来用示波器抓异常电压节点,才发现问题出在采样线和功率线太近上。
MP2642GR-Z内部开关频率切换时,电流回路会产生强烈的磁场变化,采样线只要靠近这个区域,就相当于一个天线,把高频干扰直接耦合进了ADC输入。解决方法是重新布局:电压采样走差分线,远离电感和开关节点,采样线的参考地单独走,不跟功率地混流。同时在分压电阻输出到ADC之间并了一个100nF的电容,把高频分量进一步滤掉。
还有一个实用技巧是PWM同步采样。在PWM周期的中心点触发ADC转换,避开开关动作瞬间的噪声尖峰。MKV46的PWM定时器可以做成同步触发,这个功能比在软件里傻等可靠得多。实测用了这个办法之后,ADC读数的峰峰值从30mV降到了2mV以内,均衡逻辑立刻稳定了很多。
5.2 均衡不收敛,压差停住不动
均衡跑了一个小时,压差还停在40mV左右不往下降,这是第二个常见问题。起初怀疑MP2642GR-Z输出电流不对,用钳流表测下来电流正常,但压差就是不动。
深入的排查后发现,这种情况往往是电池本身存在内阻差异,而不是单纯的SOC偏差。均衡电流流过电池内部时,会在内阻上产生压降,如果两个电池内阻不一样,表现出端电压的差异和SOC差异其实是两回事。这时候一味地搬移能量没有意义,只会让SOC对齐但端电压依然有差值。
解决办法是改变评估指标:结合电压和电流积分一起判断。记录均衡过程中累积转移的电荷量,如果转移的电量已经超过预期但压差几乎没变,就判定为内阻差异占主导,此时停止均衡,并在系统日志里标记该单元需要检查。这个逻辑加进去之后,再也没出现过均衡空转一整夜的情况。
5.3 均衡启停振荡,阈值太窄的表现
均衡启动后压差降下来,停止后不到十分钟又回到启动阈值,系统又开始均衡,如此反复。这是迟滞窗口太窄造成的。
第一次调试时把启动阈值设的是40mV,停止阈值设的35mV,窗口只有5mV,磷酸铁锂的电压回弹稍微一抖就越过窗口边界,整个系统就在那里不停地启停。后来把启动阈值改到50mV,停止阈值改到20mV,并增加最小运行时间5分钟,问题立刻消失。
这里也顺带提一个参数整定经验:启动阈值不能设得太低,不能低于电池管理系统本身电压采样的误差范围。如果ADC综合误差在5mV左右,启动阈值却设了10mV,那系统就会在“没有真正失谐”的电池组上频繁误动作,既浪费电能又影响寿命。留足裕量,迟滞窗口至少留30mV以上,是比较稳妥的做法。
5.4 掉电与状态恢复,备用电源场景的特别考验
备用电源的典型工况就是随时可能断电来电。均衡进行到一半突然掉电,来电后系统要能正确处理,不能暴走也不能卡死。
我的做法是在均衡开始和结束时各写一次非易失标志位,记录“均衡进行中”和“均衡已完成”的状态。重新上电后,MCU读取标志,如果发现上一次均衡没跑完,不急着继续跑,而是先静置一段时间重新评估压差。因为掉电期间电池处于开路状态,电压会自然趋于平衡,很多时候压差已经不需要均衡了。这样既避免了重复均衡,也让系统状态更符合实际。
不建议在均衡过程中频繁写入Flash,Flash擦写次数有限,均衡每次运行都是一次擦写,寿命会受影响。只在两次关键时刻写标志就够了,现场跑了半年,Flash完全没问题。
6. 产测与长期运行的经验总结
6.1 出厂校准流程与参数标定
电压采样通道的一致性直接决定均衡算法的准确性,出厂前必须做校准。产线上的标准做法是用精密电压源分别给两个采样通道两个点电压,比如2.800V和3.200V,记录下ADC转换值,然后计算每个通道的增益系数和偏移量,存到芯片Flash里。
校准公式很简单:真实电压 = ADC值 * gain + offset。每个电池单元通道单独存一组gain和offset。这个校准步骤不能省,运放和电阻都有误差,不校的话两个通道之间可能有十几毫伏的系统偏差,均衡算法会被这个偏差误导。
批量生产时校准时间和精度要平衡:只校准两个点,每块板子的校准时间控制在10秒内,精度可以做到±2mV以内。这个精度对均衡控制完全够用,比用更高精度的器件去硬扛要经济得多。
6.2 长期可靠性与周期性维护均衡
均衡系统的长期可靠性,一半靠硬件设计,一半靠软件策略。硬件上,功率级散热的处理要到位,电感选型时要考虑饱和电流,不能只盯着额定电流看。软件上,我加了周期性维护均衡的机制:即使压差一直没达到启动阈值,每周也会自动运行一次短时间均衡,比如10分钟。这个机制用来应对长期浮充带来的微小差异累积,把问题扼杀在萌芽状态。
均衡使能信号的硬件下拉和看门狗复位设计,保证了最极端情况下的安全。备用电源设备常年无人值守,任何异常都可能是灾难性的,安全兜底永远优先于均衡效果。还有一点是做电流闭环:实际均衡电流如果低于设定值的80%,说明接触电阻变大或者功率级老化,系统要能报故障,而不是带着隐患继续运行。
6.3 个人在长期运行中的体会
均衡不是一个一次性的动作,而是持续的微维护。备用电源电池常年在浮充状态,一致性漂移从未停止过,均衡策略要在安静和及时之间找到平衡。太激进会导致系统频繁动作、器件老化,太保守又会让一致性持续恶化。我个人更倾向于保守一点的阈值配合周期维护,长期累计下来效果反而更好。
另一个体会是这套架构的扩展性极强。两个串联单元的均衡在算法和硬件上是整个储能系统均衡策略的基石,把两串的逻辑扩展到四串、八串,核心的状态机和迟滞思想完全不变,变的只是拓扑连接和采样通道数量。做项目时在最底层花时间把滤波、校准、状态机打磨好,后面扩串非常省事,这也是我觉得这套方案真正的价值所在。