热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

2.10PID控制算法(二)

关于PID各种整理例程基于stm32,位置式,增量式等1、增量式1.1增量式方式1structt_pid2{floatSetSpeed2;floatActua

关于PID各种整理例程基于stm32,位置式,增量式等


1、增量式


1.1 增量式 方式1

struct t_pid2
{float SetSpeed2;float ActualSpeed2;float err2;float err_next2;float err_last2;float Kp2,Ki2,Kd2;
}pid2;
void PID2_init()
{pid2.SetSpeed2=0.0;pid2.ActualSpeed2=0.0;pid2.err2=0.0;//当前值pid2.err_next2=0.0;//上一次值pid2.err_last2=0.0;//上上次值pid2.Kp2=0.2;pid2.Ki2=0.015;pid2.Kd2=0.2;
}
float PID2_realize(float speed)
{float incrementSpeed=0;pid2.SetSpeed2=speed;pid2.err2=pid2.SetSpeed2-pid2.ActualSpeed2;incrementSpeed=pid2.Kp2*(pid2.err2-pid2.err_next2)+pid2.Ki2*pid2.err2+pid2.Kd2*(pid2.err2-2*pid2.err_next2+pid2.err_last2);pid2.ActualSpeed2+=incrementSpeed;pid2.err_last2=pid2.err_next2;pid2.err_next2=pid2.err2;return pid2.ActualSpeed2;
}

1.1增量式 方式1 积分饱和

所谓的积分饱和现象是指如果系统存在一个方向的偏差,PID 控制器的输出由于积分作用的不断累加而加大,从而导致执行机构达到极限位置,若控制器输出 U(k)继续增大,执行器开度不可能再增大,此时计算机输出控制量超出了正常运行范围而进入饱和区。一旦系统出现反向偏差,u(k)逐渐从饱和区退出。进入饱和区越深则退出饱和区时间越长。在这段时间里,执行机构仍然停留在极限位置而不随偏差反向而立即做出相应的改变,这时系统就像失控一样,造成控制性能恶化,这种现象称为积分饱和现象或积分失控现象。

防止积分饱和的方法之一就是抗积分饱和法,该方法的思路是在计算 u(k)时,首先判断上一时刻的控制量 u(k-1)是否已经超出了极限范围: 如果u(k-1)>umax,则只累加负偏差; 如果 u(k-1)

在这里插入图片描述
如上图,很明显有三个过冲:
过程①:因为这个过程存在较大幅度变化的误差,因此积分器累积了较大的值,从图中可以看到,积分器的面积比较大(阴影部分)ek为正;

过程②:此时积分已经饱和,产生了较大的过冲,并且在较长的一段时间内,一直处于过冲的状态,ek为负;

过程③:积分脱离饱和状态,产生了积极的调节作用,消除静差,系统输出达到设定值 ek为正;

处理过程:
在这里插入图片描述

/*定义结构体和公用体*/
typedef struct
{float setpoint; //设定值float proportiongain; //比例系数float integralgain; //积分系数float derivativegain; //微分系数float lasterror; //前一拍偏差float preerror; //前两拍偏差float deadband; //死区float result; //输出值float maximum; //最大值float minimum; //最小值
}PID;void PIDRegulation(PID *vPID, float processValue)
{float thisError;float increment;float pError,dError,iError;thisError&#61;vPID->setpoint-processValue; //本次误差pError&#61;thisError-vPID->lasterror; //本次偏差与上次偏差之差iError&#61;0;dError&#61;thisError-2*(vPID->lasterror)&#43;vPID->preerror;if(vPID->result>vPID->maximum){if(thisError<&#61;0){iError&#61;thisError;}}elseif(vPID->result<vPID->minimum){if(thisError>&#61;0){iError&#61;thisError;}}else{iError&#61;thisError;}increment&#61;vPID->proportiongain*pError&#43;vPID->integralgain*iError&#43;vPID->derivativegain*dError; //增量计算vPID->preerror&#61;vPID->lasterror; //存放偏差用于下次运算vPID->lasterror&#61;thisError;vPID->result&#43;&#61;increment;
}

1.2 增量式 方式2

#define DEFAULT_SPEED -5 // mm/s 默认目标值
#define DEFAULT_PROPORTION 0.11f // Kp系数
#define DEFAULT_INTEGRAL 0.12f // Ki系数
#define DEFAULT_DERIVATIVE 0.03f // Kd系数
/*** 函数功能: PID结构体初始化* 输入参数: 无* 返 回 值: 无* 说 明: 初始化PID参数*/
void Init_PIDStruct()
{vPID.SetPoint &#61; DEFAULT_SPEED; // 目标值 单位:mm/svPID.Proportion &#61; DEFAULT_PROPORTION; // Kp系数vPID.Integral &#61; DEFAULT_INTEGRAL; // Ki系数vPID.Derivative &#61; DEFAULT_DERIVATIVE; // Kd系数 vPID.LastError &#61; 0;vPID.PrevError &#61; 0;vPID.SumError &#61; 0;
}/*** 函数功能&#xff1a;增量式PID速度环计算* 输入参数&#xff1a;NextPoint 由编码器得到的速度值 * TargetVal 目标值* 返 回 值&#xff1a;经过PID运算得到的增量值* 说 明&#xff1a;增量式 PID 速度环控制设计,计算得到的结果仍然是速度值*/
float IncPIDCalc(__IO float NextPoint,__IO float TargetVal) //临时变量,期望值
{__IO float iError &#61; 0,iIncpid &#61; 0; //当前误差iError &#61; TargetVal - NextPoint; // 增量计算
// if((iError<0.5f)&&(iError>-0.5f))
// iError &#61; 0; // |e| <0.5,不做调整iIncpid&#61;(vPID.Proportion * iError) // E[k]项-(vPID.Integral * vPID.LastError) // E[k-1]项&#43;(vPID.Derivative * vPID.PrevError); // E[k-2]项vPID.PrevError&#61;vPID.LastError; // 存储误差&#xff0c;用于下次计算vPID.LastError &#61; iError;return(iIncpid); // 返回增量值
}

2、位置式


2.1 位置式 方式1

struct t_pid
{float SetSpeed;float ActualSpeed;float err;float err_last;float Kp,Ki,Kd;float voltage;float integral;
}pid;
void PID_init()
{pid.SetSpeed&#61;0.0;pid.ActualSpeed&#61;0.0;pid.err&#61;0.0;pid.err_last&#61;0.0;pid.voltage&#61;0.0;pid.integral&#61;0.0;pid.Kp&#61;0.2;pid.Ki&#61;0.015;pid.Kd&#61;0.2;
}
float PID_realize(float speed)
{pid.SetSpeed&#61;speed;pid.err&#61;pid.SetSpeed-pid.ActualSpeed;pid.integral&#43;&#61;pid.err;pid.voltage&#61;pid.Kp*pid.err&#43;pid.Ki*pid.integral&#43;pid.Kd*(pid.err-pid.err_last);pid.err_last&#61;pid.err;pid.ActualSpeed&#61;pid.voltage*1.0;return pid.ActualSpeed;
}

2.2 位置式 方式2–积分分离

积分分离的概念&#xff0c;其基本思路是 当被控量与设定值偏差较大时&#xff0c;取消积分作用; 当被控量接近给定值时&#xff0c;引入积分控制&#xff0c;以消除静差&#xff0c;提高精度。

struct t_pid3
{float SetSpeed3;float ActualSpeed3;float err3;float err_last3;float Kp3,Ki3,Kd3;float voltage3;float integral3;
}pid3;
void PID3_init()
{pid3.SetSpeed3&#61;0.0;pid3.ActualSpeed3&#61;0.0;pid3.err3&#61;0.0;pid3.err_last3&#61;0.0;pid3.voltage3&#61;0.0;pid3.integral3&#61;0.0;pid3.Kp3&#61;0.2;pid3.Ki3&#61;0.04;pid3.Kd3&#61;0.2;
}
float PID3_realize(float speed)
{int index&#61;0;pid3.SetSpeed3&#61;speed;pid3.err3&#61;pid3.SetSpeed3-pid3.ActualSpeed3;pid3.integral3&#43;&#61;pid3.err3;if(abs((int)pid3.err3)>200)//积分分离{index&#61;0;}else{index&#61;1;pid3.integral3&#43;&#61;pid3.err3;}pid3.voltage3&#61;pid3.Kp3*pid3.err3&#43;index*pid3.Ki3*pid3.integral3&#43;pid3.Kd3*(pid3.err3-pid3.err_last3);pid3.err_last3&#61;pid3.err3;pid3.ActualSpeed3&#61;pid3.voltage3*1.0;return pid3.ActualSpeed3;
}

2.3 位置式 方式3–积分饱和

struct t_pid4
{float SetSpeed4; float ActualSpeed4; float err4; float err_last4;float Kp4,Ki4,Kd4;float voltage4; float integral4; float umax4;float umin4;
}pid4;
void PID4_init()
{pid4.SetSpeed4&#61;0.0;pid4.ActualSpeed4&#61;0.0;pid4.err4&#61;0.0;pid4.err_last4&#61;0.0;pid4.voltage4&#61;0.0;pid4.integral4&#61;0.0;pid4.Kp4&#61;0.2;pid4.Ki4&#61;0.1; pid4.Kd4&#61;0.2;pid4.umax4&#61;400;pid4.umin4&#61;-200;
}
float PID4_realize(float speed)
{int index;pid4.SetSpeed4&#61;speed;pid4.err4&#61;pid4.SetSpeed4-pid4.ActualSpeed4;if(pid4.ActualSpeed4>pid4.umax4) //示抗积分饱和{if(abs(pid4.err4)>200) //积分分离{index&#61;0;}else{index&#61;1;if(pid4.err4<0){pid4.integral4&#43;&#61;pid4.err4;}}}else if(pid4.ActualSpeed4<pid4.umin4){if(abs(pid4.err4)>200)//积分分离{index&#61;0;}else{index&#61;1;if(pid4.err4>0){pid4.integral4&#43;&#61;pid4.err4;}}}else{if(abs(pid4.err4)>200){index&#61;0;}else{index&#61;1;pid4.integral4&#43;&#61;pid4.err4;}}pid4.voltage4&#61;pid4.Kp4*pid4.err4&#43;index*pid4.Ki4*pid4.integral4&#43;pid4.Kd4*(pid4.err4-pid4.err_last4);
// pid4.voltage4&#61;pid4.Kp4*pid4.err4&#43;index*pid4.Ki4*pid4.integral4/2&#43;pid4.Kd4*(pid4.err4-pid4.err_last4);pid4.err_last4&#61;pid4.err4;pid4.ActualSpeed4&#61;pid4.voltage4*1.0;return pid4.ActualSpeed4;
}

2.4 位置式 方式4

struct t_pid5
{float SetSpeed5;float ActualSpeed5;float err5;float err_last5;float Kp5,Ki5,Kd5;float voltage5;float integral5;
}pid5;
void PID5_init()
{pid5.SetSpeed5&#61;0.0;pid5.ActualSpeed5&#61;0.0;pid5.err5&#61;0.0;pid5.err_last5&#61;0.0;pid5.voltage5&#61;0.0;pid5.integral5&#61;0.0;pid5.Kp5&#61;0.4;pid5.Ki5&#61;0.2;pid5.Kd5&#61;0.2;
}
float PID5_realize(float speed)
{float index;pid5.SetSpeed5&#61;speed;pid5.err5&#61;pid5.SetSpeed5-pid5.ActualSpeed5;if(abs(pid5.err5)>200){index&#61;0.0;}else if(abs(pid5.err5)<180){index&#61;1.0;pid5.integral5&#43;&#61;pid5.err5;}else{index&#61;(200-abs(pid5.err5))/20;pid5.integral5&#43;&#61;pid5.err5;}pid5.voltage5&#61;pid5.Kp5*pid5.err5&#43;index*pid5.Ki5*pid5.integral5&#43;pid5.Kd5*(pid5.err5-pid5.err_last5);pid5.err_last5&#61;pid5.err5;pid5.ActualSpeed5&#61;pid5.voltage5*1.0;return pid5.ActualSpeed5;
}

总结&#xff1a;从上面公式可以发现&#xff0c;对照PID控制算法&#xff08;一&#xff09;&#xff0c;其实就分位置式与增量式至于实现过冲&#xff0c;其实是一样的&#xff0c;只不过合并同类项不同而已。


推荐阅读
  • 深入解析Java枚举及其高级特性
    本文详细介绍了Java枚举的概念、语法、使用规则和应用场景,并探讨了其在实际编程中的高级应用。所有相关内容已收录于GitHub仓库[JavaLearningmanual](https://github.com/Ziphtracks/JavaLearningmanual),欢迎Star并持续关注。 ... [详细]
  • 采用IKE方式建立IPsec安全隧道
    一、【组网和实验环境】按如上的接口ip先作配置,再作ipsec的相关配置,配置文本见文章最后本文实验采用的交换机是H3C模拟器,下载地址如 ... [详细]
  • 深入解析SpringMVC核心组件:DispatcherServlet的工作原理
    本文详细探讨了SpringMVC的核心组件——DispatcherServlet的运作机制,旨在帮助有一定Java和Spring基础的开发人员理解HTTP请求是如何被映射到Controller并执行的。文章将解答以下问题:1. HTTP请求如何映射到Controller;2. Controller是如何被执行的。 ... [详细]
  • 本文介绍了如何在 C# 和 XNA 框架中实现一个自定义的 3x3 矩阵类(MMatrix33),旨在深入理解矩阵运算及其应用场景。该类参考了 AS3 Starling 和其他相关资源,以确保算法的准确性和高效性。 ... [详细]
  • 由二叉树到贪心算法
    二叉树很重要树是数据结构中的重中之重,尤其以各类二叉树为学习的难点。单就面试而言,在 ... [详细]
  • 丽江客栈选择问题
    本文介绍了一道经典的算法题,题目涉及在丽江河边的n家特色客栈中选择住宿方案。两位游客希望住在色调相同的两家客栈,并在晚上选择一家最低消费不超过p元的咖啡店小聚。我们将详细探讨如何计算满足条件的住宿方案总数。 ... [详细]
  • 本教程详细介绍了如何使用 TensorFlow 2.0 构建和训练多层感知机(MLP)网络,涵盖回归和分类任务。通过具体示例和代码实现,帮助初学者快速掌握 TensorFlow 的核心概念和操作。 ... [详细]
  • 本题探讨了在大数据结构背景下,如何通过整体二分和CDQ分治等高级算法优化处理复杂的时间序列问题。题目设定包括节点数量、查询次数和权重限制,并详细分析了解决方案中的关键步骤。 ... [详细]
  • 目录一、salt-job管理#job存放数据目录#缓存时间设置#Others二、returns模块配置job数据入库#配置returns返回值信息#mysql安全设置#创建模块相关 ... [详细]
  • 本文介绍如何在Spring Boot项目中集成Redis,并通过具体案例展示其配置和使用方法。包括添加依赖、配置连接信息、自定义序列化方式以及实现仓储接口。 ... [详细]
  • 本文介绍如何利用栈数据结构在C++中判断字符串中的括号是否匹配。通过顺序栈和链栈两种方式实现,并详细解释了算法的核心思想和具体实现步骤。 ... [详细]
  • 深入解析Spring启动过程
    本文详细介绍了Spring框架的启动流程,帮助开发者理解其内部机制。通过具体示例和代码片段,解释了Bean定义、工厂类、读取器以及条件评估等关键概念,使读者能够更全面地掌握Spring的初始化过程。 ... [详细]
  • yikesnews第11期:微软Office两个0day和一个提权0day
    点击阅读原文可点击链接根据法国大选被黑客干扰,发送了带漏洞的文档Trumps_Attack_on_Syria_English.docx而此漏洞与ESET&FireEy ... [详细]
  • This post discusses an issue encountered while using the @name annotation in documentation generation, specifically regarding nested class processing and unexpected output. ... [详细]
  • 本题要求在一组数中反复取出两个数相加,并将结果放回数组中,最终求出最小的总加法代价。这是一个经典的哈夫曼编码问题,利用贪心算法可以有效地解决。 ... [详细]
author-avatar
蒋小宁蒋小羊
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有