控制系统建模仿真(九):PID 控制器的底层实现以及调优

前言

上一章我们讲解了PID控制器的使用,这一篇算是额外补充的,我们将用MATLAB代码和Simulink的基本模块(不使用PID control)来搭建一个PID控制器,一方面是希望能够加深大家对PID控制器的了解,一方面也是希望通过这个已知逻辑的底层实现,大家能够更熟练的使用MATLAB以及Simulink。

一、 核心原理

这边我们再复习一下上一章讲到的PID基本原理,方便后面的实现。

  1. PID 结构
    • P(比例):反应当前的误差,消除误差最快。
    • I(积分) :反应累积的误差,用于消除静差
    • D(微分) :反应误差的变化趋势,具有超前预判作用,能减少超调。
  2. PID 的表现形式
    • 并联型(Parallel) :C(s)=Kp+Kis+KdsC(s) = K_p + \frac{K_i}{s} + K_d sC(s)=Kp+sKi+Kds(MATLAB 默认)。
    • 标准型(Standard) :C(s)=Kp(1+1Tis+Tds)C(s) = K_p (1 + \frac{1}{T_i s} + T_d s)C(s)=Kp(1+Tis1+Tds)。
  3. 整定方法
    • 传统法:齐格勒-尼科尔斯(Ziegler-Nichols)经验公式。
    • 自动法:基于频率响应的自动整定技术(MATLAB 强项)。
    • 最优法:利用 ITAE、ISE 等误差性能指标进行最优化搜索。

二、题目

三、 建模部分(Simulink)

首先,我们要在Simulink里面搭建我们的题目条件以及底层的PID控制器:


一、模型整体功能概述

这个模型的核心目标有两个:

  1. 实现 PID 闭环控制:通过比例(P)、积分(I)、微分(D)三环节,对被控对象(一阶惯性环节)进行跟踪控制。
  2. 评估控制性能:计算 IAE(Integral of Absolute Error,绝对误差积分)指标,量化系统的跟踪精度与动态响应品质。

二、核心模块逐一拆解

我们从左到右、从上到下解析每个功能模块:

1. 输入与误差计算

  • 阶跃信号模块 :作为系统的参考输入(Setpoint),模拟实际场景中"让系统从稳态切换到新目标值"的需求(比如让电机转速从0提升到1000rpm)。
  • 求和模块(减法器) :计算误差信号 ( e(t) = r(t) - y(t) )(参考输入减去系统输出),这是 PID 控制器的输入信号。
  • out.e 输出端口:导出误差信号,方便后续分析或在 Scope 中观察误差随时间的变化曲线。

2. PID 控制器核心环节

PID 控制器的输出是三个环节的叠加:
u(t)=Kpe(t)+Ki∫0te(τ)dτ+Kdde(t)dtu(t) = K_p e(t) + K_i \int_0^t e(\tau) d\tau + K_d \frac{de(t)}{dt}u(t)=Kpe(t)+Ki∫0te(τ)dτ+Kddtde(t)

