版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/DanielDingshengli/article/details/84639745
了解
参考教程
http://slidegur.com/doc/5058551/visual-modelq
软件下载地址关注本博客留言即可获取。
PID控制代码实现
/* 1.比例环节Kp,作用是加快系统的响应速度,提高系统的调节精度,副作用是会导致超调;
2.积分环节Ki,作用是消除稳态误差,副作用是导致积分饱和现象;
3.微分环节Kd,作用是改善系统的动态性能,副作用是延长系统的调节时间。
理解了上述问题,那么就可以“辩证施治,对症下药”了。比如说,如果系统响应速度慢,我们就加大Kp的取值,如果超调量过大
我们就减小Kp的取值等等。可是问题这些语言的描述该如何用数学形式表达出来呢。我们所知道的,反馈系统的实质就是系统的输
出量作为反馈量与系统的输入量进行作差,从而得到系统的误差e,那么这个误差e就能够反应目前系统所处的状态。误差e可以表
明目前系统的输出状态到底偏离要求多少。而误差e的变化律ec,表示误差变化的速度。这样,我们可以根据这两个量的状态来分
析三个参数此时应该如何取值,假如e为负方向比较大,ec也为负方向增大状态,此时比例环节要大一些,从而加快调节速度,而
积分环节要小一些,甚至不加积分环节,从而防止负方向上出现饱和积分的现象。微分环节可以稍加一些,在不影响调节时间的情况
下,起到改善系统动态性能的作用*/
#include <stdio.h>
struct _pid{
float SetSpeed; //定义设定值
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.015;
pid.Kd=0.2;
printf("PID_init end \n");
}
float PID_realize(float speed){
pid.SetSpeed=speed;
pid.err=pid.SetSpeed-pid.ActualSpeed;
pid.integral+=pid.err;
pid.voltage=pid.Kp*pid.err+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(){
printf("System begin \n");
PID_init();
int count=0;
while(count<1000)
{
float speed=PID_realize(200.0);
printf("%f\n",speed);
count++;
}
return 0;
}
struct _pid{
float SetSpeed; //定义设定值
float ActualSpeed; //定义实际值
float err; //定义偏差值
float err_next; //定义上一个偏差值
float err_last; //定义最上前的偏差值
float Kp,Ki,Kd; //定义比例、积分、微分系数
}pid;
void PID_init(){
pid.SetSpeed=0.0;
pid.ActualSpeed=0.0;
pid.err=0.0;
pid.err_last=0.0;
pid.err_next=0.0;
pid.Kp=0.2;
pid.Ki=0.015;
pid.Kd=0.2;
}
float PID_realize(float speed){
pid.SetSpeed=speed;
pid.err=pid.SetSpeed-pid.ActualSpeed;
float incrementSpeed=pid.Kp*(pid.err-pid.err_next)+pid.Ki*pid.err+pid.Kd*(pid.err-2*pid.err_next+pid.err_last);
pid.ActualSpeed+=incrementSpeed;
pid.err_last=pid.err_next;
pid.err_next=pid.err;
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的基本思想是设法改变积分项的累加速度,使其与偏差大小相对应:偏差越大,积分越慢; 偏差越小,积分越快。
这里给积分系数前加上一个比例值index:
当abs(err)<180时,index=1;
当180<abs(err)<200时,index=(200-abs(err))/20;
当abs(err)>200时,index=0;
最终的比例环节的比例系数值为ki*index;
具体PID实现代码如下:*/
pid.Kp=0.4;
pid.Ki=0.2; //增加了积分系数
pid.Kd=0.2;
float PID_realize(float speed){
float index;
pid.SetSpeed=speed;
pid.err=pid.SetSpeed-pid.ActualSpeed;
if(abs(pid.err)>200) //变积分过程
{
index=0.0;
}else if(abs(pid.err)<180){
index=1.0;
pid.integral+=pid.err;
}else{
index=(200-abs(pid.err))/20;
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;
}