基于Arduino与MOS管的简易直流电子负载设计与PID闭环控制

发布时间:2026/9/9 2:31:47
基于Arduino与MOS管的简易直流电子负载设计与PID闭环控制 简介一套基于C51的简易直流电子负载程序源码面向嵌入式初学者、电源研发与测试人员帮助理解直流电子负载的基本原理以及借助PWM占空比调节来模拟不同阻值负载的实现方法。压缩包共有21个文件体积约61KB内容包括主程序源文件、多个功能头文件、Keil工程配置以及编译生成的十六进制烧录文件与列表备份文件便于直接打开工程查看完整代码和结构。已有1046人学习下载。程序覆盖初始化、用户界面显示、PWM控制、电流采样与反馈、安全保护等关键模块适用于电源研发、教学实验和产品检测等场景。通过阅读源码可以学习C51在电子负载控制中的实际应用思路掌握ADC采样、闭环调节、过流保护的实现细节为后续优化或二次开发打下基础。1. 为什么要自己做一款直流电子负载平时搞电源、锂电池、充电器项目最常遇到的一个需求就是测输出能不能扛住电流。万用表只能看空载电压接个水泥电阻又不精确电流会随着电池电压下降一路漂。这时候手头最该有的工具就是直流电子负载——它能把被测电源拉到一个固定电流、固定功率甚至模拟动态负载测出真实的带载能力。成品电子负载倒是不少几百瓦的正规仪器上千块起步便宜的家用款要么精度稀烂要么程序逻辑反人类。我做的这个“简易直流电子负载程序”核心思路是用 Arduino 驱动一颗功率 MOS 管通过 PWM 控制栅极电压来调整导通程度再配合采样电阻和 OLED 屏幕做成一个可以设定恒流值、实时显示电压电流的小设备。整体成本控制在几十块钱能应付 0~5A 的恒流放电测试测 18650 电池、3.7V 升压模块、5V 充电器完全够用。这篇文章适合电子爱好者和嵌入式入门玩家不需要懂很深的理论但我会把程序架构、PID 调节、采样滤波这些关键环节的“为什么”讲透让看完的人能自己复刻出来而不是抄一份代码就完事。2. 整体设计时我交过的学费2.1 方案选型为什么是 Arduino N-MOS 而不是纯模拟一开始我图省事也想直接用运放搭恒流源参考电压 采样电阻 比较器就能闭环好处是反应快、没有程序死机的问题。但纯模拟方案有两个麻烦一是想显示电压电流必须再引信号给 ADC电路变成线性 模拟两套体系调起来麻烦二是电流设定、恒功率、动态负载这些功能全靠旋钮电位器实现精度和灵活性都很差。后来换成了 Arduino Nano 功率 MOS 管的数字化方案。核心思路是单片机的 PWM 经过 RC 滤波变成直流电压加到 MOS 管栅极改变 MOS 导通电阻实现电流调节。ADC 实时采集采样电阻两端的压降换算成电流值再通过 PID 算法自动调整 PWM 占空比形成闭环。MOS 管为什么用 N 沟道而不是 P 沟道因为 N-MOS 在相同封装和价位下导通电阻更低、电流能力更大。虽然 N-MOS 的低端驱动对采样电路布置有点要求但只要采样电阻放在 MOS 管源极到地之间程序测量的是低端电流这个问题就顺理成章地化解了。这里顺便多说一句电子负载里的 MOS 管是工作在可变电阻区不是开关管那样工作在饱和区。意思是栅极电压不需要高到完全导通而是让管子处于“半开半闭”的状态靠调节这个通路电阻来控制电流大小。这也意味着 MOS 管上的功耗很大必须配散热器选型时还要留意安全工作区SOA别只看电流标注就往上怼。2.2 功率链路和采样链路的基本框架电流路径是被测电源正极 → MOS 管漏极 → MOS 管源极 → 采样电阻 → 被测电源负极。采样电阻选的是 0.01Ω 的大功率合金电阻电流 5A 时压降也才 50mV对被测电源的压降影响可以忽略不计。但这个电压信号太微弱单片机 ADC 直接读误差很大所以必须加一级运放放大。我用了一颗 LM358把采样电压放大 50 倍左右也就是 0.5V~2.5V 对应 1A~5A正好落在 Arduino 的 5V ADC 量程内分辨率能做到 1mA 级别对“简易”定位来说这个精度足够了。PWM 这一侧我用的是 8 位 PWM频率 31.4kHz。选择这个频率是有讲究的——一是超过人耳听觉范围不会像 1kHz 那样发出刺耳的啸叫二是电容滤波后纹波更小栅极电压更稳定。RC 滤波截止频率我压在 20Hz 左右等于把 PWM 的开关纹波都滤干净了。注意选 31.4kHz 是因为 Arduino 的 timer 分频正好能配到这个值换别的板子要查对应 Timer 配置别等着抄代码时发现 PWM 频率不对。3. 程序架构和关键代码是怎么写的3.1 主循环里的状态机设计整个程序不是流水账式的一条道跑到黑而是按状态机来组织。我分成了四个状态待机状态显示当前电压、设定电流等待按键指令。恒流调节状态通过编码器或者按键加减设定电流PID 实时调整 PWM。放电运行状态MOS 管开启按设定值拉载刷新屏幕显示实测电压电流。保护状态检测过流、过温或者电压掉到截止值以下关闭输出防止电池过放。这样的好处很明显按键逻辑不会跟显示逻辑互相打架也不容易因为某个分支卡死导致整个系统没响应。很多新手写代码喜欢把所有功能堆在 loop 里一会儿读按键一会儿刷新屏幕最后 PWM 更新时间被拖到几毫秒电流波动明显这就是状态机没有做好的典型症状。在放电运行状态下我特别把 PID 计算放在主循环最前面并且抢占式跳过显示刷新。也就是说如果 PID 计算耗时太长宁可 OCR 值更新得频繁一点也不要被 OLED 的 I2C 通信卡住。实测下来这条细节对电流稳定性影响最大。3.2 核心代码片段解析ADC 滤波和 PID 输出ADC 采样不能直接拿来算电流一个是因为 PWM 和电源自身会有开关纹波另一个是因为采样电阻的信号太弱运放输出端还是会有微小的高频噪声。我用了简单的滑动平均滤波取 16 次采样做平均这样既不会太迟钝又能把大部分毛刺压下去。uint16_t readAverageADC(uint8_t pin, uint8_t samples) { uint32_t sum 0; for (uint8_t i 0; i samples; i) { sum analogRead(pin); delayMicroseconds(50); } return sum / samples; }PID 部分没用什么库手搓了一个最简位置式float pidCalc(float setpoint, float current, float kp, float ki, float kd) { static float lastError 0; static float integral 0; float error setpoint - current; integral error; integral constrain(integral, -100, 100); // 积分限幅防止过冲 float output kp * error ki * integral kd * (error - lastError); lastError error; return output; }积分限幅这步务必要加。我一开始没加结果大电流切换到小电流的时候积分项攒了一大堆PWM 输出半天降不下来电流过冲能到设定值的 150%直接把一块测试电池搞到保护板动作。加上限幅之后动态响应虽然没那么猛但稳定性和安全性都好了很多。PWM 输出动作要 smooth不能一上来就拉到满。比如从 0A 切到 5A如果直接把占空比从 0 跳到某个大值采样电阻上的电压突变会引发 ADC 读数跳变PID 误判误差增大输出反而震荡。我的做法是在启动时让设定电流按每 50ms 增加 0.1A 的速度爬升大约 2.5 秒爬到目标值电池端看到的负载变化就很缓和MOS 管承受的瞬时功耗也小很多。3.3 显示刷新策略和按键防抖OLED 用 I2C 接口屏幕本身没问题问题出在 I2C 通信占时间。SSD1306 驱动一屏数据大约要 30~50ms如果每轮循环都刷新主循环的实时性就毁了。我的方案是把刷新率压到 5Hz也就是每 200ms 更新一次显示并且只刷新变化的部分比如电压电流数字区域不整屏重绘。按键处理也一样不能直接在循环里检测电平必须做防抖。我用的是 20ms 去抖 边沿触发检测确保一次按下只触发一次动作。这里有个细节编码器如果用轮询方式读取比中断更抗干扰尤其是有 PWM 驱动 MOS 的场合电磁环境复杂外部中断很容易被误触发导致设定电流自己跳变。4. PID 参数整定和电流闭环实测4.1 为什么开环不够用必须闭环最节俭的做法是查表输出先标定 PWM 占空比和电流之间的对应关系运行时直接查表。简单是简单但温度一上来 MOS 管导通电阻变化或者电池电压下降导致采样电压变化电流就会偏离设定值而且没有反馈纠偏只能干瞪眼。闭环就不一样了ADC 实时采样电流和设定值比较后修正 PWM 输出最终把电流稳定在设定值附近。即便负载端的电压漂了反馈也会把它拉回来。这才是电子负载的“电子”二字含义所在。4.2 我调出来的参数和整定经验以 5A 量程为例经过多轮实测我最终使用的参数是参数数值影响方向Kp30越大响应越快过大容易震荡Ki0.5消除稳态误差过大会引起低频振荡Kd5抑制超调过大会放大噪声PWM 频率31.4kHz避免啸叫降低纹波采样均值次数16次滤波平滑让 PID 输入更干净整定的办法很土但有效先把 Ki 设为 0Kd 设为 0只调 Kp。从 10 开始加每加一次就设定 3A 恒流看屏幕上的电流波动。直到电流出现等幅振荡说明 Kp 临界了然后取临界值的一半作为最终 Kp。接着加 Ki让稳态误差归零但注意 Ki 加多了会出现低频起伏表现为电流值在设定值上下慢慢摆动。最后用一点点 Kd 吸收超调Kd 不要贪多否则遇到电压剧烈变化时反而振得更厉害。这个流程适用于大部分自制的电子负载。如果换了硬件不必照抄参数但整定思路是通用的。还有个小经验整定时的负载要用带一定内阻的电池别用低内阻稳压电源直接怼低内阻源会让环路增益变大整出来的参数放到真实电池上不一定稳。4.3 恒流误差实测结果我拿了一节标称 3.7V 的 18650 电池做放电测试设定 2.500A实际显示稳定在 2.493~2.508A 之间误差不到 0.4%。当然这个数字是在室温下、电池从 4.1V 放到 3.2V 整个过程中记录的MOS 管温度从中等上升到散热器微烫电流都没有跑偏。对于自制设备来说这个精度已经相当可以了。如果想追求 0.1% 的仪表级精度那就得换更高精度的参考电压源、用 16 位 ADC 外加校准程序成本和复杂度都会上来。简易设备嘛够用就好。5. 调试过程中遇到的几个大坑5.1 一上电就过流MOS 管差点冒烟第一次上电测试还没按启动键电流就飙到 6AMOS 管温度瞬间拉满。查了半天问题出在 Arduino 复位期间 GPIO 的电平状态不确定PWM 引脚复位瞬间被拉高了栅极直接导通。解决办法是在 MOS 管栅极和地之间加一个 10kΩ 下拉电阻确保单片机还没初始化时栅压为 0。另外程序启动阶段先把引脚设置为输出低电平再初始化 PWM 和 PID 状态双重保险。5.2 OLED 闪烁导致电流波动屏幕刷新和 PID 计算挤在一起的时候电流显示值会突然跳一下听起来是显示问题其实主循环被 I2C 拖慢了PID 的时效性变差真实电流也跟着抖。这个问题用状态机里的“显示刷新优先级低于 PID 更新”解决同时在 PID 计算前加一个时间戳判断距离上次计算超过 10ms 才执行防止无效的频繁计算。5.3 MOS 管发热到底怎么压电子负载的性质决定了 MOS 管就是个大发热源5A 电流、12V 输入时MOS 管上消耗 60W不做散热几秒就烧。我用的是一颗 IRFP260N加了一个 CPU 拆机的铝挤散热器外加一个 12V 涡轮风扇强制风冷温度控制在 70℃ 以下。程序里加了温度保护逻辑用 10k NTC 贴在散热器上ADC 读温度值超 90℃ 直接关断 PWM并且屏幕提示超温保护。这个功能不能省因为如果哪次测试忘记开风扇MOS 管分分钟上天。5.4 采样电阻选型别踩坑采样电阻我一开始图便宜用了 0.1Ω 的水泥电阻误差大不说温度系数还高电流一大电阻值自己就变了导致电流读数漂移。后来换成 0.01Ω10mΩ的 2512 封装合金电阻温漂低、精度高效果立竿见影。如果手头只有康铜丝也可以自己绕用万用表四线法校准一下就行。6. 后续扩展方向和个人体会这个项目做到现在已经陪我测过不少充电器、锂电池和 DC-DC 模块了。如果还想继续升级我觉得有两个方向性价比最高一是加上位机串口上位机让负载实时把电压电流数据传回电脑画出放电曲线分析电池容量和内阻变化二是加恒功率模式设定一个瓦数程序根据当前电压自动调整电流这样测电源适配器的过载保护更加方便。最后再说一个我在反复调试中最深的体会这种带功率、带反馈的嵌入式小项目故障很少出在编程逻辑本身更多是硬件电路上的“一句话坑”——下拉电阻、去耦电容、滤波电容、散热条件任何一个缺失都可能导致程序怎么写都不对。但反过来只要你把硬件链路想清楚程序的层次自然就清晰了。先用状态机把功能切分好再逐个模块验证最后联调时才能做到心中有数。希望我的这些踩坑经验能让你少走几步弯路。本文还有配套的精品资源点击获取