PID--抗積分飽和法--004


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/***********************************************************************
    所謂的積分飽和現象是指如果系統存在一個方向的偏差, PID 控制器的輸
    出由於積分作用的不斷累加而加大, 從而導致執行機構達到極限位置, 若控制器
    輸出 U(k)繼續增大, 執行器開度不可能再增大, 此時計算機輸出控制量超出了
    正常運行范圍而進入飽和區。 一旦系統出現反向偏差, u(k)逐漸從飽和區退出。
    進入飽和區越深則退出飽和區時間越長。 在這段時間里, 執行機構仍然停留在極
    限位置而不隨偏差反向而立即做出相應的改變, 這時系統就像失控一樣, 造成控
    制性能惡化, 這種現象稱為積分飽和現象或積分失控現象。
    防止積分飽和的方法之一就是抗積分飽和法, 該方法的思路是在計算
    u(k)時, 首先判斷上一時刻的控制量 u(k-1)是否已經超出了極限范圍: 如果
    u(k-1)>umax, 則只累加負偏差;
    如果 u(k-1)<umin, 則只累加正偏差。 從而避
    免控制量長時間停留在飽和區。 直接貼出代碼, 不懂的看看前面幾節的介紹。
****************************************************************************/
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.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;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM