两节串联的电池还要不要做均衡?这是我做某备用电源控制器时被问得最多的问题。答案很直接:越是小系统越容易被忽视,而一旦忽视,这两节电池的寿命差可以拉到几倍,整个储能模块的可用容量也跟着报废。最近我在储能单元和后备电源项目里,用 MP2642GR-Z 搭配 dsPIC30F4011 做了一套针对两串电池单元的均衡控制,今天把设计思路、实现细节和调试踩坑整理出来。这篇内容适合正在做小容量电池管理系统、UPS电池管理板,或者想搞明白主动均衡到底怎么落地的人参考,我会尽量按照"硬件怎么搭、策略怎么定、代码怎么写、坑怎么避"的顺序来讲。
1. 两节串联电池的"木桶效应":为什么均衡要从最小系统做起
1.1 两节电池的失配是怎么来的
很多人觉得两节新电池同一批出厂、同一个温度环境,还都是串联着充放电,电流一模一样,怎么会有压差?实际上失配根本避不开。出厂时单体容量、内阻、自放电率就有偏差,哪怕标称都是2.4Ah,实际容量可能相差3%~5%;工作时两节电池在封装内部的位置不同、散热条件不同,温度差个几度很常见,而内阻和自放电率又都随温度变化;再加上连接片的接触电阻差异,节流效应叠加起来,压差就会一天比一天明显。
两节串联的特别之处在于,回路电流对两节电池是完全相同的,充电时先满的是容量偏小的那节,放电时先没电的也是它。如果你不做任何干预,每一次循环,容量小的一节都会比别人更早逼近过充或过放区间,长期积累下来它的衰减速度会比另外一节快得多,于是差距越来越大,形成典型的正反馈。很多"用了一年突然发现整组容量崩了"的故障,根子就在这里。
1.2 不均衡的代价:容量被弱节拖累
串联电池组的可用容量等于最弱那节电池的容量,其他电池的富裕容量都只能"陪跑"。举个例子:两节磷酸铁锂电芯,标称都是2.4Ah,其中一节实际只有2.2Ah。每次充满时,2.2Ah那节先到3.65V,控制板为了保护它只能停止充电,整组充进去的有效电量就被限制在2.2Ah;放电时它又先到2.5V的截止线,整组放电也停在那。也就是说,整组白白损失了大约8%的容量。
更难受的是损失不是一次性的。过充和过放对电池的伤害是累积的,弱节每次循环都比别人多承担接近终止条件的压力,容量衰减加速,下个循环可用容量又少一点。这类系统最常见的现象就是:均衡板没装,电池组第一年容量统计还算正常,第二年开始跳水。装均衡的价值不是让两节电池变成一模一样,而是防止弱节被反复往悬崖边缘推。
1.3 两串系统的特殊选择逻辑
四串以上的电池组通常有专门的电池监控前端芯片,集成了电压采集、温度采集、被动均衡控制,方案成熟;但两串系统往往卡在成本、体积和功耗上,用专门的AFE芯片显得有点"杀鸡用牛刀"。两串真的很尴尬:电压不高、单体数量少,用分立方案反而能控制得比较精准。
我的选择是:功率均衡部分交给 MP2642GR-Z,控制决策部分交给 dsPIC30F4011。前者把开关管、驱动、电感控制这些高压大电流的东西管起来,后者专心做采样、判断、保护和通信。两串系统的采样点只有两个,电压范围又窄,dsPIC30F4011 的10位ADC配合正确的分压设计完全够用,48KB Flash对这套逻辑来说也游刃有余。这个组合在两串这个规模上,性价比和灵活性都挺合适。
2. 系统级任务拆解:MP2642GR-Z管功率,dsPIC30F4011管决策
2.1 双方的分工边界
一开始我就给自己定了个原则:MCU不要试图去做功率级的环路控制。MP2642GR-Z 作为均衡功率芯片,内部包含开关管驱动、电感电流路径和必要的保护逻辑,它要处理的是"怎么把能量从这一节搬到那一节"这种高频大电流问题;dsPIC30F4011 要处理的是"什么时候搬、搬多大、搬到什么程度、出问题怎么停"这种低频决策问题。
这么分的直接好处是软件简单、系统鲁棒。如果把开关管的PWM控制也丢给MCU,一旦程序跑飞或者中断响应不及时,功率级就可能失控,轻则均衡电流乱跳,重则开关管过流烧毁。把功率闭环锁在芯片内部,MCU这边只给使能、方向和电流档位,整体的故障面就小很多。我后面调试时遇到的大部分莫名其妙的问题,几乎都不是功率级本身,而是MCU侧采样和决策逻辑的毛病。
2.2 硬件架构与信号流
整个系统的连接关系很清晰:两节电芯串联,下节负极作为系统地参考点,中间点记为MID,上节正极为BAT+。MP2642GR-Z的均衡端口跨接在电芯1两端和电芯2两端,具体拓扑看芯片手册,但对外来看,MCU只要通过电平信号给出"均衡开启"和"能量方向"即可。dsPIC30F4011通过ADC通道分别采集BAT+、MID和BAT-电位,算出每节电压,再根据差值决定均衡动作。
信号流向分两条:一是状态采集链路,从电芯采样线进到MCU的ADC,经过滤波进入状态机;二是控制下发链路,从MCU的GPIO/PWM输出给MP2642GR-Z的使能脚和方向脚。系统还可以把均衡状态通过UART或IO口上报给上位机、充电器或者逆变器,备用电源场景下一般还需要一个低电平有效的告警输出。
2.3 选型理由:这颗16位控制器在这里赢在哪
dsPIC30F4011不是那种算力很强的芯片,但它在这个场景里赢在外设贴合度。它有足够多的ADC通道和灵活的定时器,可以用一个固定时间中断驱动200ms周期的均衡巡检;PWM模块可以输出均衡功率级需要的开关控制信号,频率和占空比都能独立配置;工业级的温度范围和宽电压工作范围,放在电池模组这种环境里也比普通8位机更让人放心。
10位ADC看起来参数平平,但算一下就清楚够用了。假设ADC参考电压3.3V,10位的1LSB大约是3.2mV;如果采样前端把电芯电压做2:1分压,对应到电芯电压就是6.4mV左右一个码。配合16次平均滤波,完全可以把电压读数稳定到±2mV以内。而均衡控制本身并不需要高精度:启动阈值150mV、停止阈值50mV,这些尺度远大于量化噪声。真正的误差大头从来不是ADC分辨率,而是采样电阻的精度和布局引入的噪声。
2.4 均衡功率级的工作边界:别越权
这块我要多说一句,因为我自己就吃过亏。MP2642GR-Z这类芯片内部通常有自己的控制环,MCU要做的只是给它一个目标值和使能信号,然后退到后台看状态。如果你自作聪明,在MCU里额外搞一套PID去"优化"它内部的工作状态,结果通常是环路打架,表现为均衡电流震荡、芯片发烫、甚至触发过流保护。
正确做法是:把芯片手册里的绝对最大额定值、使能时序、方向切换的最小间隔都做成一张检查表,写进设计文档的第一页。后续写程序的时候,凡是涉及功率级动作的引脚切换,一律用状态机流程控制,不允许在中断里直接翻转。中断只负责记录时间标记,真正的动作放主循环里做,这样即使IRQ触发时机乱掉,也不会硬生生把均衡方向来回切换。
3. 均衡判据与策略实现:电压差、滞回与状态机
3.1 为什么用电压判据而不是SOC判据
理论上最理想的均衡判据是SOC一致,因为电池最终希望的是容量状态一致,而不是端电压一致。但两串系统里做SOC估计很吃亏:没有库仑计,soc只能靠开路电压法,而磷酸铁锂的开路电压在中间平台段非常平坦,电压差几十毫伏对应的SOC差可能有百分之十几,反过来用端电压差做SOC差,误差极大。
工程上我用的是"电压差为主、状态条件为辅"的判据。核心是:只在电压对SOC响应比较敏感的区间才做均衡,也就是充电末端和静置状态。充电末端两节电池电压都在3.3V以上,这个区间端电压对SOC变化灵敏,压差能较好地反映容量失配;静置状态没有充放电电流,欧姆压降消失,电压差也更能反映真实的开路电压差。放电过程中我基本不做一致性均衡,因为大电流下内阻差引起的电压差会污染判断,容易把好电池的电往坏电池方向搬。
3.2 启动/停止阈值与滞回设计
均衡控制最忌讳的就是频繁启停,所以必须加滞回。我的阈值设置是:启动条件为两节电压差大于150mV,停止条件为差值小于50mV。中间这100mV的区间就是滞回带,状态机进入均衡之后不会因为电压没有完全拉平就立刻退出,避免在比较器边界上来回抖动。
为什么启动阈值是150mV而不是更大?因为两节磷酸铁锂在充电末端,150mV的压差意味着大约10%~15%的容量差,再拖下去弱节离过充保护就不远了,均衡动作需要尽早介入。但又不能设得太低,比如50mV就启动,否则电池在浮充、负载切换等正常波动下就会频繁启动,无谓消耗能量、增加开关管应力。150mV启动、50mV停止是我在多轮测试后觉得比较稳的组合,具体还要结合电芯内阻和系统噪声微调。
3.3 均衡状态机设计
整个控制逻辑用状态机落地,我先给出核心框架,后面4.3节还会配合采样代码一起讲。状态分为IDLE、PRECHECK、ACTIVE、PAUSE和PROTECT五种。IDLE表示无动作;PRECHECK是启动前的确认阶段,避免噪声误触发;ACTIVE是均衡正在进行;PAUSE是暂停等待温度回落;PROTECT是过压、欠压、过温等异常状态,需要手动或延时恢复。
状态转移条件大概是:IDLE下检测到压差大于150mV且持续5个采样周期(每个周期200ms)进PRECHECK;PRECHECK里如果压差回落到150mV以下则退回IDLE,否则进入ACTIVE;ACTIVE里压差小于50mV时关均衡回IDLE,温度过高进PAUSE,检测到单体过压进PROTECT。PROTECT状态下所有均衡动作一律停止,只有故障消除并且静置一段时间后才允许重新进入IDLE。
3.4 均衡电流的分档与时机
MP2642GR-Z支持不同均衡电流档位的话,我会把它分成三档:小档0.2A、中档0.5A、大档1A。充电过程中均衡用小档,因为充电电流本身就存在,均衡电流太大可能导致本来放电的那节被"拱"到过压;静置状态下均衡用中档或大档,目的是在系统空闲时尽快把压差拉回来。
还有一个容易被忽略的问题:两节电池总电压过低时不能大电流均衡。如果整组电压低于6.0V,说明两节都处于接近放空的状态,这时候均衡大电流会加剧弱节的深度放电,反而损伤电池。我的策略是:总电压低于6.0V时禁止均衡;6.0V~6.6V之间允许小档均衡;6.6V以上才开放中档和大档。这个条件判断放在状态机入口,优先级高于压差判断。
4. 从原理图到跑起来:采样电路、固件与参数整定
4.1 单体电压采样拓扑的选择与计算
两串系统的电压采样有两种常见做法:直接电阻分压和差分运放采样。直接分压就是BAT+、MID、BAT-各自通过电阻分压进ADC,结构简单、成本低,在两串这种电压不高并且系统以BAT-为参考地的场景里完全可行;差分运放能抑制共模噪声,但多了一级电路、要额外供电,对两串系统来说性价比不高。
我用的是直接分压加RC滤波。分压计算以ADC参考3.3V、系统最高电压8.4V(两节满电4.2V)为基准,留10%裕量后,满量程对应3.0V。取分压系数K = 3.0 / 8.4 ≈ 0.357,实际取电阻R1=12kΩ、R2=6.8kΩ,Vadc = Vbat × 6.8/(12+6.8) ≈ 0.362倍。这样两节磷酸铁锂充满7.3V时采样点约2.64V,不会超过参考电压,又有比较高的信号利用率。RC滤波用100Ω串联和100nF电容,截止频率约16kHz,主要滤开关噪声和射频干扰。
4.2 均衡功率级电路要点
MP2642GR-Z外围电路我强调几个容易踩的点。第一,均衡功率级的电源输入要加足够的去耦电容,大电流切换瞬间的压降很容易引起控制电路复位,我通常在芯片电源脚放10μF陶瓷电容加0.1μF高频电容的组合;第二,均衡开关管的散热铺铜要足够,主动均衡的电感电流哪怕只有0.5A,开关管长期工作下的温升也不容小觑;第三,均衡开关动作必然产生电压尖峰,输出侧加TVS管是标准操作,千万别为了省成本省略。
另外,MCU到MP2642GR-Z的控制线不要太长,方向切换和使能信号如果受到功率级干扰,会引起误动作。我在控制线上串联了100Ω电阻,并在接收端加10nF对地电容,虽然牺牲了一点边沿速度,但换来了稳定性。电池采样线和功率线要分开走,采样线必须从电池端直接引出,不能和均衡电流的路径共用一段铜箔,否则测到的压降会把电压读数带偏。
4.3 固件主循环与均衡判定实现
这套固件我用的是200ms定时中断配合主循环状态机的结构。定时中断负责触发ADC采样,主循环里做滑动平均滤波和均衡状态判断。下面给出一个简化版本的C伪代码,重点看滤波和状态机的配合方式,实际工程里还需要加上看门狗喂狗和通信处理。
#define BAL_TH_ON 150 /* 启动阈值,单位mV */ #define BAL_TH_OFF 50 /* 停止阈值,单位mV */ #define PRECHECK_NUM 5 /* 启动确认次数 */ static int16_t bal_state; static uint16_t precheck_cnt; /* 读取两节电池电压,返回单位mV,内部做16次滑动平均 */ int16_t read_cell1_mv(void); int16_t read_cell2_mv(void); void balance_task_200ms(void) { int16_t v1 = read_cell1_mv(); int16_t v2 = read_cell2_mv(); int16_t diff = (v1 > v2) ? (v1 - v2) : (v2 - v1); switch (bal_state) { case BAL_IDLE: if (diff > BAL_TH_ON) { bal_state = BAL_PRECHECK; precheck_cnt = 0; } break; case BAL_PRECHECK: if (diff > BAL_TH_ON) { if (++precheck_cnt >= PRECHECK_NUM) { bal_state = BAL_ACTIVE; /* 根据压差方向决定能量搬移方向 */ set_balance_dir(v1 > v2 ? DIR_CELL1_TO_CELL2 : DIR_CELL2_TO_CELL1); set_balance_enable(1); } } else { bal_state = BAL_IDLE; } break; case BAL_ACTIVE: /* 温度过高或总压过低时,先暂停均衡 */ if (temperature_exceed() || pack_voltage_low()) { set_balance_enable(0); bal_state = BAL_PAUSE; } else if (diff < BAL_TH_OFF) { set_balance_enable(0); bal_state = BAL_IDLE; } break; case BAL_PAUSE: /* 条件恢复后重新开始 */ if (!temperature_exceed() && !pack_voltage_low()) { bal_state = BAL_ACTIVE; set_balance_enable(1); } break; case BAL_PROTECT: /* 过压/欠压故障恢复只能走复位流程 */ break; } }这里有个实现细节值得注意:ADC采样结果最好在中断回调里存入环形缓冲,主循环里只对缓冲区做平均,不要在主循环里直接调用阻塞式ADC转换。我的做法是200ms中断到来时依次转换两个通道,把结果追加到各自的缓冲区尾部,主循环读取时每次只取最新的16个点做平均,这样采样和判断在时间上是解耦的,代码不容易被某个慢操作卡住。
4.4 参数整定与均衡时间估算
参数整定不是随便拍脑袋,要结合均衡容量来算。假设两节电池的容量差是200mAh,均衡电流取0.5A,理论均衡时间是0.2Ah / 0.5A = 0.4小时,也就是24分钟。考虑MP2642GR-Z的能量转移效率和各种损耗,实际需要留出30%~50%的余量,所以合理的均衡窗口大约35~40分钟。
这个估算值可以帮我们判断均衡是否正常。如果实际均衡时间远超理论值的两三倍,比如超过2小时压差还没收敛,那就不应该再继续耗下去了,说明两节电池的容量差异可能已经大到不是靠主动均衡能"搬平"的程度,正确做法是发出维护告警,提示用户换电芯。如果不设这个上限,均衡系统会一直在低效工作,不仅发热,还会加速电池循环损耗。我在代码里加了一个均衡超时保护,ACTIVE状态超过4小时强制退出并置告警位,这个参数可以根据实际电芯容量调整。
5. 实测调通阶段的坑位清单:噪声、发热与保护
5.1 均衡开关一动作,ADC读数就跳
这是我在样机调试时遇到的第一个明显问题。现象是均衡一开,MCU上报的两节电压差突然从几十毫伏跳到一两百毫伏,状态机误判成"越均衡越差",来回抖动。查了一圈,问题出在地线布局上:均衡功率回路的电流和采样参考点共用了同一段铜箔,开关动作瞬间,地线上产生毫伏级压降,污染了采样地。
解决办法分硬件和软件两步。硬件上把功率地和控制地分开走,在系统入口处单点汇合;采样线从电池根部直接引出,并尽量在ADC引脚附近加双绞线或者对地电容。软件上做一个动作抑制窗口:每次开启或切换均衡方向之后,强制等待10ms以上再启动新一轮采样,让地弹和开关振铃先过去。配合这两招,ADC读数跳变的问题基本消失。
5.2 被动均衡电阻的功率陷阱
早期验证时我偷懒,均衡电阻选了个贴片0805封装,结果在0.3A均衡电流下坚持了不到十几秒就开始冒烟。算一下就明白了:磷酸铁锂单节满充3.65V,0.3A下功耗是3.65V × 0.3A ≈ 1.1W,0805封装的额定功率才0.125W,差了快一个数量级。后来换成2512封装的2W电阻,PCB上还加了比较大的散热铜箔,温度才压住。
即使是主动均衡,也要仔细看MP2642GR-Z数据手册里的电流和功率曲线,不能只看芯片标称的最大电流。散热路径决定了芯片能持续跑多久,我曾经把均衡电流设到1A跑了一整晚,第二天发现芯片表面温度突破了80°C。后来做了一版引导:均衡电流大于0.5A时开启温度轮询,超过50°C就降档,超过60°C直接暂停。元器件选型之前把功耗算一遍,比烧两次板子再改可靠得多。
5.3 为什么"均衡越均越差":充电器与均衡打架
有段时间的实测效果特别诡异,明明开了均衡,两节电压差却在充电过程中越来越大。后来把充电电流曲线和均衡使能信号叠在一起看才发现:大电流充电时,内阻大的那节电芯端电压本来就偏高,均衡判定它是"高压节",于是把它的能量往外搬;但这节只是欧姆压降大,并不是真正容量高,结果越搬越失衡。
这说明一个道理:均衡判定要避开大电流工况。我把逻辑改成充电过程中只做保护性均衡(电压超过3.60V的单节限压均衡),一致性均衡仅在充电末端的涓流区间和静置状态下执行。修改之后,均衡效果才算是真正收敛。这个坑很典型,但凡用电压判据做均衡,都必须先想清楚"当前端电压里有多少是真实SOC,有多少是电流压降"。
5.4 地线环路导致MCU复位
另一个随机出现的诡异问题是均衡开关切换偶尔会让整个控制器复位。查了很久,发现是均衡功率地和MCU电源地之间存在环路,开关管关断瞬间的di/dt在环路里感应出负压尖峰,直接打到了复位引脚附近。后来在功率地和控制地之间接了磁珠,并把复位电路改成带RC延时的上电复位,问题才彻底解决。
这类问题隐蔽性很强,因为它不是每次动作都触发,而是跟开关管关断时的电流陡度有关。我的建议是调试阶段不要急着换主控或者怀疑固件,先用示波器同时勾功率节点和MCU电源引脚,看开关动作时有没有超过芯片绝对最大额定值的尖峰。地线环路问题用示波器看波形,通常一眼就能看出来。
5.5 备用电源场景的浮充巡检
最后一个是备用电源特有的场景。这类系统大部分时间处于浮充或待机状态,负载电流很小,但浮充电压下的漏电流差异会让两节电池的电压差以每天几毫伏的速度缓慢漂移。只靠开机时均衡一次,压差慢慢又会回来。我后来加了周期巡检功能:系统每24小时自动做一轮均衡巡检,每次最长10分钟,压差小于50mV就直接跳过。一个月跑下来,两节电池的压差始终被控制在30mV以内,效果比一次性长均衡好很多。
6. 从两串到整包:多板级联与联动控制
6.1 多片均衡芯片的级联方式
两串系统跑通之后,很容易想到扩展:一个电池包有8节串联怎么办?简单粗暴的做法是每两节配一块同样的均衡子板,整包由一块主控板统一调度。dsPIC30F4011的串口或SPI可以用来和每块子板通信,主控负责汇总所有单体的电压数据,再向对应子板下发均衡使能和方向。
级联时要注意均衡的复杂度。4节以上的串联,均衡不只发生在相邻两节之间,还可能出现"第1节高、第4节低"这种跨组不平衡。好在两串子板方案天然支持相邻均衡,如果整包需要跨组转移能量,可以让中间子板作为中转站,把能量逐级"接力"过去,虽然效率低一点,但架构简单可靠。真正做整包系统时,先确认不一致主要出现在相邻位置,而不是跨组大跨度,否则要重新评估均衡拓扑。
6.2 与充电器、逆变器的策略联动
均衡不是孤立动作,它跟充电器、逆变器的状态强相关。我在备用电源系统里做了三路联动信号:充电器工作在恒流阶段时,均衡只允许小档;充电器进入恒压末期或涓流阶段时,开放中档均衡;逆变器带载放电时,均衡暂停;系统静置无负载时,开放大档均衡并启动周期巡检。联动优先级按"安全 > 均衡效率"排列,任何异常信号优先打断均衡,保证系统不会因为均衡和主回路抢资源。
这套联动逻辑用dsPIC30F4011的IO口完全能实现,充电器和逆变器的状态信号通过光耦隔离过来,MCU读取后参与状态机决策。如果你做的是带通信的储能系统,直接走协议上报也行,但备用电源场景里可靠的电平信号往往比复杂的通信协议更抗干扰。
6.3 后续值得做的扩展
这个平台后续可以做几个低成本扩展方向。一是把温度采集点增加到每节电池一个NTC,均衡降档逻辑可以从"整体温度"细化到"局部温度",能进一步压低热失控风险。二是在dsPIC30F4011的Flash里加一段轻量的SOC估算,结合均衡记录做趋势预测,当发现某节电池的均衡时间在连续多个周期显著变长时,提前给出容量衰减预警。三是把均衡动作记录存到EEPROM,方便售后分析整包的生命周期状态变化。这三件事的主体逻辑在两串样机上都能验证,等真正做整包时可以直接移植。
我从这套方案里体会到一件事:两串均衡看起来是最小系统,但它把"功率控制、采样精度、状态机设计、系统联动"这些核心问题全占了。把这个最小系统调稳,再做更大规模的均衡架构,心里会很有底。调试阶段我还保留一个习惯:每次改完程序,都在电池两端并一个数字万用表核对MCU读数,两者差距超过5mV就先查采样链路而不是怀疑电池。这个习惯帮我省了大量排查时间,也建议准备做这类系统的朋友试试。