1. 數字(離散)PID控制算法的表達式:
將PID調節器離散化,用差分方程來代替連續系統的微分方程,分爲位置式和增量式兩類。
重點理解概念如下:
a) 基本偏差e(t):表示當前測量值與設定目標值間的差,設定目標是被減數,結果可爲正或負值,正值表示未達到目標,負值表示超過設定值。(代表比例)
b) 偏差和:即每次測量的差值總和,注意正負(代表積分)
c) 基本偏差的相對偏差:即e(t)-e(t-1)用本次的基本偏差減去上一次的基本偏差。(代表微分)
位置式:
增量式:
位置式和增量式三個參數的作用:
1. Kp參數:能迅速反映誤差,從而減小誤差,但他不能消除穩態誤差,加大Kp還會引起系統的不穩定。
2. Ki參數:只要有足夠的時間,積分作用將能完全消除誤差。但其缺點積分控制是偏差累積控制,控製作業緩慢,但是如果積分作用太強會使系統的超調量加大,甚至出現振盪。
3. Kd參數:預測誤差變化趨勢,減小超調量,克服振盪,使系統的穩定性提高,還能加快系統的動態響應速度,減小調整時間,從而改善系統的動態性能。
參考代碼如下:
- /*
- 位置型pid
- */
- #include <stdio.h>
- #include<ioctl.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;
- }
增量式代碼:
- /*
- 增量型pid
- */
- #include<stdio.h>
- #include<stdlib.h>
- 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;
- }