首页/文章/ 详情

2-54 误差和误差变化一变,PID 三个参数能不能跟着在线调整?

2小时前浏览1

模糊推理 + 自适应 PID 阶跃控制仿真程序

一句话介绍: 这套程序针对一个三阶被控对象,在 1 ms 采样周期下用误差 e 和误差差分 ec 驱动 49 条 Mamdani 模糊规则,在线给出 Kp、Ki、Kd 修正量,再完成 0.5 s 单位阶跃闭环仿真,并在 0.3 s 对控制器输出叠加扰动,观察系统响应以及三个 PID 参数的自适应变化。

先看它解决什么问题

固定参数 PID 的问题并不在于公式复杂,而在于 同一组Kp、Ki、Kd要同时兼顾响应速度、超调、稳态误差和扰动恢复。当误差很大、误差正在快速变化、系统已经接近目标值时,三个参数理想的作用侧重点并不完全一样。

当前程序采用的思路是:不把 PID 参数从头到尾固定,而是根据当前误差状态,通过模糊规则实时给出修正量。

完整控制链可以概括为:

单位阶跃 → 误差e/ 误差差分ec→ 49 条模糊规则 →Kp/Ki/Kd修正 → 离散 PID → 三阶被控对象 → 新误差 → 下一采样周期

这里最关键的是:模糊控制器本身不直接替代 PID,而是作为 PID 参数的在线整定器。

1. 当前工程里真正有哪些文件?

工程主体很小,核心文件只有 4 个:

文件

当前作用

fuzzyPID.m

主入口;建立模糊系统、设置规则、离散化对象、完成 500 步闭环仿真并输出结果

fuzzpid.fis

主脚本实际写入并重新读取的 Mamdani 模糊推理系统

fuzzyPID.fis

与 fuzzpid.fis 的隶属度函数和 49 条规则一致,主要差别是 FIS 名称字段为 fuzzyPID

模糊自适应PID控制器的设计.doc

配套原理、规则表和仿真说明资料

实际运行主线以 fuzzyPID.m 为准。脚本会先在内存中重新建立 FIS,再执行 writefis(a,'fuzzpid'),随后用 readfis('fuzzpid') 读回,因此主流程真正使用的是 fuzzpid.fis。

2. 当前程序控制的是什么对象?

源码中的连续被控对象为:

G(s) = 5.235×10⁵ / (s³ + 87.35s² + 1.047×10⁴s)

采样周期固定为:

ts = 0.001 s,也就是 1 ms。

程序使用 c2d(sys,ts,'tustin') 通过 Tustin 方法把连续对象离散化,再用离散传递函数系数逐点递推输出。

仿真共执行 500 个采样点,对应约 0.5 s;参考输入始终为单位阶跃 rin=1。

另外,源码在第 300 个采样点,也就是 0.300 s,直接在控制器输出 u 上叠加 +1.0,用于观察扰动后的恢复过程。这个扰动是加在控制器输出通道上的,不是另外建立的负载扰动模型。

3. 为什么这里不把 PID 参数直接固定?

普通 PID 可以写成三个作用的组合:比例看当前误差,积分看累计误差,微分看误差变化。

当前程序的基本控制量为:

u(k) = Kp(k)·x₁ + Kd(k)·x₂ + Ki(k)·x₃

其中源码实际定义:

x₁:当前保存的误差;

x₂:相邻采样点误差之差;

x₃:误差逐步累加值。

也就是说,PID 的结构没有改变,变化的是三个系数本身。

程序设置基础值:

Kp₀ = 0.40,Ki₀ = 0,Kd₀ = 1.0

模糊推理每个采样周期给出三个修正量,再得到:

Kp(k) = 0.40 + ΔKp(k)

Ki(k) = 0 + ΔKi(k)

Kd(k) = 1.0 + ΔKd(k)

所以它的本质不是“模糊控制和 PID 二选一”,而是:

PID 负责产生控制量,模糊规则负责根据误差状态改变 PID 参数。

4. 模糊控制器到底看哪两个量?

当前 FIS 有两个输入:e:误差;ec:误差变化量。

两者论域都设为:[-3, 3]

每个输入都划分成 7 个语言状态:

NB → NM → NS → Z → PS → PM → PB

分别对应从“负大”到“正大”的七级状态。

两端 NB、PB 使用 Z 型和 S 型隶属度函数,中间五个状态使用三角隶属度函数。这样一个连续误差值通常会同时对相邻的几个模糊集 合产生不同程度的隶属,而不是被硬切成某一个单独类别。

需要注意一个很重要的源码事实:ec在程序里实际计算为error(k)-error(k-1),没有再除以ts。 因此它在当前实现中更准确地说是“每个采样步的误差差分”,并不是带物理单位的连续时间误差导数。

5. 两个输入怎样决定三个 PID 修正量?

