1. 案例1

案例1:基于串口打印的PID参数整定与调试 学习卡片

任务定义

本案例面向一个一阶惯性加纯延迟的模拟被控对象(例如直流电机转速环),要求通过串口以文本帧格式输出PID控制器的设定值、反馈值与控制量,在PC端串口终端或绘图工具中观察阶跃响应曲线。手动调整Kp、Ki、Kd三个参数,使系统满足:超调量≤10%,稳态误差≤2%,调节时间(进入±5%误差带)≤1.5s。代码在STM32F103系列MCU上运行,通过USART1以115200-8-N-1输出调试数据。

被控对象与控制器模型

被控对象传递函数为G(s)=1/(0.5s+1)·e^(-0.1s),采用零阶保持器离散化,采样周期Ts=10ms。PID控制器采用位置式算法,输出限幅[-100,100],积分分离与抗积分饱和通过输出限幅自然实现。代码中直接给出被控对象差分方程,不依赖外部硬件即可在开发板上运行并产生响应数据。

核心代码实现


#include <stdio.h>
#include <stdint.h>

// 串口发送字符串(需根据实际MCU驱动实现)
void USART_SendString(char* s) {
    while(*s) {
        // 阻塞发送单个字符至USART1数据寄存器
        // 实际项目中替换为寄存器操作或HAL库函数
        s++;
    }
}

// 被控对象参数(离散化后)
static float y = 0.0f;       // 系统输出(反馈值)
static float y_prev = 0.0f;  // 上一拍输出
static float u = 0.0f;       // 控制器输出
static float e_prev = 0.0f;  // 上一拍误差
static float integral = 0.0f;// 积分项累加值

// PID参数(手动调整区域)
#define KP  1.2f
#define KI  0.8f
#define KD  0.05f

// 目标值阶跃
#define SETPOINT  50.0f

// 被控对象差分方程:y[k]=0.8187*y[k-1]+0.1813*u[k-2]
// 对应G(s)=1/(0.5s+1)离散化后并加入一拍纯延迟
void PlantUpdate(float control) {
    static float u_delay1 = 0.0f;
    static float u_delay2 = 0.0f;
    u_delay2 = u_delay1;
    u_delay1 = control;
    y = 0.8187f * y_prev + 0.1813f * u_delay2;
    y_prev = y;
}

// 位置式PID计算
float PID_Compute(float setpoint, float feedback) {
    float error = setpoint - feedback;
    integral += error;
    // 输出限幅[-100,100]
    float out = KP * error + KI * integral + KD * (error - e_prev);
    e_prev = error;
    if(out > 100.0f) out = 100.0f;
    if(out < -100.0f) out = -100.0f;
    return out;
}

// 模拟控制周期10ms
void ControlLoop(void) {
    u = PID_Compute(SETPOINT, y);
    PlantUpdate(u);
    
    // 串口输出:设定值,反馈值,控制量
    char buf[64];
    sprintf(buf, "%.1f,%.1f,%.1f\n", SETPOINT, y, u);
    USART_SendString(buf);
}

int main(void) {
    // 初始化系统时钟、USART1(115200-8-N-1)
    // 初始化定时器中断,每10ms调用一次ControlLoop()
    // 此处为演示结构,实际需配置中断
    while(1) {
        // 主循环空转,控制由定时器中断驱动
    }
    return 0;
}

参数整定步骤与判定标准

将代码烧录至开发板后,打开串口终端(如PuTTY、串口助手)或使用Python脚本读取串口数据并实时绘图。观察阶跃响应曲线,按以下顺序调整:

  1. 先置Ki=0,Kd=0,仅用Kp从0.5开始逐步增大,观察响应速度与振荡情况,直至出现临界振荡(持续等幅振荡),记录此时Kp值;
  2. 取Kp为临界值的0.6倍,加入Ki(初始0.2),逐步增大以消除稳态误差,注意观察超调量;
  3. 若超调过大,加入Kd(初始0.01),逐步增大以抑制超调,同时观察是否引入高频噪声;
  4. 重复微调直至满足:超调量≤10%,稳态误差≤2%(即稳态值在49~51之间),调节时间≤1.5s(从阶跃开始到输出进入并保持在47.5~52.5范围内)。

验证方法

在串口终端中观察输出数据流,记录从阶跃开始到响应稳定的时间戳与数值。将数据导入Excel或MATLAB,绘制响应曲线,测量超调量(峰值-设定值)/设定值×100%、稳态误差(稳态均值-设定值)以及调节时间。若三项指标均满足要求,则整定完成。若无法满足,检查被控对象模型参数是否与代码一致,或调整PID参数搜索范围。

串口PID调试数据流与响应曲线观测 串口输出帧格式 (115200-8-N-1, 每10ms一帧) 设定值(50.0) , 反馈值(y) , 控制量(u) \n 设定值 r(t) Σ - PID控制器 Kp Ki Kd 被控对象 G(s)=1/(0.5s+1) 输出 y(t) 反馈(串口监视) PC串口终端/绘图 50.0, 12.3, 45.2 50.0, 25.7, 38.9 50.0, 36.1, 22.4 阶跃响应曲线(串口数据绘图) y t 设定值=50 超调量 调节时间 ±5%误差带(47.5~52.5) 整定目标 超调量 ≤ 10% 稳态误差 ≤ 2% 调节时间 ≤ 1.5s

调试观测点说明

上图中串口数据帧以CSV格式输出,便于直接导入Excel或绘图工具。响应曲线中蓝色虚线为设定值50,红色实线为系统输出。观测重点:①输出首次到达50的时刻对应延迟时间;②峰值与50的差值计算超调量;③进入±5%误差带(47.5~52.5)后不再超出即为调节时间终点;④稳态后输出均值与50的偏差为稳态误差。若曲线发散或持续振荡,应立即减小Kp或Ki。