您的位置:首页 > 编程语言 > C语言/C++

改进式PID控制以及C语言实现过程

2017-05-02 15:09 169 查看
改进式PID控制

         如果是在低速模式下,标准的PID基本可以满足控制要求,但随着速度的提升,PID算法要进一步修改和完善才能达到控制要求。因此需要对PID算式进行适当的改进,从而提高控制质量。

         积分项的改进

         积分项的作用:消除稳态误差,提高控制系统的精度。

积分项存在的问题:偏差较大时,积分的滞后作用会影响系统的响应速度,引起较大的超调及加长过渡过程,尤其对时间常数较大,有时间滞后的被控对象,更加剧了振荡过程。

1.      积分分离法:

改进方案:当偏差大于某个规定的门限值时,取消积分作用,从而使积分不至于过大。只有当e(k)较小时,才引入积分作用,以消除静差。这样控制量不易进入饱和区;即使进入了饱和区,也能较快的退出,所以能使系统的输出特性得到改善。

 

2.      抗积分饱和法:

改进方案:当控制量进入饱和区后,只执行削弱积分项的累加,而不进行增大积分项的累加。即计算u(k)时,先判断u(k-1)是否超过限制范围,若已超过umax,则只累计负偏差;若小于umin,则只累计正偏差,这种方法也可以避免控制量长期停留在饱和区。

算法案例如下:

[cpp] view
plain copy

 print?

/* 

    积分分离的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;  

}  

[cpp] view
plain copy

 print?

/* 

    抗击分饱和的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;  

}  

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: