当前位置: 首页 > news >正文

西门子PLC结构化编程_带前馈控制功能的位置式PID控制器

文章目录

  • 前言
  • 一、功能概述
  • 二、公式推导
    • 1. 位置式PID公式推导
    • 2. 前馈控制PID公式推导
  • 三、程序编写
    • 1. 新建自定义数据类型“1_PID_Controller”
    • 2. 新建FB块“FB36_PID_Controller_Advanced”
    • 3. 编写程序
  • 总结


前言

在之前的文章中,我们讨论了增量式PID控制模型的实现方法,见文章《西门子PLC结构化编程_增量式PID功能块》。
在该文章中,我们编写的增量式PID控制程序仅仅实现了基础功能,在工业现场实际应用中,还需要添加更多高级功能。故本篇文章将给出一个更加完善的PID控制功能块,增加了手自动无扰切换、前馈控制等功能。


一、功能概述

优化后的PID控制功能块应具备以下功能:

  1. 完整的PID实现:包含比例、积分、微分三项计算;
  2. 防积分饱和:可配置的积分上下限,防止积分项过大;
  3. 死区控制:防止控制元件频繁抖动;
  4. 基于过程值的微分:避免设定值变化导致误差过大,造成输出冲击;
  5. 手动/自动无扰切换:在手动模式下保持积分项,切换时无冲击,同时,将当前PID输出值赋给手动设定值;
  6. 输出限幅:可配置的输出上下限,保护执行机构;
  7. 状态监控:提供各项输出用于监控和调试;
  8. 手动模式:PID控制器取消激活,PID输出值等于手动设定值;
  9. 半自动模式:PID控制器激活,设定值SP由操作员手动设置;
  10. 自动模式:PID控制器激活,设定值SP由其它连锁条件计算得出
  11. Kp:增大使响应加快,但过大会导致振荡;
  12. Ti:减小使积分作用增强,消除稳态误差;
  13. Td:增大改善稳定性,抑制超调;
  14. 可选择控制器正作用/反作用;
  15. 如果过程是正作用(控制量增加→过程值增加),则控制器应设置为反作用;
  16. 如果过程是反作用(控制量增加→过程值减少),则控制器应设置为正作用;
  17. 具有前馈控制功能。

二、公式推导

1. 位置式PID公式推导

在连续时间域中,理想的PID控制器公式为:
在这里插入图片描述
其中:
u(t)u(t)u(t):控制器输出
e(t)e(t)e(t):误差信号,e(t)=r(t)−y(t)e(t) = r(t) - y(t)e(t)=r(t)y(t)(设定值 - 过程值)
KpK_pKp:比例增益
TiT_iTi:积分时间
TdT_dTd:微分时间
为了在数字控制器中实现,我们需要将连续时间公式离散化。采用后向差分法进行离散化。
积分项离散化后:
在这里插入图片描述
微分项离散化后:
在这里插入图片描述
代入到PID计算公式,可得
在这里插入图片描述
令:

Ki=KpTTiK_i = K_p \frac{T}{T_i}Ki=KpTiT(积分系数)

Kd=KpTdTK_d = K_p \frac{T_d}{T}Kd=KpTTd(微分系数)

则位置式PID公式可简写为:
在这里插入图片描述

2. 前馈控制PID公式推导

常见PID控制器的核心是 “反馈”,它检测到误差 e(t)e(t)e(t)(即目标与现实的偏差)已经发生,然后产生一个控制作用去纠正这个已经存在的偏差,所以反馈控制具有滞后性,它必须等到误差出现后才开始动作。而前馈控制思想是,在可测量的干扰影响到被控变量之前,就提前产生一个控制作用来抵消这个干扰的影响。
最终的控制器输出 u(t)u(t)u(t) 是反馈(PID)输出和前馈输出的叠加:
在这里插入图片描述
展开后即为带前馈的PID最终公式:
在这里插入图片描述
离散化后的形式:
在这里插入图片描述
其中, KffK_{ff}Kff代表前馈增益。
将前馈控制器的输出与PID控制器的输出相加,形成最终的控制作用。前馈负责“粗调”(快速应对主要干扰),PID负责“细调”(精确消除剩余误差和应对其他未知干扰)。

三、程序编写

1. 新建自定义数据类型“1_PID_Controller”

在这里插入图片描述
在这里插入图片描述
图1

2. 新建FB块“FB36_PID_Controller_Advanced”

在引脚中添加如下变量:
在这里插入图片描述
图2

3. 编写程序

在这里插入图片描述

