热门标签 | 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;只不过合并同类项不同而已。


推荐阅读
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 本文由编程笔记#小编为大家整理,主要介绍了logistic回归(线性和非线性)相关的知识,包括线性logistic回归的代码和数据集的分布情况。希望对你有一定的参考价值。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 3.223.28周学习总结中的贪心作业收获及困惑
    本文是对3.223.28周学习总结中的贪心作业进行总结,作者在解题过程中参考了他人的代码,但前提是要先理解题目并有解题思路。作者分享了自己在贪心作业中的收获,同时提到了一道让他困惑的题目,即input details部分引发的疑惑。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 本文讨论了如何使用IF函数从基于有限输入列表的有限输出列表中获取输出,并提出了是否有更快/更有效的执行代码的方法。作者希望了解是否有办法缩短代码,并从自我开发的角度来看是否有更好的方法。提供的代码可以按原样工作,但作者想知道是否有更好的方法来执行这样的任务。 ... [详细]
  • 本文介绍了如何使用Express App提供静态文件,同时提到了一些不需要使用的文件,如package.json和/.ssh/known_hosts,并解释了为什么app.get('*')无法捕获所有请求以及为什么app.use(express.static(__dirname))可能会提供不需要的文件。 ... [详细]
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社区 版权所有