增量式PID到底是什么?
掃描二維碼
隨時隨地手機看文章
0 前面的話
好久沒有更新了,內(nèi)心有種罪惡感,,至于原因,可能是因為菜吧,不知道該寫什么,還有就是因為懶吧,雖然一部分在B乎上發(fā)了,被噴了一地,便沒整理到公眾號。后面打算整理一個PID算法系列,系統(tǒng)地總結(jié)和整理一下;
這里給大家推薦一首灌籃高手的片尾曲,三井壽是灌籃高手中我最喜歡的人物之一,在湘北對抗翔陽的比賽中,三井在對位長谷川一志時體力近乎崩潰。但他想起國中的那場決賽,想到安西教練那番話:“你現(xiàn)在放棄就等于比賽提前結(jié)束?!毕氲剿彩菆猿值阶詈蟛湃〉昧藙倮?。此時,他又重燃斗志,于是便響起了這首歌《直到世界終結(jié)》。希望在生活中,大家遇到挫折和困難,多一點堅持,最終一定都能克服難關(guān)。(感覺有點陳年雞湯了)
目錄
1 什么是增量式PID?
2 舉個例子
2.1 位置式PID
2.2 增量式PID
3 偽算法
4 C語言實現(xiàn)
5 總結(jié)
在之前一篇博客中( 簡易PID算法的快速掃盲 )簡單介紹了PID算法的基本原理和位置式算法的實現(xiàn)過程,由于部分推導(dǎo)過程已經(jīng)在上一篇文章做過介紹,所以推導(dǎo)過程本文不再贅述,重點將對離散增量式PID的算法進(jìn)行實現(xiàn)。
1 什么是增量式PID?
先看一下增量式PID的離散公式如下:
:比例系數(shù)
:積分系數(shù)
:微分系數(shù)
:偏差
對于所謂的位置式,增量式的算法,這兩者只是在算法的實現(xiàn)上的存在差異,本質(zhì)的控制上對于系統(tǒng)控制的影響還是相同,單純從輸入和輸出的角度來比較,具體如下表所示;
這里簡單的說明一下;
-
位置式:位置式算法較為簡單,直接輸入當(dāng)前的偏差 ,即可得到輸出 ; -
增量式:增量式算法需要保存歷史偏差, ,即在第 次控制周期時,需要使用第 和第 次控制所輸入的偏差,最終計算得到 ,此時, 這還不是我們所需要的PID輸出量;所以需要進(jìn)行累加;
不難發(fā)現(xiàn)第一次控制周期時,即 時;
由以上公式我們可以推導(dǎo)出下式;
所以可以看出,最終PID的輸出量 ,滿足以下公式;
可見增量式算法,就是所計算出的PID增量的歷史累加和;
2 舉個例子
2.1 位置式PID
下面從一個簡單的例子中去理解一下增量式PID
,這里依然舉一個不是很恰當(dāng)?shù)睦?;如果?strong>位置式PID算法的話:
-
隆哥對一個直流電機進(jìn)行調(diào)速,設(shè)定了轉(zhuǎn)速為 1000; -
這時由于反饋回來的速度和設(shè)定的速度偏差為 ; -
經(jīng)過 位置式PID計算得到 ; -
作為 Process的輸入值(可以是 PWM的占空比),最終 Process輸出相應(yīng)的 PWM驅(qū)動直流電機; -
反饋裝置檢測到電機轉(zhuǎn)速,然后重復(fù)以上步驟;
整體框圖如下所示;
2.2 增量式PID
對于增量式PID來說;
-
隆哥對一個直流電機進(jìn)行調(diào)速,設(shè)定了轉(zhuǎn)速為 1000; -
這時由于反饋回來的速度和設(shè)定的速度偏差為 ,系統(tǒng)中保存上一次的偏差 和上上次的偏差 ,這三個輸入量經(jīng)過 增量PID計算得到 ; -
系統(tǒng)中還保存了上一次的 PID輸出的 ,所以 加上增量 ,就是本次控制周期的 PID輸出—— ; -
作為 Process的輸入值(可以是 PWM的占空比),最終 Process輸出相應(yīng)的 PWM驅(qū)動直流電機; -
反饋裝置檢測到電機轉(zhuǎn)速,然后重復(fù)以上步驟;
整體框圖如下所示;
所以這里不難發(fā)現(xiàn),所謂增量式PID,它的特點有:
-
需要輸入歷史的偏差值; -
計算得到的是PID輸出增量,因此每一次需要累加歷史增量最為當(dāng)前的PID輸出;
下面簡單介紹一下如何實現(xiàn)增量式PID算法;
3 偽算法
previous02_error := 0 //上上次偏差
previous01_error := 0 //上一次偏差
integral := 0 //積分和
pid_out := 0 //pid增量累加和
//循環(huán)
//采樣周期為dt
loop:
//setpoint 設(shè)定值
//measured_value 反饋值
error := setpoint ? measured_value //計算得到偏差
proportion := error - previous01_error //計算得到比例輸出
integral := error × dt //計算得到積分累加和
derivative := (error ? 2*previous01_error + previous02_error) / dt //計算得到微分
pid_delta := Kp × error + Ki × integral + Kd × derivative //計算得到PID增量
pid_out := pid_out + pid_delta //計算得到PID輸出
//保存當(dāng)前的偏差和上一次偏差作為下一次采樣所需要的歷史偏差
previous02_error := previous01_error
previous01_error := error //保存當(dāng)前偏差為下一次采樣時所需要的歷史偏差
wait(dt) //等待下一次采用
goto loop
4 C語言實現(xiàn)
這里直接使用了TI
公司的PID算法,做了積分抗飽和;具體可以參考controlSUITE\libs\app_libs\motor_control\math_blocks\v4.2\pid_grando.h
具體代碼如下所示;
pid_grando.h
/* =================================================================================
File name: PID_GRANDO.H
===================================================================================*/
#ifndef __PID_H__
#define __PID_H__
typedef struct { _iq Ref; // Input: reference set-point
_iq Fbk; // Input: feedback
_iq Out; // Output: controller output
_iq c1; // Internal: derivative filter coefficient 1
_iq c2; // Internal: derivative filter coefficient 2
} PID_TERMINALS;
// note: c1 & c2 placed here to keep structure size under 8 words
typedef struct { _iq Kr; // Parameter: reference set-point weighting
_iq Kp; // Parameter: proportional loop gain
_iq Ki; // Parameter: integral gain
_iq Kd; // Parameter: derivative gain
_iq Km; // Parameter: derivative weighting
_iq Umax; // Parameter: upper saturation limit
_iq Umin; // Parameter: lower saturation limit
} PID_PARAMETERS;
typedef struct { _iq up; // Data: proportional term
_iq ui; // Data: integral term
_iq ud; // Data: derivative term
_iq v1; // Data: pre-saturated controller output
_iq i1; // Data: integrator storage: ui(k-1)
_iq d1; // Data: differentiator storage: ud(k-1)
_iq d2; // Data: differentiator storage: d2(k-1)
_iq w1; // Data: saturation record: [u(k-1) - v(k-1)]
} PID_DATA;
typedef struct { PID_TERMINALS term;
PID_PARAMETERS param;
PID_DATA data;
} PID_CONTROLLER;
/*-----------------------------------------------------------------------------
Default initalisation values for the PID objects
-----------------------------------------------------------------------------*/
#define PID_TERM_DEFAULTS { \
0, \
0, \
0, \
0, \
0 \
}
#define PID_PARAM_DEFAULTS { \
_IQ(1.0), \
_IQ(1.0), \
_IQ(0.0), \
_IQ(0.0), \
_IQ(1.0), \
_IQ(1.0), \
_IQ(-1.0) \
}
#define PID_DATA_DEFAULTS { \
_IQ(0.0), \
_IQ(0.0), \
_IQ(0.0), \
_IQ(0.0), \
_IQ(0.0), \
_IQ(0.0), \
_IQ(0.0), \
_IQ(1.0) \
}
/*------------------------------------------------------------------------------
PID Macro Definition
------------------------------------------------------------------------------*/
#define PID_MACRO(v) \
\
/* proportional term */ \
v.data.up = _IQmpy(v.param.Kr, v.term.Ref) - v.term.Fbk; \
\
/* integral term */ \
v.data.ui = _IQmpy(v.param.Ki, _IQmpy(v.data.w1, \
(v.term.Ref - v.term.Fbk))) + v.data.i1; \
v.data.i1 = v.data.ui; \
\
/* derivative term */ \
v.data.d2 = _IQmpy(v.param.Kd, _IQmpy(v.term.c1, \
(_IQmpy(v.term.Ref, v.param.Km) - v.term.Fbk))) - v.data.d2; \
v.data.ud = v.data.d2 + v.data.d1; \
v.data.d1 = _IQmpy(v.data.ud, v.term.c2); \
\
/* control output */ \
v.data.v1 = _IQmpy(v.param.Kp, \
(v.data.up + v.data.ui + v.data.ud)); \
v.term.Out= _IQsat(v.data.v1, v.param.Umax, v.param.Umin); \
v.data.w1 = (v.term.Out == v.data.v1) ? _IQ(1.0) : _IQ(0.0); \
#endif // __PID_H__
example
/* Instance the PID module */
PID pid1={ PID_TERM_DEFAULTS, PID_PARAM_DEFAULTS, PID_DATA_DEFAULTS };
main() {
pid1.param.Kp = _IQ(0.5);
pid1.param.Ki = _IQ(0.005);
pid1.param.Kd = _IQ(0);
pid1.param.Kr = _IQ(1.0);
pid1.param.Km =_IQ(1.0);
pid1.param.Umax= _IQ(1.0);
pid1.param.Umin= _IQ(-1.0);
}
void interrupt periodic_interrupt_isr() {
pid1.Ref = input1_1; // Pass _iq inputs to pid1
pid1.Fbk = input1_2; // Pass _iq inputs to pid1
PID_MACRO(pid1); // Call compute macro for pid1
output1 = pid1.Out; // Access the output of pid1
}
5 總結(jié)
本文簡單總結(jié)了位置式PID算法和增量式PID算法的差異,參考了TI公司的增量式PID算法實現(xiàn),對于不同的控制對象可以根據(jù)系統(tǒng)要求選擇合適的PID算法;
由于作者能力和水平有限,文中難免存在錯誤和紕漏,請不吝賜教。
簡易PID算法的快速掃盲
一文教你搞懂C語言的Q格式
現(xiàn)成輪子OSAL操作系統(tǒng)抽象層的移植
一招教你單片機固件快速瘦身
基礎(chǔ)知識 | hex文件格式詳解
—— The End ——
長按識別二維碼關(guān)注獲取更多內(nèi)容
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!