REGION 手动、半自动、自动无扰切换IF #PID.HMI.HMIManual THEN#PID.HMI.ManualSetpoint := #PID.HMI.TotalOutput;END_IF;IF #PID.HMI.HMIAuto THEN#PID.HMI.AutoSetpoint := #PID.InPut.SetpointValue;END_IF;IF #PID.HMI.HMISemiAuto THEN#PID.HMI.SemiAutoSetpoint := #PID.InPut.SetpointValue;END_IF;IF #PID.HMI.Manual_DO THEN#PID.Temp.OutputTemp := #PID.HMI.ManualSetpoint;#PID.HMI.TotalOutput := #PID.HMI.ManualSetpoint;#PID.Static.IntegralTerm := #PID.Static.IntegralTerm; // 在手动模式下保持积分项,防止切换回自动时产生冲击#PID.OutPut.ControllerActive := 0;ELSIF#PID.HMI.SemiAuto_DO THEN#PID.InPut.SetpointValue := #PID.HMI.SemiAutoSetpoint;#PID.OutPut.ControllerActive := 1;ELSIF#PID.HMI.Auto_DO THEN#PID.InPut.SetpointValue := #PID.HMI.AutoSetpoint;#PID.OutPut.ControllerActive := 1;END_IF;END_REGIONREGION 初始化IF #PID.Static.FirstScan OR #PID.HMI.HMIReset THEN#PID.OutPut.Output := 0.0;#PID.OutPut.Error := 0.0;#PID.OutPut.Proportional := 0.0;#PID.OutPut.Integral := 0.0;#PID.OutPut.Derivative := 0.0;#PID.OutPut.FeedforwardOutput := 0.0;#PID.HMI.TotalOutput := 0.0;#PID.Static.LastError := 0.0;#PID.Static.IntegralTerm := 0.0;#PID.Static.LastProcessValue := #PID.HMI.ProcessValue;#PID.Static.FirstScan := FALSE;// 设置初始方向IF #PID.HMI.ControllerDirection = 0 THEN#PID.Static.DirectionSign := 1.0;  // 正作用ELSIF#PID.HMI.ControllerDirection = 1 THEN#PID.Static.DirectionSign := -1.0; // 反作用END_IF;IF #PID.HMI.HMIReset THENRETURN;  // 重置时立即返回,不执行后续计算END_IF;END_IF;// 时间处理#PID.Static.DeltaTime := #PID.InPut.ScanTime / 1000.0;END_REGIONREGION PID计算IF #PID.OutPut.ControllerActive THEN// 根据作用方向计算当前误差 e(t) = Direction * (SP - PV)IF ABS(#PID.InPut.SetpointValue - #PID.HMI.ProcessValue) <= #PID.InPut.DeadValue THEN#PID.Temp.ErrorTemp := 0; // 死区设置ELSE#PID.Temp.ErrorTemp := #PID.Static.DirectionSign * (#PID.InPut.SetpointValue - #PID.HMI.ProcessValue);END_IF;#PID.OutPut.Error := #PID.Temp.ErrorTemp;// 比例项计算 P = Kp × e(t)#PID.Temp.ProportionalTemp := #PID.HMI.Kp * #PID.Temp.ErrorTemp;#PID.OutPut.Proportional := #PID.Temp.ProportionalTemp;// 积分项计算(防积分饱和) I(k) = I(k-1) + (Kp × e(k) × Δt) / TiIF #PID.HMI.Ti > 0.0 AND #PID.Static.DeltaTime > 0.0 THEN#PID.Temp.IntegralTemp := #PID.Static.IntegralTerm + (#PID.HMI.Kp * #PID.Temp.ErrorTemp * #PID.Static.DeltaTime) / #PID.HMI.Ti;// 积分限幅IF #PID.Temp.IntegralTemp > #PID.InPut.IntegralMax THEN#PID.Temp.IntegralTemp := #PID.InPut.IntegralMax;ELSIF #PID.Temp.IntegralTemp < #PID.InPut.IntegralMin THEN#PID.Temp.IntegralTemp := #PID.InPut.IntegralMin;END_IF;#PID.Static.IntegralTerm := #PID.Temp.IntegralTemp;ELSE#PID.Temp.IntegralTemp := 0.0;END_IF;#PID.OutPut.Integral := #PID.Temp.IntegralTemp;// 微分项计算(基于过程值的变化率,避免设定值变化的冲击) D = -Kp × Td × (PV(k) - PV(k-1)) / Δt#PID.Temp.DerivativeTemp := 0.0;IF #PID.HMI.Td > 0.0 AND #PID.Static.DeltaTime > 0.0 THEN#PID.Temp.DerivativeTemp := - #PID.HMI.Kp * #PID.HMI.Td * (#PID.HMI.ProcessValue - #PID.Static.LastProcessValue) / #PID.Static.DeltaTime;END_IF;#PID.OutPut.Derivative := #PID.Temp.DerivativeTemp;// PID输出求和#PID.Temp.OutputTemp := #PID.Temp.ProportionalTemp + #PID.Temp.IntegralTemp + #PID.Temp.DerivativeTemp;// 前馈控制计算IF #PID.InPut.EnableFeedforward THEN// 前馈变化率限制(不使用外部前馈处理程序时使用),确保前馈输入的变化不会超过每秒±5单位的速率限制// #PID.Static.FeedforwardRateLimit := #PID.Static.FeedforwardRateLimit +// LIMIT(MN := -5.0, IN := #PID.InPut.FeedforwardInput - #PID.Static.LastFeedforwardInput, MX := 5.0);// #PID.Static.LastFeedforwardInput := #PID.InPut.FeedforwardInput;// 根据前馈类型计算前馈输出CASE #PID.InPut.FeedforwardType OF0: // 加法前馈,适用于扰动与控制量呈线性关系的系统// #PID.Temp.FeedforwardTemp := #PID.InPut.FeedforwardGain * #PID.Static.FeedforwardRateLimit; // 不使用外部前馈处理程序时使用#PID.Temp.FeedforwardTemp := #PID.InPut.FeedforwardGain * #PID.InPut.FeedforwardInput;1: // 乘法前馈,适用于扰动影响与控制量大小相关的系统// #PID.Temp.FeedforwardTemp := #PID.Temp.OutputTemp * #PID.InPut.FeedforwardGain * #PID.Static.FeedforwardRateLimit; // 不使用外部前馈处理程序时使用#PID.Temp.FeedforwardTemp := #PID.Temp.OutputTemp * #PID.InPut.FeedforwardGain * #PID.InPut.FeedforwardInput / 100.0;ELSE: // 默认加法前馈// #PID.Temp.FeedforwardTemp := #PID.InPut.FeedforwardGain * #PID.Static.FeedforwardRateLimit; // 不使用外部前馈处理程序时使用#PID.Temp.FeedforwardTemp := #PID.InPut.FeedforwardGain * #PID.InPut.FeedforwardInput;END_CASE;// 前馈输出限幅#PID.Temp.FeedforwardTemp := LIMIT(MN := -50.0, IN := #PID.Temp.FeedforwardTemp, MX := 50.0);#PID.OutPut.FeedforwardOutput := #PID.Temp.FeedforwardTemp;// 总输出 = PID输出 + 前馈输出#PID.Temp.OutputTemp := #PID.Temp.OutputTemp + #PID.Temp.FeedforwardTemp;ELSE#PID.OutPut.FeedforwardOutput := 0.0;END_IF;END_IF;// 输出限幅IF #PID.Temp.OutputTemp > #PID.InPut.OutputMax THEN#PID.Temp.OutputTemp := #PID.InPut.OutputMax;// 抗积分饱和: 当输出饱和时,停止积分作用IF #PID.InPut.EnableFeedforward AND (#PID.Temp.OutputTemp - #PID.OutPut.FeedforwardOutput) > #PID.InPut.OutputMax THEN#PID.Static.IntegralTerm := #PID.Static.IntegralTerm - (#PID.Temp.OutputTemp - #PID.OutPut.FeedforwardOutput - #PID.InPut.OutputMax);END_IF;ELSIF #PID.Temp.OutputTemp < #PID.InPut.OutputMin THEN#PID.Temp.OutputTemp := #PID.InPut.OutputMin;// 抗积分饱和: 当输出饱和时,停止积分作用IF #PID.InPut.EnableFeedforward AND (#PID.Temp.OutputTemp - #PID.OutPut.FeedforwardOutput) < #PID.InPut.OutputMin THEN#PID.Static.IntegralTerm := #PID.Static.IntegralTerm - (#PID.Temp.OutputTemp - #PID.OutPut.FeedforwardOutput - #PID.InPut.OutputMin);END_IF;END_IF;#PID.OutPut.Output := #PID.Temp.OutputTemp;#PID.HMI.TotalOutput := #PID.Temp.OutputTemp;// 保存当前值供下次使用#PID.Static.LastError := #PID.Temp.ErrorTemp;#PID.Static.LastProcessValue := #PID.HMI.ProcessValue;// 更新状态#PID.OutPut.DirectionStatus := #PID.HMI.ControllerDirection;END_REGIONREGION 辅助功能// 按钮自复位#PID.HMI.HMIManual := #PID.HMI.HMIManual AND NOT #PID.Temp.HMIManualReset;#PID.HMI.HMISemiAuto := #PID.HMI.HMISemiAuto AND NOT #PID.Temp.HMISemiAutoReset;#PID.HMI.HMIAuto := #PID.HMI.HMIAuto AND NOT #PID.Temp.HMIAutoReset;// #PID.HMI.HMIReset := #PID.HMI.HMIReset AND NOT #PID.Temp.HMIResetReset;// 自动生成复位信号#PID.Temp.HMIManualReset := #PID.HMI.HMIManual;#PID.Temp.HMISemiAutoReset := #PID.HMI.HMISemiAuto;#PID.Temp.HMIAutoReset := #PID.HMI.HMIAuto;// #PID.Temp.HMIResetReset := #PID.HMI.HMIReset;END_REGION