对应图中的三个分支:

  • 比例(P)环节 :直接对误差信号乘以比例系数 KpK_pKp,快速响应误差,但过大的 KpK_pKp 会导致系统振荡。
  • 积分(I)环节 :误差信号先经过积分器(1/s 模块,代表积分运算∫e(t)dt\int e(t)dt∫e(t)dt,再乘以积分系数 KiK_iKi,用于消除稳态误差,但会增加系统超调。
  • 微分(D)环节 :误差信号先经过微分器(Δu/Δt 模块,代表微分运算 de(t)dt\frac{de(t)}{dt}dtde(t),再乘以微分系数 KdK_dKd,用于抑制超调、加快响应,但对噪声敏感。
  • 求和模块(加法器):将 P、I、D 三个环节的输出叠加,得到 PID 控制器的总输出 u(t)

3. 非线性环节(饱和模块)

在 PID 输出之后,可以串联一个饱和模块,这是工业场景的典型设计:

  • 模拟执行器的"输出能力限制"(比如阀门的最大开度、电机的最大扭矩)。
  • 防止控制器输出超出硬件极限,避免系统进入非线性失控状态。

4. 被控对象

模型中的被控对象是一个一阶惯性环节,传递函数为:

G(s)=148s+1G(s) = \frac{1}{48s + 1}G(s)=48s+11

  • 一阶惯性环节是工业中最常见的近似模型(比如温度、液位等慢响应过程),48s+1 表示系统的时间常数为48秒,反映了系统响应的快慢。
  • 输入是 PID 控制器的输出 u(t)u(t)u(t),输出是系统的实际响应y(t)y(t)y(t)。

5. IAE 性能指标计算

IAE 是控制系统常用的性能指标,定义为:

IAE=∫0∞∣e(t)∣dt\text{IAE} = \int_0^\infty |e(t)| dtIAE=∫0∞∣e(t)∣dt

对应图中的两个模块:

  • 绝对值模块(|u| :对系统输出 y(t)y(t)y(t)与参考输入 r(t)r(t)r(t)的误差取绝对值,得到 ∣e(t)∣|e(t)|∣e(t)∣。
  • 积分器(1/s 模块) :对 ∣e(t)∣|e(t)|∣e(t)∣进行积分运算,最终输出就是 IAE 指标值(out.simout 端口导出)。
  • 物理意义:IAE 越小,说明系统跟踪误差的累积越小,控制精度越高。

三、模型工作流程闭环逻辑

  1. 输入触发:阶跃信号产生参考输入 ( r(t) )。
  2. 误差生成:减法器计算误差 ( e(t) = r(t) - y(t) )。
  3. PID 运算:P/I/D 环节分别处理误差,叠加得到控制输出 ( u(t) )。
  4. 输出限幅:饱和模块限制 ( u(t) ) 的范围,模拟执行器约束。
  5. 对象响应:被控对象接收 ( u(t) ),输出实际响应 ( y(t) )。
  6. 反馈闭环:( y(t) ) 反馈到减法器,更新误差信号,形成闭环控制。
  7. 性能评估:绝对值+积分模块计算 IAE,量化控制效果。

三、 编程部分(MATLAB)

你希望我详细讲解这段名为 pid_iae_cost 的 MATLAB 函数代码,我会从功能、逐行逻辑、使用场景三个维度拆解,让你彻底理解它的作用和实现原理。

MATLAB代码一:pid_iae_cost函数

一、函数整体功能总结

这个函数是 PID 参数优化的代价函数(Cost Function) ,核心作用是:

输入一组 PID 参数(Kp/Ki/Kd),自动运行指定的 Simulink 模型,计算该参数下系统的 IAE(绝对误差积分) 值并返回;若参数非法或仿真出错,返回一个极大的惩罚值(1e6),避免优化算法选择无效参数。

简单来说,它是"自动调参"的核心:优化算法(如 fmincon/遗传算法)会反复调用这个函数,尝试不同的 PID 参数,最终找到使 IAE 最小的最优参数。

二、逐行代码解析

matlab 复制代码
function J = pid_iae_cost(x, modelName, T_end)
    % 1. 提取PID参数:x是优化算法传入的参数向量,格式为[Kp, Ki, Kd]
    Kp = x(1); Ki = x(2); Kd = x(3);
    
    % 2. 参数合法性校验:PID参数通常非负(工程上极少用负数)
    if any(x < 0)
        J = 1e6;  % 若有负数参数,返回极大惩罚值(让优化算法放弃该参数)
        return;   % 直接退出函数,不执行后续仿真
    end
    
    % 3. 将参数赋值到MATLAB基础工作区
    assignin('base','Kp',Kp);
    assignin('base','Ki',Ki);
    assignin('base','Kd',Kd);
    
    % 4. 执行Simulink仿真并计算IAE(带异常处理,避免程序崩溃)
    try
        % 运行指定的Simulink模型,设置仿真结束时间,保存输出和时间数据
        simOut = sim(modelName, 'StopTime', num2str(T_end), ...
                     'SaveOutput', 'on', 'SaveTime', 'on');
                 
        e = simOut.e.Data;       % 提取仿真输出的误差信号e(对应Simulink的out.e端口)
        t = simOut.tout;         % 提取仿真的时间向量(横轴)    
        
        J = trapz(t, abs(e));    % 核心:用梯形积分法计算IAE(绝对误差积分)
        
    catch ME  % 捕获仿真过程中的错误(如模型不存在、参数非法等)
        disp(['仿真错误: ' ME.message]);  % 打印错误信息,方便调试
        J = 1e6;  % 返回惩罚值,保证优化算法能继续运行
    end
end
关键代码解释
  1. 参数提取与校验

    • x 是优化算法(如 fmincon)传入的参数向量,必须是 [Kp, Ki, Kd] 顺序;
    • any(x < 0) 检查是否有参数为负,工程上 PID 参数几乎都是非负的(负数会导致控制逻辑混乱),因此用 1e6 作为"惩罚值"------优化算法的目标是最小化 J,会自动避开这类参数。
  2. assignin 函数的作用

    • 上面的Simulink 模型中,PID 模块的参数(Kp/Ki/Kd)引用了 MATLAB 基础工作区 的变量(而非固定值);
    • assignin('base','Kp',Kp) 把函数内的 Kp 值"传递"到基础工作区,让 Simulink 模型能实时使用新的参数,这是"动态调参"的关键。
  3. 仿真与 IAE 计算

    • sim() 函数:自动运行 Simulink 模型,StopTime 设置仿真结束时间,SaveOutput 开启输出保存;
    • simOut.e.Data:提取你之前 Simulink 模型中 out.e 端口的误差信号数据(即e(t)=参考输入−系统输出e(t) = 参考输入 - 系统输出e(t)=参考输入−系统输出);
    • trapz(t, abs(e)):用 梯形积分法 计算 IAE=∫0Tend∣e(t)∣dt\text{IAE} = \int_0^{T_{end}} |e(t)| dtIAE=∫0Tend∣e(t)∣dt,这是数值积分中最常用、最稳定的方法,比简单求和更精准。
  4. 异常处理(try-catch)

    • 仿真可能出错(比如模型路径写错、参数超出执行器极限导致模型报错);
    • catch 块会捕获错误,打印提示信息,并返回惩罚值 1e6,避免优化算法因单次仿真失败而终止。

MATLAB代码二:主函数

你希望我详细讲解这段完整的 MATLAB 脚本,它是一套"PID 参数自动寻优 + 结果验证 + 可视化"的完整工作流,核心是用 fminsearch 算法找到使 IAE 最小的最优 PID 参数,并直观展示最优参数下的误差曲线。我会逐行拆解逻辑,同时说明关键函数的用法和注意事项。

一、脚本整体功能总结

这段脚本的核心目标是:

  1. 清空工作区、命令行和图表,初始化仿真参数;
  2. fminsearch 无约束优化算法,调用 pid_iae_cost 代价函数,自动迭代寻找最优 PID 参数(Kp/Ki/Kd);
  3. 输出最优参数和对应的最小 IAE 值;
  4. 用最优参数重新运行 Simulink 模型,绘制误差曲线,直观验证控制效果。

二、逐行代码解析

matlab 复制代码
% ===================== 第一步:环境初始化与参数设置 =====================
clear; clc; close all;  % 清理工作区变量、清空命令行、关闭所有绘图窗口(避免干扰)
modelName = 'pid_iae_model';   % 你的Simulink模型名(必须和.slx文件名一致)
T_end = 300;                   % 仿真结束时间(300秒,足够系统达到稳态)

assignin('base','T_end',T_end);  % (可选)将T_end传递到基础工作区,供Simulink模型调用(若模型用到)

% 第二步:设置优化初始值和算法参数
x0 = [0.5, 0.1, 0.01];   % PID参数初始猜测值 [Kp, Ki, Kd],可根据经验调整
options = optimset('Display','iter',...  % 优化选项配置:显示迭代过程(方便看寻优进度)
                   'TolX',1e-3,...       % 参数收敛精度:参数变化小于1e-3时停止迭代
                   'TolFun',1e-3,...     % 代价函数收敛精度:IAE变化小于1e-3时停止迭代
                   'MaxIter',60,...      % 最大迭代次数:最多迭代60次
                   'MaxFunEvals',120);   % 最大函数调用次数:最多调用120次pid_iae_cost

% 第三步:调用fminsearch寻找最优PID参数
[x_opt,J_opt] = fminsearch( ...
                @(x) pid_iae_cost(x,modelName,T_end), x0, options);
% 解释:@(x)是匿名函数,把x(PID参数)、modelName、T_end传给pid_iae_cost;
% x_opt:返回的最优PID参数 [Kp_opt, Ki_opt, Kd_opt];
% J_opt:返回最优参数下的最小IAE值。

% 第四步:输出最优结果(格式化打印,更易读)
fprintf('\n 最优 PID 参数:\nKp = %.4f\nKi = %.4f\nKd = %.4f\n', ...
        x_opt(1),x_opt(2),x_opt(3));  % %.4f表示保留4位小数
fprintf('最小 IAE = %.6f\n',J_opt);   % 保留6位小数,更精准

% 第五步:用最优参数更新工作区,重新运行仿真
assignin('base','Kp',x_opt(1));  % 把最优Kp传给基础工作区
assignin('base','Ki',x_opt(2));  % 最优Ki
assignin('base','Kd',x_opt(3));  % 最优Kd

simOut = sim(modelName, 'StopTime', num2str(T_end));  % 用最优参数运行Simulink模型

% 第六步:提取仿真数据,绘制误差曲线
t = simOut.tout;    % 提取仿真时间向量
e = simOut.e.Data;  % 提取误差信号e(t)的数据

figure;  % 新建绘图窗口
plot(t, e, 'LineWidth', 1.5);  % 绘制误差曲线,线宽1.5(更清晰)
xlabel('时间 t (s)');          % x轴标签
ylabel('误差 e(t)');           % y轴标签
title(['最优PID控制下的误差曲线 (IAE=' num2str(J_opt) ')']);  % 标题包含IAE值
grid on;  % 显示网格,方便读取数值

三、关键知识点补充

1. fminsearch vs fmincon(优化算法选择)
  • fminsearch:无约束优化算法(基于单纯形法),优点是无需安装优化工具箱 (MATLAB基础版就有)、用法简单;缺点是无法直接设置参数上下限(但你的pid_iae_cost里已经用any(x<0)限制了非负,间接实现约束)。
  • fmincon:有约束优化算法(需优化工具箱),可直接设置参数上下限(如lb=[0,0,0], ub=[10,2,1]),寻优更精准,但依赖工具箱。
  • 你这段脚本用fminsearch更轻量化,适合新手入门。
2. optimset 参数的含义(新手必懂)
参数名 作用
Display','iter 显示迭代过程(打印每一步的参数和IAE值),方便调试;若设为'off'则不显示
TolX 参数收敛阈值:两次迭代的PID参数变化小于1e-3时,认为参数收敛,停止迭代
TolFun 代价函数收敛阈值:两次迭代的IAE值变化小于1e-3时,认为IAE收敛
MaxIter 最大迭代次数:防止算法无限迭代(60次足够PID寻优)
MaxFunEvals 最大函数调用次数:限制pid_iae_cost的调用次数(避免仿真耗时过久)
3. 常见问题与避坑点
  • 报错:找不到模型/变量 :确保modelName和Simulink模型文件名完全一致,且模型文件在MATLAB当前工作目录下;
  • 迭代次数用完仍未收敛 :可适当增大MaxIter(如改为100)或放宽TolX/TolFun(如改为1e-2);
  • 误差曲线为空 :检查Simulink模型的out.e端口是否正确命名,且SaveOutput是否开启(pid_iae_cost里的sim函数已设置SaveOutput='on',无需额外设置);
  • 最优参数为0 :初始值x0设置不合理(如太小),可调整x0(比如[1,0.2,0.05]),或增大参数上限(若用fmincon)。

总结

  1. 这段脚本是完整的PID参数自动寻优工作流:初始化→参数寻优→结果输出→仿真验证→可视化,覆盖了工程中PID整定的核心环节;
  2. 核心逻辑是用fminsearch调用pid_iae_cost,通过最小化IAE找到最优PID参数,fminsearch无需工具箱,适合新手;
  3. 最后绘制误差曲线是关键验证步骤:最优参数下的误差曲线应快速收敛到0,且无明显振荡,直观体现控制效果。

四、运行结果



相关推荐
aini_lovee1 天前
MATLAB基于小波技术的图像融合实现
开发语言·人工智能·matlab
3GPP仿真实验室1 天前
【Matlab源码】6G候选波形:OFDM-IM 增强仿真平台 DM、CI
开发语言·matlab·ci/cd
rit84324991 天前
MATLAB中Teager能量算子提取与解调信号的实现
开发语言·matlab
我找到地球的支点啦1 天前
通信扩展——扩频技术(超级详细,附带Matlab代码)
开发语言·matlab
Dev7z2 天前
基于 MATLAB 的铣削切削力建模与仿真
开发语言·matlab
fengfuyao9852 天前
基于MATLAB的表面织构油润滑轴承故障频率提取(改进VMD算法)
人工智能·算法·matlab
机器学习之心2 天前
基于随机森林模型的轴承剩余寿命预测MATLAB实现!
算法·随机森林·matlab
rit84324992 天前
基于MATLAB的环境障碍模型构建与蚁群算法路径规划实现
开发语言·算法·matlab
hoiii1872 天前
MATLAB SGM(半全局匹配)算法实现
前端·算法·matlab
yong99902 天前
MATLAB面波频散曲线反演程序
开发语言·算法·matlab