023_STM32之PID算法原理及應用


(O)關於程序BUG說明,看最后面的紅色字體,視頻和源代碼中都沒有說明

(一)PID控制算法(P:比例     I:積分    D:微分)

(二)首先先說明原理,使用的是數字PID算法,模擬PID算法在計算機這樣的系統中是不能夠直接使用的,數字PID算法又分為位置式PID控制算法增量式PID控制算法,那么下面從原理上說明這兩種算法

(三)原理分析如圖

 

(四)從上面圖中我們可以得到定義

定義變量
用戶設定值:         SV
當前值(實際值):    PV
偏差:              E = SV - PV       

 

(五)如果我們在一段時間內就從傳感器讀取一個值,那么我們就可以得到一個實際值的數據序列,,那么我們也會得到一個偏差值的序列

讀取時間:  t(1) t(2)    ------  t(k-1) t(k) 讀取到的值: X(1) X(2)    ------  X(k-1)  X(k)
偏差值: E(1) E(2)    ------  E(k-1)  E(k)


那么我們從偏差值中可以知道:  E(X) > 0     說明未達標
                E(X) = 0     說明正好達標
                E(X) < 0 說明超標

 

 (六)比例控制(P),作用:對偏差起到及時反映的作用,一旦產生偏差,控制器立即做出反映.............

定義:
比例系數:Kp    (根據系統進行調節)
比例輸出:POUT  = Kp * E(k) 
     POUT = Kp * E(k) + OUT0

OUT0說明:OUT0是防止E(K) = 0 時候比例控制不作用,所以添加個OUT0進去,OUT0可以根據系統定義大小
Kp說明:如果我們得到一個偏差之后,將偏差進行放大或者縮小來讓控制器進行控制

 

(七)積分控制(I),作用:消除靜差............

從上面我們得到偏差序列:
偏差值: E(1) E(2)    ------  E(k-1)  E(k)

定義,歷史偏差值之和:S(k) = E(1) + E(2) + .... + E(k-1) + E(K)
定義,積分輸出:   IOUT = Kp * S(k) + OUT0

 

(八)微分控制(D),作用:反映偏差信號的變化趨勢.............

從上面我們得到偏差序列: 偏差值: E(1)    E(2)    ------  E(k-1)  E(k)
定義,偏差之差:D(k) = E(k) - E(k-1)
定義,微分輸出:DOUT = Kp * D(k) + OUT0

 

(九)那么我們從上面就能得出PID的控制算法

PIDOUT = POUT + IOUT + DOUT = (Kp * E(k) + OUT0) + (Kp * S(k) + OUT0) + (Kp * D(k) +OUT0)
       = Kp * (E(k) + S(k) + D(k)) + OUT0

OUT0防止PIDOUT = 0 時候算法還有輸出,防止失去控控制
比例(P):考慮當前
積分(I):考慮歷史
微分(D):考慮未來

 

(十)位置式PID,上面只是簡單的說明了一下原理,那么實際的數字PID控制算法中,額,那個變換公式打不出來,自行百度,這里就直接打出結果

Ti:積分常數
TD:微分常數
T:計算周期

上面兩個是變化后的積分和微分的那個,那么我們把上面的兩個替換到第九點中,我們就得到位置上PIDOUT的公式,兩個式子是一樣的

 

(十一)增量式PID,本次基礎上加上多少偏差:△OUT

 

/**********************分割線************************/

(十二)上面的只是PID的原理說明,那么數字PID的公式是

(十三)那么我們將上面的公式通過通過C語言寫出來

1. 位置式PID

#ifndef _pid_ #define _pid_ #include "stm32f10x_conf.h"
#define     MODEL_P         1
#define     MODEL_PI         2
#define     MODEL_PID     3 typedef struct { u8 choose_model; //使用哪個模式調節
    
    float Sv;     //用戶設定值
    float Pv;        //當前值,實際值
 
    float Kp;        //比例系數
    float T;      //PID計算周期--采樣周期
    u16   Tdata;    //判斷PID周期到沒到
    float Ti;        //積分時間常數
    float Td;       //微分系數
    
    
    
    float Ek;          //本次偏差
    float Ek_1;        //上次偏差
    float SEk;         //歷史偏差之和
    
    float Iout;        //積分輸出
    float Pout;        //比例輸出 
    float Dout;        //微分輸出
    
    float OUT0;        //一個維持的輸出,防止失控

    float OUT;        //計數最終得到的值
 u16 pwmcycle;//pwm周期
 }PID; extern PID pid; //存放PID算法所需要的數據
void PID_Calc(void); //pid計算
void PID_Init(void);        //PID初始化 

#endif
#include "pid.h" #include "PWM_Config.h" #include "USART_Config.h"   //USART設置
 PID pid; //存放PID算法所需要的數據
