当前位置:首页 > 工业控制 > 工业控制
[导读]在STM32嵌入式控制中,PID控制器是温度、电机转速、平衡小车等闭环系统的核心算法。本文提供一份可直接移植的增量式PID代码模板,并分享工程中行之有效的参数整定方法。



STM32嵌入式控制中,PID控制器是温度、电机转速、平衡小车等闭环系统的核心算法。本文提供一份可直接移植的增量式PID代码模板,并分享工程中行之有效的参数整定方法。


一、增量式PID算法模板


相比位置式PID,增量式PID输出的是控制量的增量(Δu),天然抗积分饱和,且手动/自动切换无冲击。


pid.h


#ifndef __PID_H

#define __PID_H


typedef struct {

   float Kp, Ki, Kd;      // 比例、积分、微分系数

   float Ts;               // 采样周期(秒)

   float error[3];         // e[k], e[k-1], e[k-2]

   float output_min;       // 输出下限

   float output_max;       // 输出上限

   float last_output;      // u[k-1]

} IncPID_t;


void PID_Init(IncPID_t *pid, float kp, float ki, float kd, float ts);

float PID_Calculate(IncPID_t *pid, float setpoint, float feedback);

void PID_SetOutputLimit(IncPID_t *pid, float min, float max);


#endif



pid.c


#include "pid.h"


void PID_Init(IncPID_t *pid, float kp, float ki, float kd, float ts)

{

   pid->Kp = kp;

   pid->Ki = ki;

   pid->Kd = kd;

   pid->Ts = ts;

   pid->error[0] = pid->error[1] = pid->error[2] = 0;

   pid->last_output = 0;

   pid->output_min = -1000;

   pid->output_max = 1000;

}


float PID_Calculate(IncPID_t *pid, float setpoint, float feedback)

{

   // 1. 更新误差序列

   pid->error[2] = pid->error[1];

   pid->error[1] = pid->error[0];

   pid->error[0] = setpoint - feedback;


   // 2. 计算增量 Δu

   float delta = pid->Kp * (pid->error[0] - pid->error[1])

               + pid->Ki * pid->Ts * pid->error[0]

               + pid->Kd / pid->Ts * (pid->error[0] - 2*pid->error[1] + pid->error[2]);


   // 3. 增量限幅(防突变)

   if (delta > 50)  delta = 50;

   if (delta < -50) delta = -50;


   // 4. 累加得到绝对输出

   float output = pid->last_output + delta;


   // 5. 总输出限幅

   if (output > pid->output_max) output = pid->output_max;

   if (output < pid->output_min) output = pid->output_min;


   pid->last_output = output;

   return output;

}


void PID_SetOutputLimit(IncPID_t *pid, float min, float max)

{

   pid->output_min = min;

   pid->output_max = max;

}



二、STM32定时器调用示例


在1ms定时器中断中调用PID,输出控制PWM占空比:

IncPID_t motor_pid;


void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)

{

   if (htim->Instance == TIM3)  // 1ms定时器

   {

       float current_speed = Read_Encoder_Speed();  // 编码器反馈

       float pwm_out = PID_Calculate(&motor_pid, target_speed, current_speed);

       Set_Motor_PWM((int16_t)pwm_out);

   }

}


int main(void)

{

   HAL_Init();

   SystemClock_Config();

   MX_TIM3_Init();       // 1ms定时器

   MX_TIM1_Init();       // PWM输出


   PID_Init(&motor_pid, 1.5f, 0.01f, 0.05f, 0.001f);

   PID_SetOutputLimit(&motor_pid, -999, 999);


   HAL_TIM_Base_Start_IT(&htim3);

   HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);


   while (1)

   {

       // 可通过串口在线修改PID参数

   }

}



三、参数整定四步法


第一步:纯比例(P)试探


• Ki=0, Kd=0,Kp从小开始(如0.5)


• 给定阶跃目标,观察响应


• 若不振荡:逐步增大Kp(每次×1.5)


• 若持续等幅振荡:记录临界Kp(Ku)和振荡周期(Tu),然后Kp=0.5×Ku


第二步:加入积分(I)消除静差


• 保持Kp,从Ki=0.001开始逐步增大


• 观察稳态误差是否消失


• 若出现低频摆动:Ki过大,需减小


第三步:加入微分(D)抑制超调


• 保持Kp、Ki,从Kd=0.01开始


• 观察超调量是否减小


• 若出现高频抖动:Kd过大,需减小或滤除噪声


第四步:微调与限幅


• 积分限幅:在PID结构中增加integral_limit,防止积分饱和


• 输出死区:当误差小于阈值时输出置0,防止频繁调节


