改进式PID控制以及C语言实现过程
2016-03-31 14:14
323 查看
改进式PID控制
如果是在低速模式下,标准的PID基本可以满足控制要求,但随着速度的提升,PID算法要进一步修改和完善才能达到控制要求。因此需要对PID算式进行适当的改进,从而提高控制质量。
积分项的改进
积分项的作用:消除稳态误差,提高控制系统的精度。
积分项存在的问题:偏差较大时,积分的滞后作用会影响系统的响应速度,引起较大的超调及加长过渡过程,尤其对时间常数较大,有时间滞后的被控对象,更加剧了振荡过程。
1. 积分分离法:
改进方案:当偏差大于某个规定的门限值时,取消积分作用,从而使积分不至于过大。只有当e(k)较小时,才引入积分作用,以消除静差。这样控制量不易进入饱和区;即使进入了饱和区,也能较快的退出,所以能使系统的输出特性得到改善。
2. 抗积分饱和法:
改进方案:当控制量进入饱和区后,只执行削弱积分项的累加,而不进行增大积分项的累加。即计算u(k)时,先判断u(k-1)是否超过限制范围,若已超过umax,则只累计负偏差;若小于umin,则只累计正偏差,这种方法也可以避免控制量长期停留在饱和区。
算法案例如下:
如果是在低速模式下,标准的PID基本可以满足控制要求,但随着速度的提升,PID算法要进一步修改和完善才能达到控制要求。因此需要对PID算式进行适当的改进,从而提高控制质量。
积分项的改进
积分项的作用:消除稳态误差,提高控制系统的精度。
积分项存在的问题:偏差较大时,积分的滞后作用会影响系统的响应速度,引起较大的超调及加长过渡过程,尤其对时间常数较大,有时间滞后的被控对象,更加剧了振荡过程。
1. 积分分离法:
改进方案:当偏差大于某个规定的门限值时,取消积分作用,从而使积分不至于过大。只有当e(k)较小时,才引入积分作用,以消除静差。这样控制量不易进入饱和区;即使进入了饱和区,也能较快的退出,所以能使系统的输出特性得到改善。
2. 抗积分饱和法:
改进方案:当控制量进入饱和区后,只执行削弱积分项的累加,而不进行增大积分项的累加。即计算u(k)时,先判断u(k-1)是否超过限制范围,若已超过umax,则只累计负偏差;若小于umin,则只累计正偏差,这种方法也可以避免控制量长期停留在饱和区。
算法案例如下:
/* 积分分离的pid控制算法c语言实现 系统所用时间是原来时间的一半 系统的快速性得到了提高 */ #include<stdio.h> #include<stdlib.h> struct _pid{ float SetSpeed; //定义设定值 //24V 1100-1900 float ActualSpeed; //定义实际值 float err; //定义偏差值 float err_last; //定义上一个偏差值 float Kp,Ki,Kd; //定义比例、积分、微分系数 float voltage; //定义电压值(控制执行器的变量) float integral; //定义积分值 }pid; //项目中获取到的参数 void PID_init(){ printf("PID_init begin \n"); pid.SetSpeed=0.0; pid.ActualSpeed=0.0; pid.err=0.0; pid.err_last=0.0; pid.voltage=0.0; pid.integral=0.0; pid.Kp=0.2; //自己设定 pid.Ki=0.04; //自己设定 pid.Kd=0.2; //自己设定 printf("PID_init end \n"); } float PID_realize(float speed){ pid.SetSpeed=speed; //设定值 pid.err=pid.SetSpeed-pid.ActualSpeed; //设定值-实际值 int index; if(abs(pid.err)>200) { index=0; }else{ index=1; pid.integral+=pid.err; } pid.voltage=pid.Kp*pid.err+index*pid.Ki*pid.integral+pid.Kd*(pid. err-pid.err_last); //算法具体实现过程 pid.err_last=pid.err; //上一个偏差值 pid.ActualSpeed=pid.voltage*1.0; //算出实际值 return pid.ActualSpeed; //返回 } int main(){ PID_init(); int count=0; while(count<1000) { float speed=PID_realize(200.0); printf("%f\n",speed); count++; } return 0; }
/* 抗击分饱和的pid控制算法 */ #include<stdio.h> #include<stdlib.h> struct _pid{ float SetSpeed; //定义设定值 float ActualSpeed; //定义实际值 float err; //定义偏差值 float err_last; //定义上一个偏差值 float Kp,Ki,Kd; //定义比例、积分、微分系数 float voltage; //定义电压值(控制执行器的变量) float integral; //定义积分值 float umax; float umin; }pid; void PID_init(){ printf("PID_init begin \n"); pid.SetSpeed=0.0; pid.ActualSpeed=0.0; pid.err=0.0; pid.err_last=0.0; pid.voltage=0.0; pid.integral=0.0; pid.Kp=0.2; pid.Ki=0.1; //注意,和上几次相比,这里加大了积分环节的值 pid.Kd=0.2; pid.umax=400; pid.umin=-200; printf("PID_init end \n"); } float PID_realize(float speed){ int index; pid.SetSpeed=speed; pid.err=pid.SetSpeed-pid.ActualSpeed; if(pid.ActualSpeed>pid.umax) //灰色底色表示抗积分饱和的实现 { if(abs(pid.err)>200) //蓝色标注为积分分离过程 { index=0; }else{ index=1; if(pid.err<0) { pid.integral+=pid.err; } } }else if(pid.ActualSpeed<pid.umin){ if(abs(pid.err)>200) //积分分离过程 { index=0; }else{ index=1; if(pid.err>0) { pid.integral+=pid.err; } } }else{ if(abs(pid.err)>200) //积分分离过程 { index=0; }else{ index=1; pid.integral+=pid.err; } } // pid.voltage=pid.Kp*pid.err+index*pid.Ki*pid.integral+pid.Kd*(pid.err-pid.err_last); pid.voltage=pid.Kp*pid.err+index*pid.Ki*pid.integral/2+pid.Kd*(pid.err-pid.err_last);//梯形积分 pid.err_last=pid.err; pid.ActualSpeed=pid.voltage*1.0; return pid.ActualSpeed; } int main(){ PID_init(); int count=0; while(count<1000) { float speed=PID_realize(200.0); printf("%f\n",speed); count++; } return 0; }
相关文章推荐
- 2015级C++第6周项目 类的组合、静态存储
- 用C++实现快速排序
- VSCode配置C++编写环境
- PID连续控制算法的表达式以及C语言实现
- 【C++】《C++标准程序库》小结第十三章-stream(1)
- C++中的深浅拷贝问题
- C语言中空格符,制表符,换行符详解
- c++之派生类访问基类的友元函数
- C/C++中指向指针的指针传递函数
- 函数
- 牛客网-拼接最小字典序问题
- 『C++ Primer学习笔记』Chapter 1
- C++Builder 2010 生产的EXE软件在没由安装C++Builder 2010的电脑上运行的方法
- C++ _类模板
- 第七届蓝桥杯省赛C\C++B组题目之四平方和
- C语言实现时间的加一天或者减一天
- Libb64:c/c++实现的base64编码解码库函数
- C++中数字与字符串之间的转换,别人的,
- C++ 之 构造函数与析构函数
- 欢迎使用CSDN-markdown编辑器