总结

本文给出了优化的PID控制器模型,增加了抗饱和积分、死区控制、前馈控制、手自动无扰切换、作用方向选择等功能。


文章转载自:

http://bDVyhxSv.qqhfc.cn
http://huwWwGiw.qqhfc.cn
http://OCujFRjZ.qqhfc.cn
http://Qhhs5v1V.qqhfc.cn
http://6HnE3ORP.qqhfc.cn
http://WPzs0GUc.qqhfc.cn
http://nS3vsXFB.qqhfc.cn
http://qYYUWx8z.qqhfc.cn
http://g09qyIy8.qqhfc.cn
http://CQ07beS0.qqhfc.cn
http://YLCaPq9i.qqhfc.cn
http://87b4564B.qqhfc.cn
http://79KXtvqV.qqhfc.cn
http://x5jgJ6ib.qqhfc.cn
http://4lkUO3SN.qqhfc.cn
http://lc5Or8ZB.qqhfc.cn
http://4EHsJMq4.qqhfc.cn
http://SFf1TIk6.qqhfc.cn
http://Dlrdv8nY.qqhfc.cn
http://zsawDKsw.qqhfc.cn
http://9jAsOZmT.qqhfc.cn
http://1apEIin3.qqhfc.cn
http://3hWIU9Pa.qqhfc.cn
http://7ps2fC6a.qqhfc.cn
http://AeY91Eg2.qqhfc.cn
http://qtnwUOF0.qqhfc.cn
http://O56jAPY2.qqhfc.cn
http://RVmpYEFv.qqhfc.cn
http://N5wTuPca.qqhfc.cn
http://t75yUWpK.qqhfc.cn
http://www.dtcms.com/a/377328.html

