从零开始:用STM32和PID算法打造一个带双闭环的数控电源(附完整代码)

张开发
2026/4/19 9:26:30 15 分钟阅读

分享文章

从零开始:用STM32和PID算法打造一个带双闭环的数控电源(附完整代码)
从零开始用STM32和PID算法打造一个带双闭环的数控电源附完整代码最近在工作室折腾数控电源项目时发现市面上成品要么价格昂贵要么功能单一。于是萌生了自己动手做一个的念头——既能满足日常给开发板供电的需求又能作为学习PID控制和电力电子的绝佳实践。这个项目最吸引人的地方在于它完美结合了硬件电路设计和嵌入式软件开发从BUCK降压电路到STM32的PID算法实现每一步都充满挑战和乐趣。1. 硬件设计与元件选型1.1 BUCK降压电路核心设计BUCK电路作为整个系统的功率转换核心其设计直接决定了电源的效率和稳定性。我选择了同步整流方案相比传统二极管续流方式效率能提升5-8%。关键元件选型需要考虑以下几个参数MOS管选择输入24V时上管选用IRF540N100V/33A下管选用IRF320555V/110A确保足够的余量电感计算根据公式L(Vin-Vout)×D/(ΔI×fsw)设定fsw100kHzΔI0.3A得到L≈68μH输出电容采用低ESR的固态电容470μF/35V并联陶瓷电容100nF组合提示实际制作时建议先用面包板搭建测试电路确认基本功能后再设计PCB可以避免很多后期调试麻烦。1.2 采样电路设计双闭环控制需要精确的电压电流采样这里采用了差分放大方案参数电压采样电流采样传感器电阻分压0.01Ω采样电阻放大电路OP07运放(增益2)INA282芯片(增益50)滤波二阶RC低通(1kHz)二阶RC低通(1kHz)ADC参考3.3V3.3V// 电压采样校准代码示例 float voRatio 3.3f / (4096 * (R2/(R1R2)) * AmpGain);2. STM32系统搭建2.1 外设配置要点使用STM32F103C8T6作为主控需要配置以下关键外设PWM生成TIM1通道1100kHz频率72MHz时钟下ARR720-1ADC采样规则组双通道触发源设为TIM1 CC1事件保护电路EXTI中断检测过压/过流信号响应时间2μs用户界面0.96寸OLED显示电压电流旋转编码器调节// PWM初始化代码片段 void PWM_Init(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); TIM_TimeBaseStructure.TIM_Period 720-1; TIM_TimeBaseStructure.TIM_Prescaler 0; TIM_TimeBaseStructure.TIM_ClockDivision 0; TIM_TimeBaseStructure.TIM_CounterMode TIM_CounterMode_Up; TIM_TimeBaseInit(TIM1, TIM_TimeBaseStructure); TIM_OCInitStructure.TIM_OCMode TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse 0; TIM_OCInitStructure.TIM_OCPolarity TIM_OCPolarity_High; TIM_OC1Init(TIM1, TIM_OCInitStructure); TIM_CtrlPWMOutputs(TIM1, ENABLE); TIM_Cmd(TIM1, ENABLE); }2.2 软件架构设计采用前后台系统架构关键任务划分如下实时控制任务1kHz执行处理PID计算和保护检测用户界面任务100Hz刷新处理编码器输入和OLED显示校准任务上电时运行自动校准零点偏移和比例系数主程序流程 ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ 系统初始化 │───▶│ 参数校准 │───▶│ 主循环 │ └─────────────┘ └─────────────┘ └─────────────┘ ▲ │ ┌───────────┴───────────┐ │ │ ┌───────▼───────┐ ┌───────▼───────┐ │ 1ms定时中断 │ │ 按键扫描 │ │ - PID计算 │ │ - 编码器处理 │ │ - 保护检测 │ │ - OLED刷新 │ └───────────────┘ └───────────────┘3. PID算法实现与调参3.1 双闭环控制策略系统采用电压外环电流内环的双闭环结构工作模式自动切换恒压模式(CV)当负载电流小于设定值时恒流模式(CC)当输出电压超过设定值时// 控制模式切换逻辑 if(device.recoveryCnt device.faultTime) { switch(device.controlMode) { case CV_MODE: device.controlPWM pidUpdate(vPID, vPID.desired, fb_vo); iPID.outLast1 device.controlPWM; device.controlMode (fb_ioiPID.desired)?CV_MODE:CC_MODE; break; case CC_MODE: device.controlPWM pidUpdate(iPID, iPID.desired, fb_io); vPID.outLast1 device.controlPWM; device.controlMode (fb_vovPID.desired)?CV_MODE:CC_MODE; break; } PWM_Update(device.controlPWM); }3.2 PID参数整定实战通过Ziegler-Nichols方法整定参数具体步骤先将Ki、Kd设为0逐渐增大Kp直到系统出现等幅振荡记录临界增益Ku和振荡周期Tu根据下表确定PID参数控制类型KpKiKdP0.5Ku--PI0.45Ku0.54Ku/Tu-PID0.6Ku1.2Ku/Tu0.075KuTu注意实际调试中发现对于开关电源系统Kd值需要适当减小以避免高频噪声放大。4. 调试技巧与性能优化4.1 常见问题解决方案在项目开发过程中遇到了几个典型问题振荡问题在输出轻载时出现通过增加输出电容ESR串联0.5Ω电阻解决采样噪声ADC采样值跳动大采用软件滑动平均滤波窗口8模式切换抖动增加5%的滞回区间避免临界状态频繁切换4.2 性能测试数据最终成品经过严格测试主要性能指标如下测试项目条件结果输出电压精度5V/2A负载±0.8%负载调整率0-3A阶跃变化50mV效率24V输入12V/3A输出89%纹波噪声12V/3A30mVpp// 滑动平均滤波实现 #define FILTER_LEN 8 typedef struct { float buf[FILTER_LEN]; uint8_t index; } Filter_t; float filterUpdate(Filter_t* f, float newVal) { f-buf[f-index] newVal; f-index (f-index 1) % FILTER_LEN; float sum 0; for(int i0; iFILTER_LEN; i) { sum f-buf[i]; } return sum / FILTER_LEN; }整个项目从设计到调试完成大约用了三周时间最耗时的部分是PID参数整定和保护电路调试。实际使用中发现给STM32供电最好采用独立的LDO而不是直接从BUCK电路取电这样可以避免MCU复位导致输出失控的情况。

更多文章