1. 项目背景与核心需求拆解
1.1 为什么串联电池组必须做均衡
先聊一个我在实际项目中反复遇到的场景:两节标称容量完全一致的电池串联使用,跑了三个月之后,其中一节先到截止电压,另一节还剩一截电量放不出来。整个电池包的可用容量不是两节之和,而是被最弱的那一节拖住了。这就是串联电池组最典型的“木桶效应”。
串联结构里,电流是共用的,但每节电池的内阻、自放电率、出厂容量、老化速度都不可能完全一致。充电时电压高的那节先到上限,放电时电压低的那节先到下限,BMS 如果只盯着总压看,就会误判整组状态。长期下来,弱的那节被反复过充过放,加速衰减,整组寿命直接腰斩。
所以均衡这件事,本质上不是“让两节电池一样”,而是让每节电池都工作在自己的安全区间内,把整组可用容量释放出来。储能系统和备用电源系统对这一点尤其敏感,因为这类场景往往是长期浮充、偶尔深度放电,电池组一旦失衡,关键时刻顶不上,维护成本还高。
1.2 被动均衡与主动均衡的取舍逻辑
均衡方案分两大流派:被动均衡和主动均衡。
被动均衡说白了就是给电压高的那节并一个电阻,把多余的能量以热量形式烧掉。优点是电路简单、成本低、可靠性高,缺点是能量浪费、均衡电流小、发热集中。主动均衡则是把能量从高电压节搬到低电压节,效率高、速度快,但拓扑复杂、成本高、控制难度大。
在这个项目里,我最终选的是基于 MP2642GR-Z 的被动均衡方案。原因很直接:储能和备用电源系统的均衡需求通常是“涓流式”的,不需要大电流快速拉平,只要在浮充阶段持续微调即可。MP2642GR-Z 这颗芯片集成了均衡开关管和驱动逻辑,外围只需要配均衡电阻,MCU 通过 I2C 或 GPIO 就能控制,整体 BOM 非常干净。对于两节串联这种小规模电池组,主动均衡的复杂度和成本完全不划算。
1.3 主控选型:为什么是 STM32F469II
主控这块我选了 STM32F469II。有人会问,两节电池均衡而已,用个 F0 系列甚至 8 位机不就够了?这话没错,但要看系统整体定位。
STM32F469II 是 F4 系列里的高性能型号,180MHz 主频、2MB Flash、384KB RAM,带 LCD-TFT 控制器和 Chrom-ART 图形加速器。在这个项目里,它不只是做均衡控制,还要承担整个储能系统的状态显示、数据记录、通信上报(CAN/RS485)以及多路 ADC 采样。均衡只是它众多任务中的一个。用 F469 的好处是:
- 算力冗余充足:均衡算法、SOC 估算、温度补偿可以并行跑,不用抠 CPU 周期。
- 外设丰富:多路 12 位 ADC 直接采电池电压和温度,不用外挂采样芯片。
- 图形能力强:本地 HMI 显示电池状态,用户体验直接拉满。
- 生态成熟:HAL 库、CubeMX 配置工具,开发周期短。
如果只是单纯做两节均衡,确实大材小用。但放在完整的储能/备用电源系统里,F469II 是合理的选择。
1.4 系统整体架构概览
整个系统的信号链路是这样的:
- 两节电池串联,中间节点和正负端分别接入分压/滤波网络,送到 STM32F469II 的 ADC 通道。
- MP2642GR-Z 的均衡通道分别跨接在两节电池两端,由 MCU 的 GPIO 控制通断。
- 温度传感器(NTC)贴在电池表面,接入另一路 ADC。
- MCU 根据电压、温度、工作状态决定是否开启均衡,以及开启哪一路。
- 状态通过 LCD 本地显示,同时经 CAN 总线上报给上位机。
这个架构的核心思想是:采样要准、判断要稳、执行要安全。下面逐层拆开讲。
2. 核心器件解析与硬件设计要点
2.1 MP2642GR-Z 的功能定位与引脚逻辑
MP2642GR-Z 是一颗面向多节电池管理的模拟前端类器件,内部集成了均衡开关和相应的控制逻辑。它的典型用法是配合 MCU 完成每节电池的独立均衡控制。
从功能上看,它主要提供几个能力:
- 独立通道控制:每个电池节对应一个均衡通道,可以单独开启或关闭。
- 开关集成:均衡用的功率开关做在芯片内部,外部只需要接限流/均衡电阻。
- 状态反馈:部分型号支持故障回读,比如过温、开关异常等。
实际接线时要注意,均衡电阻的选型直接决定均衡电流。假设我们希望均衡电流在 50mA 左右,单节电池电压按 3.7V 算,均衡电阻 R = V / I = 3.7V / 0.05A = 74Ω。取标准值 75Ω,实际电流约 49mA。功耗 P = I²R = 0.05² × 75 = 0.1875W,所以电阻要选 0.25W 或 0.5W 的封装,留足余量。
注意:均衡电阻的功耗计算不能只看标称电压,要按电池充满时的最高电压来算,否则长期工作会烧电阻。比如磷酸铁锂充满 3.65V,三元锂充满 4.2V,算出来的功耗差别不小。
2.2 STM32F469II 的 ADC 采样通道规划
F469II 的 ADC 是 12 位逐次逼近型,最高采样率 2.4MSPS(在适当配置下)。采电池电压有两种常见做法:
做法一:电阻分压直接采。两节串联总压最高 8.4V(三元锂),超过 ADC 的 3.3V 参考电压,必须分压。比如用 100k 和 47k 分压,分压比 = 47 / (100+47) = 0.32,8.4V 分压后约 2.69V,落在量程内。
做法二:专用电池采样芯片。比如带菊花链的采样 AFE,精度更高但成本也高。
这个项目里我用的是分压方案,因为只有两节,电路简单。但分压方案有个坑:分压电阻的精度直接影响采样精度。普通 1% 电阻带来的误差在 mV 级别,对于均衡判断够用,但如果要做精确 SOC 估算就不够了。所以我在分压网络里用了 0.1% 精度的电阻,并且加了 RC 滤波(100Ω + 100nF),抑制开关噪声。
采样通道分配如下:
| 通道 | 采样对象 | 分压比 | 备注 |
|---|---|---|---|
| ADC1_IN0 | 电池1电压 | 0.32 | 0.1% 电阻 |
| ADC1_IN1 | 电池2电压 | 0.32 | 0.1% 电阻 |
| ADC1_IN2 | 总压 | 0.32 | 用于交叉校验 |
| ADC1_IN3 | NTC 温度 | 分压 | 10k 上拉 |
电池2的电压采样要注意:它的“地”是电池1的正极,不是系统 GND。所以要么用差分采样,要么用高边采样电路。我这里是先把电池2的正极对系统 GND 分压,再减去电池1的电压,软件上做差得到电池2的真实电压。这样做的好处是硬件统一,坏处是软件要做减法,两次采样的误差会叠加。实测下来,在 12 位 ADC 加 0.1% 电阻的条件下,单节电压误差能控制在 ±5mV 以内,够用。
2.3 均衡电阻与热设计
前面算了均衡电阻的阻值和功耗,这里补充热设计。两路均衡同时开启时,两个 75Ω 电阻各耗散约 0.19W,加起来 0.38W。如果电阻是 0805 封装,额定功率通常 0.125W,直接超了。所以必须用 1206 或 2010 封装,或者用两个电阻并联分摊。
我实际用的是 1206 封装的 75Ω 电阻,额定 0.25W,单颗工作在 0.19W 左右,温升可以接受。但如果你把均衡电流提到 100mA,功耗就变成 0.75W,1206 也扛不住,得换 2512 或者加散热铜箔。
实操心得:均衡电阻不要贴在一起放,尽量拉开距离,避免热集中。PCB 上电阻下方铺铜,通过过孔把热量导到背面,能显著降低表面温度。我实测过,同样功耗下,铺铜加过孔能让电阻表面温度降 15℃ 左右。
2.4 电源与隔离设计
储能系统的供电环境通常比较恶劣,浪涌、反接、电压跌落都可能出现。所以电源部分我做了几层保护:
- 输入端 TVS:抑制浪涌。
- 防反接二极管:防止电源接反烧板。
- 宽压 DC-DC:输入 9~36V,输出 5V,再 LDO 到 3.3V 给 MCU。
- 模拟电源隔离:ADC 参考电压用独立的 LDO 供电,减少数字噪声干扰。
电池采样线和均衡线要走单独的模拟区域,远离 DC-DC 和 CAN 差分线。这一点在 PCB 布局时就要规划好,否则后期调试时噪声能把采样精度毁掉。
3. 均衡控制策略与软件实现
3.1 均衡触发条件的设计
均衡不是随时都能开的。我设定的触发条件有三个:
- 电压差超过阈值:两节电池电压差大于 30mV 时,考虑开启均衡。
- 处于充电或浮充状态:放电过程中不做均衡,因为放电时电压差可能只是暂时的负载差异,不代表真实容量差异。
- 温度在安全区间:电池温度 0~45℃ 才允许均衡,超出范围关闭。
这三个条件是“与”关系,全部满足才启动。为什么要加充电状态判断?因为放电时电压低的那节可能只是内阻大、压降大,一停止放电电压就回来了。如果这时候均衡,等于把好好的电放掉,纯属浪费。
电压差阈值 30mV 是经验值。太小了会频繁触发,均衡开关反复动作,寿命受影响;太大了均衡效果不明显。对于磷酸铁锂,平台期电压变化平缓,阈值可以放宽到 50mV;三元锂电压曲线陡,30mV 比较合适。
3.2 均衡开启与关闭的时序控制
均衡开关的动作不能太随意,我设计了一套时序:
- 开启前:先采样确认电压差仍然超标,避免误判。
- 开启时:先开电压高的那一路,延时 100ms 再检查电流是否正常。
- 运行中:每 10 秒重新采样,如果电压差降到 10mV 以下,关闭均衡。
- 关闭时:先关开关,再延时 500ms 让电压稳定,然后重新采样确认。
这里有个细节:均衡关闭后电压会“回弹”。因为均衡时电池有电流流过,内阻产生压降,测到的电压偏低。关闭后电流消失,电压回升。如果不延时直接判断,会误以为均衡没效果,反复开启。所以关闭后的延时采样很关键。
代码上,我用状态机实现:
typedef enum { BAL_IDLE, BAL_CHECK, BAL_START, BAL_RUNNING, BAL_STOP, BAL_SETTLE } BalState_t; void Bal_StateMachine(void) { static BalState_t state = BAL_IDLE; static uint32_t timer = 0; switch(state) { case BAL_IDLE: if (Bal_IsConditionMet()) { state = BAL_CHECK; timer = 0; } break; case BAL_CHECK: if (++timer > 100) { // 100ms 确认 if (Bal_IsConditionMet()) { Bal_EnableHighCell(); state = BAL_START; } else { state = BAL_IDLE; } timer = 0; } break; // ... 其余状态 } }3.3 电压采样滤波与校准
ADC 采样原始值抖动是必然的,直接拿来判断会误触发。我用了两级滤波:
第一级:中值滤波。连续采 5 次,去掉最大最小,取中间 3 个平均。这能滤掉突发的尖峰噪声。
第二级:一阶低通滤波。公式:filtered = filtered * 0.9 + new_sample * 0.1。这个系数决定了响应速度和平滑度的平衡。0.9 意味着时间常数约 10 个采样周期,对于 100ms 采样一次的场景,响应时间约 1 秒,足够平滑又不会太迟钝。
校准方面,我在生产时做两点校准:用高精度电源给一个已知电压,记录 ADC 读数,算出增益和偏移。校准系数存在 Flash 里,上电加载。这样能把分压电阻的误差也补偿掉。
踩过的坑:一开始我没做校准,直接用理论分压比算,结果两节电池的读数系统性偏差 20mV,均衡判断全乱套。后来发现是分压电阻实际值和标称值有偏差,而且两路偏差还不一样。校准之后误差降到 3mV 以内。
3.4 温度补偿与安全保护
温度对电池电压影响很大,尤其是低温下内阻升高,电压读数会偏低。我的做法是:
- 温度低于 10℃ 时,均衡阈值放宽到 50mV,避免误触发。
- 温度低于 0℃ 或高于 45℃ 时,禁止均衡。
- 温度超过 60℃ 时,触发过温保护,关闭所有均衡并上报故障。
NTC 的阻值-温度关系是非线性的,我用查表法加线性插值。表每隔 5℃ 一个点,覆盖 -20℃ 到 80℃。查表比算 Steinhart-Hart 公式快,精度也够。
安全保护还包括:
- 过压保护:单节超过 4.25V(三元锂)立即关闭充电并报警。
- 欠压保护:单节低于 2.8V 关闭放电。
- 均衡超时保护:单次均衡超过 2 小时强制关闭,防止开关卡死。
这些保护逻辑放在 1ms 周期的定时器中断里,优先级最高,确保及时响应。
4. 实操调试与问题排查实录
4.1 硬件调试:从裸板到能采样
新板子回来,第一步不是直接上电池,而是用可调电源模拟电池电压。我一般按这个顺序:
- 测电源:确认 5V、3.3V 正常,纹波在 50mV 以内。
- 测参考电压:ADC 的 VREF 必须是稳定的 3.3V,偏差超过 10mV 就要查 LDO。
- 灌电压测采样:可调电源给 3.0V、3.7V、4.2V 三个点,看 ADC 读数是否线性。
- 测均衡开关:给一个模拟电压差,看均衡电阻两端电压是否按预期变化。
这一步最容易出问题的是分压电阻焊错。我有一次把 100k 和 47k 焊反了,分压比变成 0.68,8.4V 分压后 5.7V,直接超量程,ADC 读数一直是满值。查了半天才发现是电阻位置错了。所以焊接后一定要用万用表量一下分压点的实际电压。
4.2 均衡效果验证:数据说话
硬件通了之后,怎么验证均衡真的有效?我的方法是人为制造不平衡:给一节电池并一个 100Ω 电阻,让它慢慢放电,制造 100mV 左右的电压差。然后开启均衡,记录电压变化。
实测数据(两节 18650,标称 3.7V):
| 时间 | 电池1电压 | 电池2电压 | 压差 | 均衡状态 |
|---|---|---|---|---|
| 0min | 4.05V | 3.95V | 100mV | 开启 |
| 30min | 4.03V | 3.97V | 60mV | 开启 |
| 60min | 4.01V | 3.99V | 20mV | 开启 |
| 75min | 4.00V | 4.00V | 0mV | 关闭 |
可以看到,50mA 的均衡电流下,100mV 的压差大约 75 分钟拉平。这个速度对于储能系统完全够用,因为储能系统经常是几天甚至几周的浮充周期。
注意:均衡过程中如果同时在充电,电压会被充电电流抬高,压差判断会失真。所以我的策略是充电时暂停均衡判断,只在浮充或静置时做均衡。
4.3 常见问题速查表
| 现象 | 可能原因 | 排查方法 | 解决 |
|---|---|---|---|
| 采样值跳动大 | 滤波不足/噪声耦合 | 示波器看采样点波形 | 加 RC 滤波,增加软件滤波 |
| 均衡不启动 | 条件判断太严 | 打印各条件状态 | 放宽阈值,检查温度 |
| 均衡电阻发烫 | 功耗超额定 | 算功耗,摸温度 | 换大封装,降均衡电流 |
| 电压读数偏差大 | 分压电阻误差 | 万用表量分压点 | 做两点校准 |
| 均衡后电压回弹 | 关闭后立即采样 | 加延时 | 延时 500ms 再判断 |
| 开关反复动作 | 阈值太窄/无迟滞 | 看开关日志 | 加 10mV 迟滞 |
| 温度读数异常 | NTC 接触不良 | 量 NTC 阻值 | 重新贴装,加导热胶 |
4.4 几个容易忽略的细节
第一,均衡开关的驱动能力。MP2642GR-Z 内部开关的导通电阻会影响均衡电流。如果导通电阻是 1Ω,均衡电阻 75Ω,实际电流是 V/(75+1),比理论值小 1.3%。这个误差可以接受,但如果导通电阻更大就要重新算。
第二,PCB 走线的压降。均衡电流 50mA 流过细走线,如果走线电阻 0.5Ω,压降 25mV,会影响采样精度。所以采样线和均衡线要分开走,采样线走差分对,均衡线加粗。
第三,电池连接器的接触电阻。这个最容易被忽略。连接器接触电阻如果有 10mΩ,50mA 电流下压降 0.5mV,影响不大。但如果接触不良,电阻到 1Ω,压降 50mV,采样直接废掉。所以连接器要选镀金的,插拔力要够。
第四,软件看门狗。均衡控制跑在 MCU 里,如果程序跑飞,均衡开关可能一直开着,把电池放空。所以必须开独立看门狗,并且均衡开关的控制引脚在硬件上要有默认关闭的拉电阻。
5. 系统集成与扩展思考
5.1 与上位机的通信协议设计
均衡状态需要上报给上位机,我用的 CAN 总线,协议自定义。每帧 8 字节,包含:
- 电池1电压(2字节,单位 mV)
- 电池2电压(2字节,单位 mV)
- 温度(1字节,单位 ℃,偏移 -40)
- 均衡状态(1字节,bit0 电池1均衡,bit1 电池2均衡)
- 故障码(2字节)
上报周期 1 秒,故障时立即上报。CAN 波特率 250kbps,总线负载率很低,留足了扩展空间。
协议设计的关键是字节对齐和单位统一。电压用 mV 做单位,避免浮点传输;温度用偏移编码,一个字节覆盖 -40~215℃,够用。故障码按位定义,每一位对应一种故障,上位机解析方便。
5.2 从两节扩展到多节的思路
这个项目是两节,但储能系统经常是 16 节甚至更多。扩展到多节时,架构要变:
- 采样:两节可以用 MCU 直接采,多了就要用菊花链 AFE,比如支持多节级联的采样芯片。
- 均衡:MP2642GR-Z 这类器件通常支持多通道,级联即可。
- 通信:多节系统用 CAN 或隔离 RS485,节点多了要考虑总线仲裁。
软件上,均衡策略要从“两两比较”变成“找最高和最低”。多节均衡的经典算法是:找出电压最高的那节,开启它的均衡,直到它降到平均值附近,再找下一个。这样比同时开多路更节能,热分布也更均匀。
5.3 低功耗场景的优化
备用电源系统有时候是电池供电,MCU 的功耗要抠。F469II 性能强但功耗不低,跑满 180MHz 时电流上百 mA。优化手段:
- 降频:均衡判断不需要高速,降到 24MHz 足够。
- 间歇采样:不是一直采,而是定时唤醒采样,采完就睡。
- 关闭外设:不用 LCD 时关掉,CAN 不通信时进低功耗模式。
实测下来,间歇工作模式下平均电流能降到 5mA 以下,对于备用电源的待机需求完全够用。
5.4 长期可靠性验证
储能系统要求 10 年以上寿命,均衡电路的可靠性至关重要。我做了几项加速测试:
- 高温老化:85℃ 环境下连续均衡 1000 小时,观察电阻和芯片参数漂移。
- 温度循环:-40℃ 到 85℃ 循环 500 次,检查焊点开裂。
- 开关寿命:均衡开关反复通断 10 万次,测导通电阻变化。
结果:均衡电阻在高温下阻值漂移小于 1%,芯片开关导通电阻变化小于 5%,焊点无开裂。这些数据说明方案在长期使用中是可靠的。
我个人在实际操作中的体会是,均衡这件事,硬件是基础,软件是灵魂。硬件设计留足余量,软件策略做细做稳,两者缺一不可。很多项目出问题,不是芯片选错了,而是细节没抠到位——采样没校准、滤波没做好、时序没设计好。把这几块吃透,两节电池的均衡其实是个很成熟的方案,MP2642GR-Z 加 STM32F469II 这套组合,稳定性和灵活性都经得起考验。后续如果要扩展,采样和通信层做模块化设计,换芯片、加节数都不用大改架构。