void PID_Init() { pid.choose_model = MODEL_PID; pid.T=330;                //采樣周期,定時器使用1ms,則最小執行PID的周期為330ms
 pid.Sv=280;                //用戶設定值
    pid.Kp=0.5;                //比例系數
  pid.Ti=180;            //積分時間
    pid.Td=1;                    //微分時間
    pid.OUT0=0;                //一個維持的輸出
 pid.pwmcycle = 330;    //PWM的周期
} void PID_Calc()  //pid計算
{ float DelEk;            //本次和上次偏差,最近兩次偏差之差
    float ti,ki; float td; float kd; float out; if(pid.Tdata < (pid.T))  //最小計算周期未到
 { return ; } pid.Tdata = 0; pid.Ek=pid.Sv-pid.Pv;               //得到當前的偏差值
    pid.Pout=pid.Kp*pid.Ek;          //比例輸出
 pid.SEk+=pid.Ek;                    //歷史偏差總和
 DelEk=pid.Ek-pid.Ek_1;              //最近兩次偏差之差
 ti=pid.T/pid.Ti; ki=ti*pid.Kp; pid.Iout=ki*pid.SEk*pid.Kp;  //積分輸出
/*注意:上面程序中多了個pid.Kp,原程序中有,請自動刪除,正確的應該是pid.Iout=ki*pid.SEK */
td=pid.Td/pid.T; kd=pid.Kp*td; pid.Dout=kd*DelEk; //微分輸出 switch(pid.choose_model) { case MODEL_P: out= pid.Pout; printf("使用P運算\r\n") ; break; case MODEL_PI: out= pid.Pout+ pid.Iout; printf("使用PI運算\r\n") ; break; case MODEL_PID: out= pid.Pout+ pid.Iout+ pid.Dout; printf("使用PID運算\r\n") ; break; } printf("PID算得的OUT:\t%d\r\n",(int)out) ; ////////////////////////////////////////////////////////// /*判斷算出的數是否符合控制要求*/ if(out>pid.pwmcycle) //不能比PWM周期大,最大就是全高嗎 { pid.OUT=pid.pwmcycle; } else if(out<0) //值不能為負數 { pid.OUT=pid.OUT0; } else { pid.OUT=out; } printf("實際輸出使用的pid.OUT:\t%d\r\n",(int)pid.OUT) ; pid.Ek_1=pid.Ek; //更新偏差 Turn_Angle((int)pid.OUT); //輸出PWM }

 

2.增量式PID

#ifndef _pid_ #define _pid_ #include "stm32f10x_conf.h"
#define     MODEL_P         1
#define     MODEL_PI         2
#define     MODEL_PID     3 typedef struct { u8 choose_model; //使用哪個模式調節
    
  float curr;              //當前值
    float set;               //設定值
    

    float En;                    //當前時刻
    float En_1;                //前一時刻
    float En_2;                //前二時刻
        
    float Kp;               //比例系數
    float T;                     //采樣周期---控制周期,每隔T控制器輸出一次PID運算結果
    u16   Tdata;            //判斷PID周期到沒到
    float Ti;               //積分時間常數
    float Td;               //微分時間常數
    
    float Dout;                //增量PID計算本次應該輸出的增量值--本次計算的結果
    float OUT0;                //一個維持的輸出,防止失控
    
    short currpwm;      //當前的pwm寬度
    u16 pwmcycle;       //pwm周期
 }PID; extern u8 STATUS; extern PID pid; void PIDParament_Init(void);  /*增量式PID初始化*/
void pid_calc(void);                  /*pid計算 並輸出*/

#endif
#include "pid.h" #include "PWM_Config.h" #include "USART_Config.h"   //USART設置
 PID pid; void PIDParament_Init()  // { pid.choose_model = MODEL_PID; pid.T=330;                //采樣周期,定時器使用1ms,則最小執行PID的周期為330ms
 pid.set =280;            //用戶設定值
    pid.Kp=0.5;                //比例系數
    pid.Ti=40;                //微分系數常數
    pid.Td=10;                //積分時間常數
    pid.OUT0=0;                //一個維持的輸出
 pid.pwmcycle = 330;    //PWM的周期
} void pid_calc()  //pid??
{ float dk1;float dk2; float t1,t2,t3; if(pid.Tdata < (pid.T))  //最小計算周期未到
 { return ; } pid.Tdata = 0; pid.En=pid.set-pid.curr;  //本次誤差
    dk1=pid.En-pid.En_1;   //本次偏差與上次偏差之差
    dk2=pid.En-2*pid.En_1+pid.En_2; t1=pid.Kp*dk1;                            //比例
 t2=(pid.Kp*pid.T)/pid.Ti;      //積分
    t2=t2*pid.En; t3=(pid.Kp*pid.Td)/pid.T;        //微分
    t3=t3*dk2; switch(pid.choose_model) { case MODEL_P:     pid.Dout= t1;                    printf("使用P運算\r\n") ; break; case MODEL_PI:  pid.Dout= t1+t2;                printf("使用PI運算\r\n") ; break; case MODEL_PID: pid.Dout= t1+t2+t3;        printf("使用PID運算\r\n") ; break; } pid.currpwm+=pid.Dout;  //本次應該輸出的PWM
    printf("PID算得的OUT:\t%d\r\n",(int)pid.currpwm) ; /*判斷算出的數是否符合控制要求*/
    if(pid.currpwm>pid.pwmcycle)            //算出的值取值,肯定是在0-pid.pwmcycle之間,不然的話PWM怎么輸出
 { pid.currpwm=pid.pwmcycle; } if(pid.currpwm<0) { pid.currpwm=0; } printf("實際輸出使用的OUT:\t%d\r\n",(int)pid.currpwm) ; pid.En_2=pid.En_1; pid.En_1=pid.En; Turn_Angle(pid.currpwm); //輸出PWM
 }

 (十五)上面我們貼出來位置式PID算法和增量式PID算法的核心部分了,但是上面的理論上可以直接移植,添加一些還沒有定義的變量就好了,下面是具體的演示工程

 

