ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

基于STM32的Buck-Boost可调直流电源设计与PID双环控制

基于STM32的Buck-Boost可调直流电源设计与PID双环控制 简介一份基于STM32的PID控制可调直流稳压稳流电源设计文档采用Buck-Boost复合拓扑实现0-10V宽范围电压输出0-2A分辨率0.1V面向电力电子与嵌入式方向的高校学生、科研人员及电源设计工程师。内容涵盖STM32最小系统、Buck-Boost功率电路、INA226传感器接口、LCD12864显示驱动、4x4矩阵键盘驱动以及PID闭环控制、数字滤波、过压/过流/过温保护与主程序集成并给出了系统架构、设计指标和代码示例可作为实验室教学或二次开发参考。包体为单个PDF文件大小1.34MB便于阅读与打印。已有114人学习下载适合希望理解开关电源与PID算法协同工作的读者。通过对照电路框图与代码逻辑可快速掌握从硬件搭建到控制调参的完整思路并在此基础上扩展更高效或更高精度的电源方案。1. 项目概述与系统设计思路手头刚做完的这个项目是把电力电子和嵌入式控制串在一起的典型活儿——用STM32做核心控制器驱动一个Buck-Boost拓扑的功率电路实现既能升压又能降压的可调直流电源同时用PID双环把电压和电流都稳稳地管住。先说结论这个项目做完你能得到一台0~30V可调、限流可设、纹波在可接受范围内的实验电源而且关键在于整套控制逻辑是透明的、可调的、可复现的。它解决的不仅是“怎么搭一个电源”的问题更是“怎么让电源输出稳得住、响应快、不失控”的问题——这也是PID控制从理论走向工程落地的完整闭环。在做这个系统之前有几个核心问题必须想清楚否则后面调起来会非常痛苦为什么选Buck-Boost而不是单纯的Buck或Boost因为负载端既可能是12V设备需要从24V降压也可能是5V传感器需要从3.7V锂电池升压单一拓扑只能覆盖一半场景。Buck-Boost是升降压一体适应面广得多。为什么用STM32而不是专门的电源管理芯片或者模拟方案因为要可调、要显示、要保护逻辑、要和上位机通信这些需求纯模拟电路能实现但改参数极不方便专用DSP成本和技术门槛又高STM32F103系列性价比极高资料多开发环境成熟适合做毕业设计也适合做产品原型。为什么用PID双环因为只用单电压环时负载突变会引起输出电压大起大落电流冲击可能烧负载。电流内环先起作用限制过流电压外环再做精细调节两级各管一摊这是工程上最稳妥的做法。我用的主控是STM32F103C8T6其实就是大家熟知的“蓝丸”核心板价格便宜72MHz主频跑PID运算绰绰有余内置12位ADC和高级定时器TIM1能输出带死区控制的互补PWM这对驱动半桥极其友好。2. 硬件设计主功率拓扑与驱动方案2.1 四开关Buck-Boost拓扑选型与参数设计现在大部分Buck-Boost方案早就不局限在传统的单电感反极性拓扑就是输出负压的那种Cuk变体而是用四开关Buck-Boost两对MOS管加一个电感输入输出同极性效率高、控制灵活。四个开关的工作逻辑可以这样理解Q1、Q2组成Buck桥臂Q3、Q4组成Boost桥臂。当输入电压高于目标输出电压时只有Q1、Q2在做PWM开关Q3常开、Q4常闭系统工作在降压模式。当输入电压低于目标输出电压时Q1常开、Q2常闭Q3、Q4在做PWM开关系统工作在升压模式。当输入电压和目标输出电压接近时四管同时开关进入Buck-Boost过渡区。我这次用的频率是40kHz。为什么选这个值电感设计公式是这样的L (Vin - Vout) × D × T / ΔI其中D是占空比T是开关周期ΔI是允许的电感电流纹波。以12V输入、24V输出、最大负载2A、纹波系数取20%来计算ΔI 0.4AD ≈ (Vout - Vin) / Vout 0.5T 25μs代入公式L ≈ (24-12) × 0.5 × 25μs / 0.4A ≈ 375μH。实际我取了一个330μH的功率电感比算出来的值略小代价是纹波稍微大一点点但动态响应会更快。电感选型时要注意饱和电流至少是最大峰值电流的1.5倍。2.2 驱动电路与关键器件选择要点很多新手在驱动这一环翻车。STM32的GPIO输出高电平是3.3V而功率MOS管的栅极驱动电压最好在10V以上才能完全导通不然MOS管工作在线性区发热量巨大直接烧管。我的方案是IR2104半桥驱动芯片——便宜、经典、自带死区时间。STM32的TIM1输出互补PWM经过IR2104自举升压后驱动上管再用普通驱动能力驱动下管。每片IR2104负责一个桥臂两片搞定四开关拓扑。MOS管选的是IRF540N耐压100V电流33A导通电阻只有77mΩ在40kHz以下开关频率下完全够用。管子的栅极串一个10Ω电阻来限制驱动电流防止振铃栅源之间加一个10kΩ下拉电阻防止上电瞬间误导通。输出电容用的是两个470μF电解电容并联再加一个0.1μF瓷片电容滤高频前面输入侧同样加一个大电解电容吸收开关纹波。有一点特别提醒功率电路和STM32控制板的地要采用单点接地功率地和控制地在电源入口处汇合否则开关噪声会干扰ADC采样PID算得再准也没用采样进来全是噪声。2.3 电压电流采样链路设计PID双环控制能不能收敛很大程度上取决于采样准不准。电压采样我用的电阻分压电压跟随器方案分压比11:1把0~30V变成0~2.73V送入STM32的ADC通道。电流采样用了ACS712霍尔电流传感器5A量程输出灵敏度185mV/A可以测直流也可以测交流关键是它实现了主电路和采样电路之间的电气隔离安全性好。ADC这一块有很多人想省事直接拿GPIO口去读电位器我劝你千万别这么干。STM32 ADC的输入阻抗是要求信号源阻抗足够低的直接接分压电阻会导致采样值漂移误差超过5%。我在ADC前端加了RC滤波R100ΩC0.1μF截止频率大概16kHz既能滤掉一部分开关纹波又不会拖慢响应速度。3. 软件架构STM32与PID控制核心实现3.1 控制整体框架与时序分配软件上我用的是标准的前后台结构没用实时操作系统——这个项目规模用RTOS反而增加负担。主循环负责按键扫描、LCD刷新、串口收数据这些事对实时性要求低两个定时器中断干重活TIM1产生40kHz的PWM驱动开关管TIM2定时器每100μs触发一次ADC采样和PID运算。100μs的采样周期意味着控制的数字带宽是10kHz对电源这种被控对象来说完全足够。电流环比电压环快这是双环控制的基本原则——电流环先看到扰动先行动电压环后知后觉但负责把最终误差拉到零。PID输出最终映射到PWM的占空比寄存器CCR上。STM32的TIM1是16位定时器ARR设为1000所以PWM分辨率是0.1%控制量为000~1000之间的整数。PID输出经过限幅处理钳位在50~950之间留出死区和最小脉宽的保护余量。我用的是增量式PID而不是位置式PID原因很简单增量式输出的是控制量的增量也就是每次调整多少占空比而不是直接输出绝对值。好处是积分饱和问题天然被弱化——历史误差累积不会无限堆高只要限幅设计合理系统就不会出现大幅度超调后长时间回不来的情况。float IncrementalPID(float target, float current, PID_t *pid) { float error target - current; float dError error - pid-lastError; pid-integral error; pid-integral constrain(pid-integral, -pid-iLimit, pid-iLimit); float output pid-Kp * error pid-Ki * pid-integral pid-Kd * dError; pid-lastError error; return constrain(output, -pid-outputLimit, pid-outputLimit); }增量式PID的输出是增量值所以我做个累积器来跟踪当前的占空比设定值每次在中断里执行duty output。下面的代码是电压电流双环协调控制的核心逻辑为了防积分饱和电压环在输出接近限幅值时把积分清零。// 电流内环 电压外环 协调控制 void Control_Loop(void) { adc_value ADC_GetValue(ADC_CH_VOUT); vout (float)adc_value * VOLTAGE_SCALE; iout (float)ADC_GetValue(ADC_CH_IOUT) * CURRENT_SCALE; // 先算电压环输出作为电流环的目标值 float voltOut IncrementalPID(targetVoltage, vout, pidVoltage); float currTarget voltOut * CURRENT_LIMIT_FACTOR; // 再算电流环输出得到最终PWM增量 float currOut IncrementalPID(currTarget, iout, pidCurrent); pwmDuty currOut; pwmDuty constrain(pwmDuty, PWM_MIN, PWM_MAX); TIM1-CCR1 pwmDuty; // Buck上管 TIM1-CCR3 pwmDuty; // 根据模式映射到对应PWM }3.2 稳压稳流两种模式切换与软启动电源必须能工作在CV和CC两种模式。CV模式就是恒压输出电流不超过设定值CC模式是恒流输出电压被负载压到设定值以下。实现方式我用的不是切换两套PID参数而是让两个环同时运算哪个占主动看负载情况如果输出电流还没到限流值电压环主导电流环输出会趋向为零一旦电流到了限流值电压环的误差会变得很大但它的输出被限幅器挡住电流环自然接管。这个思路叫“双环自动切换”实现简单切换过程平滑不会出现两个环互相打架的情况。软启动是必须做的否则电源上电瞬间输出电容充电电流巨大会触发过流保护甚至烧MOS管。我的做法是上电后把目标电压从0逐步爬升到设定值每10ms增加1%整个过程持续1秒。同时在软件里加了延时触发主循环里做超时计数器启动完成后才允许设定电流值生效。3.3 STM32的开发环境搭建与工程移植很多刚接触STM32的人卡在第一关——开发环境。我用的是Keil MDK 5 STM32CubeMX生成初始化代码 HAL库开发的组合。CubeMX的好处是图形化配置时钟树、GPIO、定时器、ADC这些外设参数生成代码后直接往里面填业务逻辑。有同学问我为什么用HAL库而不是标准外设库——HAL库虽然代码冗余大一点但是移植性是真的好不同型号的STM32之间差别能降到最低而且现在市面上大部分资料都是基于HAL库的。如果是从零开始搭工程我的建议路径是先装好Keil MDK 5和对应的器件库确保能编译空工程用STM32CubeMX创建工程配好RCC、SWD调试口、USART1用于打印日志配置TIM1输出两路互补PWM频率40kHz死区时间1μs配置ADC1的通道0和通道1都采用连续转换模式、DMA做搬运减轻CPU负担配置TIM2定时器100μs中断在中断回调函数里触发PID运算调试时我用ST-Link V2做下载器调试工具可以实时查看全局变量变化。记得在CubeMX里把SWD接口勾选上否则程序跑起来后会把调试引脚复用成GPIO直接导致连接失败——这个问题我踩过好几次每次都是重新按住复位键抢时间下载踩一次长记性。4. PID调参与实验测试记录4.1 手把手PID参数整定流程PID参数整定是最容易劝退人的环节但其实有套路可循。我采用的是“先内环后外环先用比例后加积分”的分步整定方法。每一步都是为了观察清楚系统响应普适性很强把这个过程记录下来可以直接抄作业第一步电流环整定。把电压环禁用电流环目标值设为1AKp从0.1开始往上加观察电流波形。当Kp加到一定值波形开始出现高频震荡能看到电流在1A附近以开关频率周期抖动就说明Kp过大退回上一个值然后加一点Ki来消除稳态误差。我最后整出来的电流环参数是Kp0.8Ki0.05Kd0。第二步电压环整定。此时把电流环的PID输出接到PWM上电压环输出作为电流环目标。电压环Kp从0.2开始每次增大30%看输出的阶跃响应。如果电压过冲到设定值的110%以上就停下来适当加Kd来压低超调。我最后的电压环参数是Kp1.5Ki0.08Kd0.3。第三步联合调试。双环都放开做负载突变测试。调参时有个非常实用的技巧用STM32的串口把寄存器里的中间变量实时打印出来——电压误差、电流误差、PID输出值、PWM占空比40kHz的数据肯定打不完但你可以每100个采样点只发送一个点的数据这样波形就是10Hz的降采样版本完全够用观察系统行为。数据接到电脑上用串口助手存成CSV直接用Excel画图这套土办法比买示波器还直观。4.2 实测数据与动态响应分析测试条件输入12V蓄电池输出目标24V负载通过电子负载逐级加载。负载电流输出电压输出纹波(峰峰值)电压偏差0A24.01V30mV0.04%0.5A23.98V42mV-0.08%1.0A23.96V55mV-0.17%1.5A23.93V68mV-0.29%2.0A23.88V80mV-0.50%负载从0.5A突加到1.5A时电压跌落大约320mV恢复时间约4ms超调量不到设定值的1%。这个动态性能虽然没有商用电源模块那么极致但作为自己设计的实验电源已经算很出色的成绩了。如果需要进一步提升可以把开关频率提高到80kHz用更小的电感值再加上前馈控制——用输入电压和负载电流计算出一个基础占空比PID只需要在基础值上做微调这样扰动抑制能力会强一大截。4.3 两种PID算法对比为什么增量式更适合电源再展开说一下增量式和位置式的区别。位置式PID的输出量是绝对的占空比值公式里积分项对历史上所有误差求和——这有个隐患一旦系统长时间输出饱和积分项会累积到一个很大的值等误差反转时系统要花很长时间才能把积分拉回正常范围这个现象就叫积分饱和。增量式只关心误差的变化量输出的每个时刻都是当前控制量和上一时刻控制量的差值积分饱和的问题就小得多。只要输出限幅和积分限幅设计合理系统就算长时间工作在饱和区一旦误差变小也能迅速恢复响应。当然增量式也有代价它对采样噪声更敏感。因为它在计算中用了误差的一阶差分如果ADC采样值本身就是抖动的差分操作会把噪声放大。所以前面说的ADC硬件滤波和软件均值滤波一个都不能少我的做法是对同一个电压通道连续采样8次去掉最大值最小值剩下6个取平均。5. 常见问题排查与调试技巧5.1 电源输出异常振荡、啸叫与电压跌落实际调试过程中几乎没有一次上电就能稳定运行的。我整理了几个最常见的情况和排查思路状况一空载正常加载后电压跌落明显。先怀疑是不是电压环响应不够快把Kp往上加看看情况变不变。如果加了Kp后波形开始震荡就在电流环上找问题——电流环的响应带宽还有余量的话把电流环Kp也往上提。有时候单纯是采样延迟太大可以尝试减短ADC采样滤波深度。状况二输出有吱吱的啸叫声。开关频率落在人耳听觉范围内的部分被电感、电容谐振激发出可听噪声或者是PWM在轻载时出现了低频调制占空比跳动频率在几kHz级别从而发出啸叫。排查方法是在电感附近听声源然后用万用表量输出是否异常。解决思路是改用跳周期模式比如轻载时每小时钟周期跳一次或者增加最小脉宽限制。状况三输出电压是有了但纹波奇大无比。示波器接上看到一串毛刺注意探头要打到10×挡位另外用弹簧地线代替长地夹——这个很多人不知道用长地夹量的纹波数值完全不可信。真实衰减后如果纹波还是大检查输出电容ESR便宜的电解电容ESR高纹波滤不好需要并联瓷片电容。5.2 常见开发环境错误汇总不少同学用Keil下载程序时遇到过这个错误error: no stm32 target found! If your product embeds debug authentication, please这个报错通常意味着ST-Link和芯片之间的SWD通信建立不起来。大多数情况下是芯片已经被烧过程序且代码把SWD引脚占用了解决办法是按住板子上的复位键点击下载的同时松开复位键抢在程序启动前建立通信然后赶紧擦除Flash。还有可能就是ST-Link线序接错尤其注意SWDIO和SWCLK是不是接反了。另一个高频问题是用VSCode开发STM32时编译链配置失败。VSCode EIDE插件可以搭建轻量级开发环境但要注意把arm-none-eabi-gcc的路径配置到系统环境变量里还需要在.vscode/c_cpp_properties.json里手动指定芯片的头文件目录否则代码补全和语法检测全崩。5.3 STM32开发中的硬件干扰排查手段电源项目和电机项目很像主功率回路和主控贴得很近电磁干扰是避免不了的。我在调试时遇到ADC采样值周期性跳变、同一个采样值在不同通道间串扰的问题排查到最后就是接地问题。建议做法是所有传感器地线单独汇总到功率地控制板和功率板之间用磁珠或0Ω电阻隔离地平面。串口线如果干扰大可以降低波特率到9600并在数据上加CRC校验。6. 我的实战心得与下一步扩展方向这个项目做完我最深的感受是硬件电路设计决定系统的性能下限而PID控制软件决定系统能不能逼近这个下限。很多人在调参时一上来就猛增Kp其实先要检查硬件层——采样值稳不稳、PWM死区对不对、电感有没有选对硬件是地基地基没打好控制逻辑再好都白搭。再分享一个细节技巧PID代码里所有浮点运算对STM32F103来说略重一个中断100μs里跑完两条PID运算链浮点算下来大概占用60%~70%的CPU时间。实测不会卡死但为了留出余量我后来把参数都换成了定点数运算把Kp、Ki、Kd映射成整数用移位代替除法性能提升非常明显。有些追求极致效率的项目还会把ADC采样频率降下来但控制逻辑运算频率维持不变这也算是进一步优化的空间。如果你打算在这个项目基础之上继续做我觉得有几个很有意思的方向一是加一个基于ESP8266或K210的无线通信模块把电源的电压电流数据实时传到手机AppK210的并行处理和图像识别能力可以顺带做状态监控面板实现远程监测和预警二是引入模糊PID整定根据误差大小自动切换控制参数让大信号响应快、小信号精度高三是做主动式纹波抑制用一对反向串联的电容做纹波对消。这些扩展都不是从零开始——Buck-Boost主功率是底层硬件PID双环是核心控制逻辑通信和交互只是在这两者之上做应用层而已。最后说句实在话这次踩过的所有坑、调过的每一组参数最后沉淀下来的价值都大于“做出了一个电源”本身。控制逻辑是通用的把PID的原理吃透往电机调速、温度控制、逆变器项目上迁移都只需要改改被控对象的模型和参数。这就是基础项目能带来的杠杆效应。本文还有配套的精品资源点击获取
返回列表