两个输入各有 7 个模糊状态,因此组合后正好形成:

7 × 7 = 49 条规则。

每条规则同时给出三个输出的语言状态,也就是一次性决定 Kp、Ki、Kd 应该往哪个方向修正。

例如当前规则中:

当 e=NB、ec=NB 时,输出为 Kp=PB、Ki=NB、Kd=PS;

当 e=Z、ec=Z 时,输出为 Kp=Z、Ki=Z、Kd=NS;

当 e=PB、ec=PB 时,输出为 Kp=NB、Ki=PB、Kd=PB。

规则全部采用权重 1、AND 关系;FIS 配置使用:

AND=min → implication=min → aggregation=max → centroid 重心法解模糊。

这意味着程序不是简单查一条离散表,而是先计算多条规则的激活程度,再把它们聚合成连续的三个修正量。

6. 三个修正量的范围为什么不一样?

源码给三个模糊输出设置了不同论域:

输出修正量

FIS 范围

加到的基础值

ΔKp

[-0.3, 0.3]

0.40

ΔKi

[-0.06, 0.06]

0

ΔKd

[-3, 3]

1.0

这说明当前设计从一开始就没有让三个参数使用同一调节尺度。

简单理解:比例、积分、微分在当前离散控制器中的数值敏感度不同,因此模糊输出范围也分别设计。最终实际参数仍由“基础值 + 模糊修正量”得到。

源码配套说明也强调,规则设计的目标不是让三个参数同步增减,而是根据误差大小和变化趋势,在不同阶段分别兼顾响应速度、稳态误差和动态抑制。

7. 一个采样周期里,程序实际按什么顺序工作?

当前循环的顺序非常明确:

读取上一周期e/ec→ 模糊推理 → 更新Kp/Ki/Kd→ 计算 PID 输出u→ 必要时叠加扰动并限幅 → 更新离散对象输出 → 计算新误差 → 保存给下一周期

控制器输出还带有:-10 ≤ u ≤ 10的硬限幅。

这里还有一个容易被注释误导的小细节:源码第 173、174 行把 x(2) 注释成“微分I”、把 x(3) 注释成“积分D”,文字标签写反了;但实际计算关系没有反,x(2) 确实乘的是 Kd,x(3) 确实乘的是 Ki。

另外,当前离散 PID 没有显式对差分项除以 ts,也没有对积分累加项乘以 ts。因此当前 Ki、Kd 的数值实际上已经和 1 ms 的离散实现方式绑定;如果大幅修改采样周期,不能只改 ts 而完全照搬原参数。

8. 当前默认仿真下,系统实际表现怎样?

工程没有保存单独的数值结果文件,配套文档主要给出响应曲线。为避免把图上的视觉判断写成固定结果,可以按当前源码的 Tustin 离散对象、FIS 中的 min/max/centroid 配置和 49 条规则做等价复算。

按当前默认条件复算,可得到下面这组量级结果:

指标

等价复算结果

初始阶跃峰值

约 1.00032

初始阶跃超调

约 0.03%

0.299 s 时输出

约 0.99987

扰动后最大输出

约 1.05110

扰动后峰值时刻

约 0.327 s

重新进入 ±2% 误差带

约 0.347 s

0.500 s 时输出

约 0.99976

也就是说,在当前这一个三阶对象和当前规则下,单位阶跃本身的超调很小;0.300 s 加入 +1.0 控制输出扰动后,输出短时上冲到约 1.051,随后又回到目标值附近。

这组数值属于按当前源码关系做的等价复算,不是对所有 MATLAB 版本和所有 FIS API 实现都承诺完全逐位一致的固定输出。

9.Kp、Ki、Kd 真的在仿真过程中变化了吗?

会,而且这正是这套程序最值得观察的结果之一。

按同一套默认条件等价复算,500 个采样点内三个参数大致变化在:

Kp:约 0.3310 ~ 0.4111;

Ki:约 -0.00025 ~ 0.0160;

Kd:约 0.2890 ~ 1.0000。

这说明模糊系统并不是只在初始化时给一次参数,而是每个采样周期都会根据 e 和 ec 重新推理。

当系统离目标较远、误差快速变化、接近稳态或者受到扰动时,激活的规则组合不同,三个修正量也随之改变。程序最后分别绘制 Kp、Ki、Kd 的时间序列,就是为了观察这种在线整定过程。

10. 为什么不能把它直接理解成“模糊 PID 一定优于固定 PID”?

因为当前工程只实现了这一套模糊自适应 PID 仿真,并没有在同一脚本里建立固定 PID 对照组,也没有给出 IAE、ISE、调节时间等统一评价指标的对比实验。

所以从当前程序可以确认的是:

它确实根据 e/ec 在线修改三个 PID 参数;

它确实完成了当前三阶对象的阶跃与扰动仿真;

当前默认规则下能看到参数自适应和扰动恢复过程。

