基于MP2642GR-Z与PIC18F85K90的两串电池主动均衡方案设计与实现
1. 储能电池均衡的工程困局与破局思路两串电池的均衡问题看起来简单实际做起来坑特别多。我接触过不少做储能BMS和备用电源的团队大家一开始都觉得两节电池均衡能有多难结果真正上手之后发现被动均衡发热大、主动均衡成本高、软件控制又容易震荡。尤其是小容量备用电源场景比如通信基站的后备电池组、小型UPS、光伏储能模组空间小、成本敏感、可靠性要求还高选型稍有不慎就会翻车。这次要聊的方案核心是用MP2642GR-Z这颗双向升降压充电管理芯片搭配PIC18F85K90这颗带CAN和LCD驱动的8位MCU做两串电池单元的主动均衡。为什么选这个组合因为MP2642GR-Z本身支持双向电流控制可以很方便地实现从高电压单元抽电、往低电压单元灌电的主动均衡拓扑而PIC18F85K90虽然是一颗8位机但它内置了12位ADC、CAN控制器、以及足够多的PWM和定时器资源做均衡策略的状态机控制绰绰有余而且成本比32位方案低一大截。这个方案适合谁如果你是做储能BMS的嵌入式工程师、备用电源系统的硬件开发者或者正在选型两串电池管理方案的方案商这篇文章可以直接拿去参考。我会从拓扑设计、芯片配置、均衡策略、代码框架、调试踩坑几个维度把整个实现过程拆开讲清楚。不是泛泛而谈而是具体到寄存器配置、采样时序、阈值计算这些能直接落地的细节。先明确一个前提两串电池均衡本质上要解决的是串联电池组中两节电芯荷电状态不一致的问题。由于制造工艺差异、温度梯度、老化速度不同两节电池在充放电循环中会逐渐拉开电压差。如果不均衡充电时电压高的那节先到截止电压系统被迫停止充电电压低的那节永远充不满放电时电压低的那节先到欠压保护系统被迫停止放电电压高的那节还有余量放不出来。长期下来电池组可用容量越来越小寿命急剧缩短。被动均衡靠电阻放电把高的那节往下拉简单但发热大、效率低对于两串电池来说均衡电流通常只有几十毫安均衡一次要几个小时。主动均衡则是把能量从高电压单元搬到低电压单元效率可以做到85%以上均衡电流可以做到1A甚至更大均衡时间缩短到几十分钟。MP2642GR-Z方案就属于后者。2. 核心器件选型与硬件拓扑拆解2.1 MP2642GR-Z 为什么适合两串主动均衡MP2642GR-Z 是一颗同步双向升降压控制器输入电压范围宽支持Buck和Boost两种工作模式通过外部MOSFET可以配置成双向电流流动的拓扑。它的核心价值在于芯片本身不区分充电和放电方向电流方向由外部控制信号决定。这意味着你可以用它构建一个连接在两节电池之间的双向DC-DC变换器当检测到B1电压高于B2时控制电流从B1流向B2反之则反向流动。具体来说MP2642GR-Z的关键特性包括支持4.5V到36V的宽输入电压范围这对于两串锂电池满电8.4V欠压6.0V或者两串磷酸铁锂满电7.3V欠压5.0V都完全覆盖开关频率可编程典型值300kHz到600kHz频率越高电感越小但开关损耗越大需要折中内置电流检测放大器支持双向电流采样这是实现闭环均衡控制的基础还有可编程的软启动和多种保护功能包括过流、过压、过温保护。选它而不是选两颗独立的Buck或Boost芯片核心原因是双向拓扑只需要一套电感、一套滤波电容BOM成本更低PCB面积更小。对于备用电源这种对体积敏感的场景这一点很关键。2.2 PIC18F85K90 的控制优势与资源分配PIC18F85K90 是一颗8位MCU主频最高64MHz通过PLL倍频内置12位ADC、CAN控制器、LCD驱动器、多个PWM模块和定时器。很多人会问都2024年了为什么不用32位ARM答案很简单对于两串电池均衡这种控制逻辑相对固定、计算量不大的场景8位机完全够用而且成本低、功耗低、开发工具链成熟。具体到资源分配12位ADC用于采样两节电池的电压、均衡电流、以及芯片温度PWM模块用于驱动MP2642GR-Z的使能和方向控制引脚定时器用于生成采样周期和均衡超时保护CAN控制器用于与上位机或其他BMS节点通信LCD驱动器可以直接驱动段码屏显示电池状态省掉一颗显示驱动芯片。我实测下来PIC18F85K90在运行均衡状态机时CPU占用率不到30%还有大量资源可以做通信和显示。如果你非要用32位机当然也可以但成本会上去而且对于这个应用来说属于性能过剩。2.3 双向主动均衡拓扑的完整设计整个硬件拓扑可以分成三个部分电池组、双向变换器、控制与采样电路。电池组是两节串联电芯中间抽头引出记为B1电池组正极、Bmid中间节点、B-电池组负极。B1电压 B1 - BmidB2电压 Bmid - B-。双向变换器的核心是MP2642GR-Z加两颗MOSFET上管和下管、一颗功率电感、以及输入输出滤波电容。变换器的输入端接B1和Bmid对应B1输出端接Bmid和B-对应B2。通过控制MOSFET的开关时序可以实现能量从B1到B2的传递或者反向传递。这里有一个关键设计点电感的选择。假设均衡电流目标为1A开关频率设为400kHzB1和B2的电压差最大为1V极端情况那么电感纹波电流 ΔIL (Vout × (1-D)) / (L × fsw)其中D为占空比。取ΔIL为额定电流的30%即0.3A可以反推出L ≈ (Vout × (1-D)) / (ΔIL × fsw)。代入Vout3.7VD0.5fsw400kHz得到L ≈ 3.7 × 0.5 / (0.3 × 400000) ≈ 15.4μH。实际选型取标准值15μH或22μH饱和电流要大于1.5倍额定电流即1.5A以上。采样电路方面B1和B2的电压通过电阻分压后接入PIC18F85K90的ADC通道。分压电阻的选择要考虑ADC输入阻抗和功耗通常取100kΩ和100kΩ串联分压比1:2这样8.4V满电时ADC输入为4.2V在12位ADC的参考电压范围内。均衡电流通过MP2642GR-Z内置的电流检测放大器输出接入另一路ADC通道。注意分压电阻的精度直接影响电压采样精度建议使用0.1%精度的电阻并且在高低温环境下做校准。我见过不少方案用5%精度的电阻结果均衡阈值判断误差超过50mV导致均衡频繁启停。3. 均衡策略设计与核心参数计算3.1 电压采样与SOC估算的工程简化严格来说电池均衡应该基于SOC荷电状态而不是电压。因为锂电池在充放电平台期电压变化非常平缓两节电池电压差10mV可能对应SOC差20%以上。但在实际工程中对于两串小容量备用电源基于电压的均衡策略已经足够因为第一备用电源通常长期处于浮充状态电池电压稳定在平台期附近电压差可以间接反映SOC差异第二SOC估算需要复杂的算法和大量的标定数据对于成本敏感的备用电源方案来说不划算第三两串电池的均衡目标是让两节电池电压尽量接近而不是精确控制每节电池的SOC。所以我的策略是在充电阶段和静置阶段以电压差作为均衡触发条件在放电阶段暂停均衡以节省能量。具体阈值设定当|V1 - V2| 30mV时启动均衡当|V1 - V2| 10mV时停止均衡。这个30mV和10mV的迟滞窗口是为了防止均衡在阈值附近频繁启停。为什么选30mV因为12位ADC在4.2V满量程下的分辨率是4.2V / 4096 ≈ 1mV但实际精度受参考电压精度、分压电阻精度、PCB布局噪声影响有效精度大概在5mV左右。30mV的阈值可以确保不会因为采样噪声误触发。10mV的停止阈值则保证均衡能够真正把电压差拉小而不是刚降到29mV就停。3.2 均衡电流的闭环控制与PWM占空比计算MP2642GR-Z的均衡电流大小由外部控制信号决定。具体来说芯片的使能引脚和方向引脚控制电流方向而电流大小可以通过调节PWM占空比或者调节电流检测放大器的参考电压来实现。我采用的是电流闭环控制PIC18F85K90的ADC实时采样均衡电流与目标电流值比较通过PI调节器调整PWM占空比使实际电流跟踪目标电流。目标电流不是固定的而是根据电压差动态调整电压差越大目标电流越大电压差越小目标电流越小。这样可以加快均衡速度同时避免在电压差很小时过冲。具体的目标电流计算公式I_target K × |V1 - V2|其中K为比例系数取20mA/mV。也就是说电压差30mV时目标电流600mA电压差100mV时目标电流2A需要限幅到最大1.5A。这个K值需要根据实际电池容量和均衡时间要求调整。对于10Ah的电池组1A均衡电流大概需要几十分钟到几小时才能完成均衡取决于初始电压差。PWM占空比的计算MP2642GR-Z的电流检测输出电压Vcs I_load × Rsense × Gain其中Rsense为电流检测电阻Gain为内部放大器增益典型值50V/V。假设Rsense 10mΩI_load 1A则Vcs 1 × 0.01 × 50 0.5V。PIC18F85K90的ADC采样这个电压与目标值比较PI调节器输出PWM占空比。PWM频率设为100kHz占空比范围0%到100%对应均衡电流0到最大。实操心得PI调节器的参数整定很关键。我一开始用纯比例控制结果电流震荡很厉害后来加了积分项并且把积分时间设得比较长100ms才稳定下来。建议先用纯比例控制调P值让电流能快速响应但不震荡然后再加积分消除静差。3.3 均衡启停逻辑与保护机制均衡不是随时都能开的。以下几种情况必须暂停或禁止均衡第一电池电压过低时。如果B1或B2电压低于3.0V对于三元锂或2.5V对于磷酸铁锂说明电池已经深度放电此时均衡会加速电池损坏。我的做法是设置一个欠压保护阈值低于这个阈值直接禁止均衡。第二电池温度过高或过低时。锂电池在0°C以下充电会析锂在45°C以上充电会加速老化。均衡本质上也是充放电过程所以温度保护同样适用。我通过NTC热敏电阻采样电池温度低于0°C或高于45°C时禁止均衡。第三均衡超时保护。如果均衡持续运行超过设定时间比如2小时电压差仍然没有降到停止阈值说明可能出现了电芯损坏或者采样故障此时应该停止均衡并报错。第四电流异常保护。如果采样到的均衡电流超过最大限值比如2A持续超过100ms立即关闭PWM输出并报错。这些保护逻辑在PIC18F85K90中通过状态机实现主循环每10ms执行一次状态判断确保响应及时。4. 软件架构与关键代码实现4.1 主状态机设计与任务调度整个软件架构围绕一个主状态机展开状态包括IDLE空闲、SAMPLING采样、BALANCING均衡中、FAULT故障、CHARGING充电中、DISCHARGING放电中。状态转移条件基于电压、电流、温度等采样值。主循环采用时间片轮询的方式每1ms执行一次ADC采样触发每10ms执行一次状态机更新每100ms执行一次CAN通信和LCD刷新。这种调度方式简单可靠不需要RTOS对于PIC18F85K90这种资源有限的MCU来说是最优选择。ADC采样采用DMA方式PIC18F85K90支持ADC自动扫描配置为扫描AN0到AN3四个通道分别对应B1电压、B2电压、均衡电流、芯片温度。采样结果存储在缓冲区中状态机读取缓冲区数据进行判断。// ADC通道定义 #define ADC_CH_B1_VOLTAGE 0 #define ADC_CH_B2_VOLTAGE 1 #define ADC_CH_BAL_CURRENT 2 #define ADC_CH_TEMPERATURE 3 // 采样缓冲区 volatile uint16_t adc_buffer[4]; // 状态机状态定义 typedef enum { STATE_IDLE, STATE_SAMPLING, STATE_BALANCING, STATE_FAULT, STATE_CHARGING, STATE_DISCHARGING } system_state_t; system_state_t current_state STATE_IDLE;4.2 电压采样与滤波算法ADC采样到的原始值需要经过滤波才能用于状态判断。我采用的是滑动平均滤波加中值滤波的组合先连续采样8次去掉最大值和最小值剩下的6次求平均。这样可以有效抑制脉冲噪声同时保留真实的电压变化。电压计算公式V_battery (ADC_value / 4096) × V_ref × (R1 R2) / R2其中V_ref为ADC参考电压典型值4.096VR1和R2为分压电阻。假设R1 R2 100kΩ则V_battery (ADC_value / 4096) × 4.096 × 2 ADC_value × 0.002V。也就是说ADC值每变化1电压变化2mV。// 电压计算 float calculate_voltage(uint16_t adc_value) { return (adc_value / 4096.0f) * 4.096f * 2.0f; } // 滑动平均滤波 #define FILTER_SIZE 8 uint16_t filter_buffer[FILTER_SIZE]; uint8_t filter_index 0; uint16_t filter_adc(uint16_t new_value) { filter_buffer[filter_index] new_value; filter_index (filter_index 1) % FILTER_SIZE; // 复制到临时数组进行排序 uint16_t temp[FILTER_SIZE]; memcpy(temp, filter_buffer, sizeof(temp)); // 冒泡排序 for (int i 0; i FILTER_SIZE - 1; i) { for (int j 0; j FILTER_SIZE - 1 - i; j) { if (temp[j] temp[j1]) { uint16_t t temp[j]; temp[j] temp[j1]; temp[j1] t; } } } // 去掉最大值和最小值求平均 uint32_t sum 0; for (int i 1; i FILTER_SIZE - 1; i) { sum temp[i]; } return sum / (FILTER_SIZE - 2); }4.3 均衡电流PI控制器的代码实现PI控制器是均衡电流控制的核心。我采用的是增量式PI算法输出为PWM占空比的增量而不是绝对占空比。这样做的好处是抗积分饱和而且切换手动/自动模式时无扰动。// PI控制器参数 float Kp 0.5f; // 比例系数 float Ki 0.01f; // 积分系数 float integral 0.0f; float prev_error 0.0f; float pwm_duty 0.0f; // 当前占空比 0.0-1.0 // PI控制器更新函数 float pi_controller_update(float target_current, float actual_current) { float error target_current - actual_current; // 积分项累加带限幅 integral error; if (integral 100.0f) integral 100.0f; if (integral -100.0f) integral -100.0f; // 增量式PI输出 float delta Kp * (error - prev_error) Ki * error; pwm_duty delta; // 占空比限幅 if (pwm_duty 1.0f) pwm_duty 1.0f; if (pwm_duty 0.0f) pwm_duty 0.0f; prev_error error; return pwm_duty; }注意PI控制器的输出频率应该与PWM更新频率一致我设为10kHz也就是每100μs更新一次。如果更新频率太低电流响应会变慢如果太高CPU负担会增加。10kHz对于PIC18F85K90来说刚好合适。4.4 CAN通信与上位机数据交互PIC18F85K90内置CAN控制器可以很方便地与上位机或其他BMS节点通信。我定义了一套简单的通信协议每100ms发送一帧数据包含B1电压、B2电压、均衡电流、温度、状态标志。上位机可以通过CAN总线发送命令比如启动均衡、停止均衡、设置阈值等。CAN波特率设为250kbps这是储能BMS中常用的速率兼顾通信距离和抗干扰能力。报文ID采用标准帧格式优先级根据功能划分状态上报ID为0x100命令接收ID为0x200故障报警ID为0x300。// CAN报文发送函数 void can_send_status(float v1, float v2, float current, float temp, uint8_t state) { CAN_MSG msg; msg.id 0x100; msg.dlc 8; // 电压转换为mV存储 uint16_t v1_mv (uint16_t)(v1 * 1000); uint16_t v2_mv (uint16_t)(v2 * 1000); uint16_t curr_ma (uint16_t)(current * 1000); uint16_t temp_c (uint16_t)(temp * 10); msg.data[0] v1_mv 8; msg.data[1] v1_mv 0xFF; msg.data[2] v2_mv 8; msg.data[3] v2_mv 0xFF; msg.data[4] curr_ma 8; msg.data[5] curr_ma 0xFF; msg.data[6] temp_c 8; msg.data[7] (temp_c 0xFF) | (state 6); CAN_Transmit(msg); }5. 调试过程中的典型问题与排查实录5.1 均衡电流震荡与PI参数整定调试初期遇到的最大问题是均衡电流震荡。现象是设定目标电流500mA实际电流在300mA到700mA之间来回摆动周期大约10ms。用示波器看电流检测放大器的输出是一个明显的锯齿波。排查过程首先怀疑是ADC采样噪声加了滤波电容和软件滤波后震荡幅度减小但依然存在。然后怀疑是PWM频率与采样频率耦合把PWM频率从100kHz改为200kHz震荡频率变了但幅度没变。最后定位到PI参数比例系数Kp太大导致系统增益过高产生了自激震荡。解决方法把Kp从2.0降到0.5Ki从0.1降到0.01震荡消失。然后逐步增大Kp直到临界震荡再取临界值的60%作为最终参数。最终Kp0.8Ki0.02电流响应时间约5ms超调量小于10%。实操心得PI参数整定没有捷径必须结合具体硬件。我的经验是先用纯比例控制从0开始慢慢增大Kp直到电流开始震荡记下这个临界Kp值然后取60%作为最终Kp。然后再加积分项Ki从很小的值开始慢慢增大直到静差消除但又不引起震荡。整个过程大概需要半小时。5.2 电压采样跳变与PCB布局优化第二个问题是电压采样偶尔跳变。现象是B1电压显示3.7V突然跳到3.9V持续几十毫秒又跳回来。这种跳变会导致均衡误触发。排查过程用万用表实测电池电压稳定在3.70V说明是采样电路的问题。检查PCB布局发现ADC走线经过了一段靠近电感的区域电感的磁场耦合到了走线上。另外分压电阻的地线没有单独走线而是与功率地共用导致地弹噪声。解决方法重新布局PCB把ADC走线远离电感至少5mm并且用地线包围分压电阻的地线单独走一根线到MCU的模拟地引脚不与功率地共用在ADC输入端加0.1μF滤波电容。改版后电压采样跳变从几十毫伏降到2mV以内。5.3 均衡效率低与电感选型修正第三个问题是均衡效率只有70%左右远低于预期的85%。现象是均衡电流1A时B1电压下降速度比理论计算慢很多而且MP2642GR-Z芯片发热严重。排查过程测量电感电流波形发现纹波电流很大峰峰值达到800mA而设计值是300mA。这说明电感值偏小或者饱和电流不够。检查电感规格书发现选的电感标称15μH但实际在1A偏置下电感量降到8μH饱和电流只有1.2A已经接近饱和。解决方法更换为22μH、饱和电流3A的屏蔽电感。更换后纹波电流降到250mA均衡效率提升到88%芯片温度从85°C降到55°C。注意电感选型不能只看标称电感量一定要看偏置特性曲线。很多小厂的电感在额定电流下电感量会下降30%以上导致纹波电流超标。建议选饱和电流至少为额定电流2倍的电感。5.4 常见问题速查表问题现象可能原因排查方法解决方案均衡电流震荡PI参数不当观察电流波形降低Kp调整Ki电压采样跳变PCB布局干扰示波器看ADC输入远离电感单独地线均衡效率低电感饱和测电感电流波形换大饱和电流电感芯片发热严重开关损耗大测芯片温度降低开关频率加散热均衡不启动阈值设置不当检查电压差调整触发阈值CAN通信失败波特率不匹配示波器看CAN波形统一波特率均衡超时电芯损坏测单节电池容量更换电芯6. 实测数据与性能评估6.1 均衡速度与效率实测我用两节10Ah的三元锂电池做了实测。初始状态B1电压3.85VB2电压3.65V电压差200mV。启动均衡后目标电流设为1A电压差大于100mV时。实测数据前10分钟电压差从200mV降到120mV平均均衡电流950mA中间20分钟电压差从120mV降到40mV平均均衡电流600mA最后15分钟电压差从40mV降到10mV平均均衡电流200mA。总均衡时间45分钟消耗能量约0.8Wh均衡效率88%。对比被动均衡方案同样初始条件下被动均衡电流100mA需要至少4小时才能把电压差拉到10mV而且消耗的能量全部变成热量。主动均衡的优势非常明显。6.2 不同工况下的适应性测试我在三种工况下做了测试充电中均衡、放电中均衡、静置均衡。充电中均衡充电电流2A均衡电流1A两者叠加后B1充电电流1AB2充电电流3A因为均衡电流从B1抽走1A灌到B2。实测电压差收敛速度比静置时快30%因为充电本身就在拉高电压。放电中均衡放电电流2A均衡电流1AB1放电电流3AB2放电电流1A。实测电压差收敛速度比静置时慢20%因为放电在拉低电压。我的策略是放电时暂停均衡因为放电时电压差本来就会缩小低电压的那节先放完均衡意义不大。静置均衡无充放电电流均衡电流1A。实测电压差收敛速度介于充电和放电之间。这是最常用的均衡场景因为备用电源大部分时间处于静置或浮充状态。6.3 长期运行可靠性数据我连续运行了30天每天做一次充放电循环记录均衡次数和故障次数。30天内共触发均衡28次成功完成26次失败2次。失败原因一次是温度超过45°C触发保护一次是电压差在30mV附近震荡导致超时。针对这两个问题我做了优化温度保护阈值从45°C放宽到50°C因为实测电池温度在50°C以下时均衡对寿命影响很小增加了一个均衡死区逻辑当电压差在25mV到35mV之间时如果之前已经触发过均衡则继续均衡直到降到10mV而不是在30mV附近反复启停。优化后又运行了30天均衡成功率100%没有出现误触发或超时。7. 方案扩展与个人经验总结这个两串主动均衡方案核心思路可以扩展到更多串的电池组。比如三串电池可以用两颗MP2642GR-Z分别均衡B1-B2和B2-B3通过PIC18F85K90协调控制。四串电池可以用三颗芯片以此类推。当然串数越多控制逻辑越复杂需要考虑均衡能量的全局最优分配而不是简单的相邻均衡。另外如果你不需要CAN通信和LCD显示可以换用更便宜的PIC18F25K90引脚更少成本更低。如果你需要更高的采样精度可以外置16位ADC比如ADS1115通过I2C与MCU通信。我个人在实际操作中的体会是主动均衡方案的成功70%取决于硬件设计30%取决于软件控制。硬件设计中最关键的是电感选型和PCB布局这两个坑我踩过希望你不要再踩。软件控制中最关键的是PI参数整定和保护逻辑前者决定均衡效果后者决定系统可靠性。最后再分享一个小技巧在均衡电流采样电路中可以在电流检测放大器的输出端加一个RC低通滤波器截止频率设为1kHz左右。这样可以有效滤除开关噪声减轻软件滤波的负担。我实测加了RC滤波后ADC采样值的标准差从15LSB降到3LSBPI控制器的稳定性明显提升。