相关文章:

  • 【JVM】参数设置及依据
  • 老树发新芽:六西格玛培训为石油机械制造注入持久活力
  • pandas的使用(2)数据选取
  • 【数据结构与算法-Day 25】工程中的王者:深入解析红黑树 (Red-Black Tree)
  • 【leetcode】63. 不同路径 II
  • 低压电工作业操作证的考试难度如何?
  • 【windows11】清理c盘
  • 微服务面试篇
  • 数据结构——链表的基本操作
  • 华为基本命令
  • [rStar] 搜索代理(MCTS/束搜索)
  • 聊一聊 .NET 某跨境物流系统 内存暴涨分析
  • langchain+通义千问,实现简单地RAG应用
  • 【Spring】原理解析:Spring Boot 自动配置
  • 象形柱状图(Vue3)
  • RESTful API:@RequestParam与@PathVariable实战对比
  • 【ESP系列】ESP32S3
  • kafka集群部署与使用
  • Linux-Shell编程之sed和awk
  • 无人设备遥控器之状态反馈技术篇
  • 4.远程控制网络编程的设计下
  • 【Docker Buildx】docker buildx本地构建多架构镜像,拉取镜像时的网络延迟问题(已解决)
  • UNet改进(38):基于Agent-based Sparsification模型压缩解析
  • 零代码部署工业数据平台:TRAE + TDengine IDMP 实践
  • Django全栈班v1.01 Python简介与特点 20250910
  • 【MFC】对话框属性:Absolute Align(绝对对齐)
  • 【面试】Elasticsearch 实战面试问题
  • Java与Vue前后端Excel导入交互解决方案
  • 2023年IEEE TASE SCI2区,基于Dubins路径的多异构无人机动态灾情检测与验证集成分配,深度解析+性能实测
  • 无人机电流技术与安全要点