但不能仅凭这套源码进一步宣称“精度一定更高”“鲁棒性一定更强”或“对所有对象都优于固定 PID”。如果要做这种结论,需要再加入同对象、同采样周期、同饱和约束下的固定 PID 对照和统一指标。

11. 这套程序更适合用在哪里?

模糊 PID 原理教学与课程实验

它把 隶属度函数、49 条规则、重心解模糊、PID 参数修正、闭环响应 全部放在一个脚本中,非常适合观察“模糊推理怎样参与 PID 整定”这条完整链路。

PID 参数自整定思路验证

如果想研究“误差大小和误差变化趋势能否用于在线调节 PID”,这套程序提供了一个结构清晰的基线,可以直接修改规则表、隶属度函数和基础 PID 参数做对照实验。

扰动恢复过程观察

当前脚本已经在 0.300 s 注入一次控制输出扰动,因此适合观察参数变化与输出恢复之间的对应关系,也方便继续改扰动幅值和时刻做敏感性实验。

新控制对象的离线仿真起点

可以把 sys=tf(...) 换成其他传递函数继续实验,但这不等于参数可以原样迁移。新的对象如果误差尺度、时间尺度或动态特性明显不同,需要重新检查 e/ec 论域、基础 PID 参数和 49 条模糊规则。

当前工程是 MATLAB 离线仿真脚本,不包含传感器采集、执行器接口、实时操作系统或硬件闭环,因此不应直接把它描述成已经完成的工业实时控制系统。

12. 哪些参数最值得修改?

当前程序里真正会明显改变控制行为的,主要是下面几组参数。

参数

当前值

为什么值得改

调整后的主要影响

kp0 / ki0 / kd0

0.40 / 0 / 1.0

决定模糊修正之前的 PID 基准

改变整体响应速度、稳态校正和动态抑制基线

e / ec 论域与隶属度函数

[-3,3]、各 7 个集 合

决定什么误差会被解释成 NB~PB

直接改变规则触发区域和参数修正灵敏度

rulelist

49 条规则

是自适应整定策略本身

改变不同误差状态下三个参数的增减方向

u 限幅

[-10,10]

限制控制器可用输出幅度

影响大误差或强扰动下的响应和饱和行为

ts

0.001 s

当前差分、累加和对象离散化都依赖采样周期

改变离散动态;修改后通常需要重新整定 Ki/Kd 和模糊尺度

如果只是更换被控对象,应把 sys=tf(...) 视为新的项目模型条件,而不是只改一个普通调参值。对象一变,原来的参数和规则是否仍合适需要重新验证。

13. 怎么运行这套程序?

运行主脚本:fuzzyPID,源码会自动完成:

建立 FIS → 加入隶属度函数 → 加入 49 条规则 → 保存并读取fuzzpid.fis→ 建立连续对象 → Tustin 离散化 → 500 步闭环仿真 → 显示规则、响应、参数变化和 FIS 结构

从函数调用看,工程至少依赖:

Fuzzy Logic Toolbox:newfis、addvar、addmf、addrule、evalfis、plotmf、plotfis、fuzzy 等;

Control System Toolbox:tf、c2d、tfdata。

当前源码采用的是传统 FIS 函数接口。如果所用 MATLAB 版本对这些旧式接口不再直接兼容,需要按该版本的 Fuzzy Logic Toolbox API 做迁移;这属于运行环境兼容问题,不应把缺失函数误判成控制算法本身的结果问题。

如果只是按原工程做实验,优先保持 ts=0.001 s 不变,然后再分别修改基础 PID 参数、隶属度函数或 rulelist,这样更容易判断每一项修改究竟改变了什么。

14. 一句话看懂这个项目

这是一个模糊自适应 PID 控制仿真程序:它以三阶传递函数对象为测试对象,在 1 ms 采样周期下用误差e和误差差分ec激活 49 条 Mamdani 模糊规则,分别给Kp、Ki、Kd生成在线修正量,再通过离散 PID 完成 500 点单位阶跃控制,并在 0.300 s 对控制器输出加入+1.0扰动;按当前源码等价复算,初始阶跃超调约 0.03%,扰动后输出峰值约 1.051,随后重新回到目标附近,因此它最适合用于模糊 PID 原理教学、参数整定规则实验和新控制对象的离线方案验证,而不是直接作为已经完成硬件闭环的工业实时控制系统。



来源:MATLAB学习与应用
SystemMATLAB控制
著作权归作者所有,欢迎分享,未经许可,不得转载
首次发布时间:2026-10-28
最近编辑:2小时前
explicit-z
硕士 工种号:MATLAB学习与应用
获赞 212粉丝 79文章 340课程 5
点赞
收藏
作者推荐
未登录
还没有评论
课程
培训
服务
行家
VIP会员 学习计划 福利任务
下载APP
联系我们
帮助与反馈