024——PID算法整定

(一)首先在使用PID算法之前先進行基礎的設置

1. PWM正脈沖控制輸出開

2. 傳感器曲線隨着PWM占空比越大而越大

3. 傳感器在環境下情況下最低數據    ,和最高數據。 設定值不能超過這兩個范圍

 

(二)湊試法的基本方法是:對參數實行先比例,后積分,再微分的整定步踩具體步驟如下:
 
1)首先先只整定比例部分。將比例系數Kp由小變大,觀察系統響應的變化情況,直到得到反應快、超調小的響應曲線。如果系統沒有靜差或靜差小到允許的范圍內,那么只需要比例控制器即可滿足要求。
 
2)整定積分時間常數。在比例控制下系統的靜差不滿足設計要求時,則需要采用積分環節來消除靜差。整定時,首先置積分時間Ti為一較大值,並將經第一步整定很到的比例系數略為縮小(如縮小為原值的4/5),觀察系統響應的情況,然后根據觀察的情況來減小積分時間常數,同時比例系數也可能縮小,使系統消除靜差的同時能夠獲得良好的動態性值在此過程中,在此過程可根據響應曲線的好壞反復改變比例系數與積分時間常數,以期得到滿意的控制過程與整定參數。
 
3)整定微分時間常數。若使用比例積分控制器消除了靜差,但動態過程經反復調勝仍不能滿意(主要是響應速度達不到要求),則可加人微分環節,構成PID控制器。整定時先置.較小的微分時間常數,同時比例系數略微減小、 積分時間常數略微增大,觀察系統師應的情況。然后加大微分時間常數,比例系數、積分時間常數相應調整,反復調整,直到得滿意的控制過程和整定參數。

 

(三)總結試湊法

1. 比例系數有小到大,然后找出超調小的Kp

2. 積分時間常數Ti由大變小,適當調整Kp

3. 微分時間常數Td由小變大,適當調整Ti和Kp

 

(四)實驗總結

1. KP設定,最初使用1,假如控制之后實際值比設定值小不夠,那就增大。反之就減少。

2. TI設定,數據先很大。看效果

  1). 如果TI加進去之后數據很久才變化到目標值就逐漸減小。如果TI減少到執行幾次都是比設定值大的時候那就逐漸增大

  2). 如果剛加進去變化很快,並且超調很高,就增大來調節

3. 積分就看情況調節

 

(五)增量式PID控制與位置式PID控制比較,有如下優點:
    1)由式增量式PID控制與位置式PID可見,增量式PID控制算式只需要現時刻以及前兩個時刻的偏差采樣值,計算量和存儲量都小,且計算的是增量,當存在計算誤差或精度不足時,對控制量計算的影響較小。而位置式PID控制算式每次計算均與整個過去的狀態有關,需要過去所有的偏差采樣值參與累積計算,容易產生較大的積累誤差,存儲量和計算量較大。
 
    2)增量式PID控制容易實現無擾動切換。增量式PID控制算法是對前一一時刻控制量的增量式變化,對執行機構的沖擊小。位置式PID控制算法則是對前一穩定運行點控制量的絕對大小的變化,變化大,對執行機構容易產生沖擊。
 
    3)增量式PID控制本質上具有更好的抗干擾能力。若某個時刻采樣值受到干擾,對於位置式PID控制,這個干擾會一直影響系統的整個運行過程;而增量式PID控制算式只需要現時刻以及前兩個時刻的偏差采樣值,干擾最多影響3個采樣時間,其他時間不受該干擾的影響。
 
    4)位置式PID控制比增量式PID控制更容易產生積分飽和。
 
    5)在實際控制中,增量式PID控制算法比位置式PID控制算法應用更為廣泛。

 

 【故事】我和PID控制之六:采樣周期惹的禍

 

 

注意:視頻中有一些地方口誤,記得識別,如毫秒可能會讀成微妙,額。。。。沒辦法

注意:關於位置式PID算法中程序積分公式那里多了個pid.Kp,記得刪除,具體的位置看上面的位置式PID

程序中有注解,資料下載下來的程序沒有刪除,記得刪除!!!!!!

 

視頻教程:https://v.qq.com/x/page/o0826j2am1x.html

資料下載:https://download.csdn.net/download/xiaoguoge11/10911361

 

 


免責聲明!

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



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