四、在线调参与调试技巧


4.1 串口透传参数


void Serial_Debug(void)

{

   char buf[64];

   sprintf(buf, "SP=%.1f FB=%.1f OUT=%.1f\r\n",

           target_speed, current_speed, pwm_out);

   HAL_UART_Transmit(&huart1, (uint8_t*)buf, strlen(buf), 10);

}



4.2 在线修改Kp/Ki/Kd


通过串口接收命令:

if (strncmp(rx_buf, "KP:", 3) == 0)

   motor_pid.Kp = atof(rx_buf + 3);



4.3 数据可视化


将SP、FB、OUT三个变量通过DAC输出或串口发给上位机(如VOFA+),实时绘制曲线,比看数值直观十倍。


五、常见问题与对策


现象 原因 对策


输出饱和后恢复慢 积分饱和 启用积分限幅或增量式PID


目标附近来回抖动 Kp过大或死区太小 减小Kp,加入5%死区


响应太慢 Kp过小或Ki过大 增大Kp,减小Ki


微分项引入噪声 反馈信号有高频噪声 对反馈做低通滤波后再微分


六、结语


本文提供的增量式PID模板可直接移植到STM32工程,配合定时器中断实现1ms周期的闭环控制。参数整定遵循先P后I再D的顺序,配合串口在线调参与波形观察,可在半小时内完成大部分系统的调优。


本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除( 邮箱:macysun@21ic.com )。
换一批
延伸阅读

在STM32软件开发中,ST官方提供两套固件库:HAL(Hardware Abstraction Layer)与LL(Low-Layer)。很多工程师困惑:两者除了API风格不同,运行效率和资源消耗究竟差多少?本文基于S...

关键字: STM32 HAL库 LL库

本项目是一个专为RT-Thread RT-Spark开发板设计的硬件与软件定制接口。它创建了一个交互式系统,通过物理输入(按钮)产生数字输出(LCD文本和LED信号)。通过连接外部面包板组件与开发板内置功能之间的桥梁,我...

关键字: LCD LED STM32

在STM32嵌入式开发中,精确延时是非常基础但又极其关键的功能。无论是驱动单总线传感器(比如DS18B20)、控制LCD屏幕时序、还是生成精确的脉冲信号,都需要用到微秒级甚至纳秒级精度的延时。很多新手刚开始使用STM32...

关键字: STM32 嵌入式

在STM32嵌入式开发中,RAM(随机存取存储器)是程序运行时存储动态数据、堆栈、全局变量的核心资源,直接决定了程序能实现的功能复杂度。很多开发者都遇到过莫名的程序崩溃、硬件异常,追根溯源往往是RAM分配错误、占用溢出:...

关键字: RAM STM32

在嵌入式STM32开发中,程序崩溃是开发者最常遇到也最头疼的问题之一:程序运行中突然跑飞、进入HardFault中断,开发者往往只能靠加打印猜位置,排查一个bug可能需要几天时间。这时候,Backtrace功能就像是嵌入...

关键字: 嵌入式STM32 STM32

特点:Arduino Uno R3 带有引脚布局,1MB Flash / 384KB RAM,支持 48MHz 和 96MHz 涡轮频率,24 个 GPIO 引脚(均可中断),21 个 PWM 渠道,内置 BLE 无线通...

关键字: 自动驾驶 机器学习 PID控制器

当一个项目需要在STM32上运行FreeRTOS时,摆在工程师面前的不止一条路。STM32CubeMX图形化配置工具的出现,让RTOS的集成从“手工作坊”变成了“流水线作业”。但这是否意味着传统的手写移植已经过时?答案并...

关键字: STM32 FreeRTOS

系统采用基于OpenCV的图像处理技术,实时检测车道线并估算车辆轨迹。根据这些信息,计算出转向角度,使车辆保持在车道中央行驶,并通过PID控制器确保转向行为平稳稳定。

关键字: PID控制器 计算机视觉 OpenCV

一块STM32G431、三颗IRFS7530 MOSFET、两个1mΩ采样电阻——这就是一台20A无人机电调的全部硬件。但从上电到电机平稳空转,中间隔着寄存器配置、ADC同步触发、Park变换、PI调参、SVPWM生成五...

关键字: STM32 无人机 FOC电调

该项目是一个基于 RT-Spark STM32 开发板的实时、裸机硬件接口。它充当了一个交互式的控制面板,将物理世界与数字世界连接起来。通过读取来自一个 5 个方向操纵杆的输入,该系统会立即触发数字逻辑来控制外部独立的...

关键字: 液晶显示屏 FSMC 开发板 STM32
关闭