實(shí)際調(diào)參
從實(shí)際的 PID 系統(tǒng)曲線來理解 PID 各個(gè)系數(shù)的調(diào)節(jié)效果。
① 先調(diào)整比例系數(shù),積分、微分系數(shù)設(shè)置為 0,此時(shí)的系統(tǒng)只有比例環(huán)節(jié)參與控制,此時(shí)系統(tǒng)的曲線出現(xiàn)大幅振蕩。
首先確定硬件上是否出現(xiàn)了故障,例如電壓不穩(wěn)定、電機(jī)堵轉(zhuǎn)等,排除了這些之后,那就說明比例系數(shù)調(diào)節(jié)的過大了,這個(gè)時(shí)候我們可以把比例系數(shù)慢慢地減小,并同時(shí)觀察曲線的變化。
② 當(dāng)我們調(diào)小比例系數(shù)之后,曲線的大幅度振蕩現(xiàn)象消失,但是曲線依舊存在小幅度的超調(diào)現(xiàn)象,并且此時(shí)通過調(diào)節(jié)比例系數(shù)已經(jīng)無法優(yōu)化曲線。
此時(shí),我們可以慢慢地增大微分系數(shù),并同時(shí)觀察曲線的變化,從而找到最合適的參數(shù)。
增大微分系數(shù)之后,如果系統(tǒng)的曲線已經(jīng)較為理想,則說明這個(gè)系統(tǒng)只需要比例和微分環(huán)節(jié)的控制。
③ 如果在純比例環(huán)節(jié)的控制下,系統(tǒng)的實(shí)際值始終達(dá)不到目標(biāo)值,存在靜態(tài)誤差。
此時(shí),可以逐漸增大積分系數(shù),并同時(shí)觀察曲線的變化,如果消除靜差的時(shí)間過長,則可以再適當(dāng)增大積分系數(shù),但是需要注意兼顧系統(tǒng)的超調(diào)量。
經(jīng)過調(diào)整之后,如果系統(tǒng)的曲線已經(jīng)較為理想,則說明這個(gè)系統(tǒng)只需要比例和積分環(huán)節(jié)的控制。
④ 如果系統(tǒng)在比例和積分環(huán)節(jié)的控制下出現(xiàn)小幅度的超調(diào)現(xiàn)象,可以慢慢地增大微分系數(shù),并同時(shí)觀察曲線的變化,從而找到最合適的參數(shù)。
以上就是在實(shí)際調(diào)參中經(jīng)常遇到的一些問題以及解決方法。在實(shí)際應(yīng)用中,控制系統(tǒng)是多樣且復(fù)雜的,這一些方法只能作為參考,并不是通用的,因此在 PID 調(diào)參過程中,要注意經(jīng)驗(yàn)的積累。
參考Code
PID初始化代碼
定義一個(gè)新的PID參數(shù)時(shí),就是建立一個(gè)新的結(jié)構(gòu)體,運(yùn)算和初始化時(shí)直接調(diào)用對(duì)應(yīng)的成員變量就行,十分方便簡潔,具體定義的結(jié)構(gòu)體如下:
typedef struct{
//PID運(yùn)算模式
uint8_t mode;
//PID 三個(gè)基本參數(shù)
__IO float Kp;
__IO float Ki;
__IO float Kd;
__IO float max_out; //PID最大輸出
__IO float max_iout; //PID最大積分輸出
__IO float2 set; //PID目標(biāo)值
__IO float2 fdb; //PID當(dāng)前值
__IO float out; //三項(xiàng)疊加輸出
__IO float Pout; //比例項(xiàng)輸出
__IO float Iout; //積分項(xiàng)輸出
__IO float Dout; //微分項(xiàng)輸出
//微分項(xiàng)最近三個(gè)值 0最新 1上一次 2上上次
__IO float Dbuf[3];
//誤差項(xiàng)最近三個(gè)值 0最新 1上一次 2上上次
__IO float error[3];
} pid_type_def;
初始運(yùn)行時(shí)調(diào)用一次,初始化各個(gè)參數(shù)
void Own_PID_init(pid_type_def *pid, uint8_t mode, const __IO float PID[3], __IO float max_out, __IO float max_iout){
if (pid == NULL || PID == NULL){
return;
}
pid- >mode = mode;
pid- >Kp = PID[0];
pid- >Ki = PID[1];
pid- >Kd = PID[2];
pid- >max_out = max_out;
pid- >max_iout = max_iout;
pid- >Dbuf[0] = pid- >Dbuf[1] = pid- >Dbuf[2] = 0.0f;
pid- >error[0] = pid- >error[1] = pid- >error[2] = pid- >Pout = pid- >Iout = pid- >Dout = pid- >out = 0.0f;
}
PID運(yùn)算代碼
__IO float PID_calc(pid_type_def *pid, __IO float ref, __IO float set)
{
//判斷傳入的PID指針不為空
if (pid == NULL){
return 0.0f;
}
//存放過去兩次計(jì)算的誤差值
pid- >error[2] = pid- >error[1];
pid- >error[1] = pid- >error[0];
//設(shè)定目標(biāo)值和當(dāng)前值到結(jié)構(gòu)體成員
pid- >set = set;
pid- >fdb = ref;
//計(jì)算最新的誤差值
pid- >error[0] = set - ref;
//判斷PID設(shè)置的模式
if (pid- >mode == PID_POSITION)
{
//位置式PID
//比例項(xiàng)計(jì)算輸出
pid- >Pout = pid- >Kp * pid- >error[0];
//積分項(xiàng)計(jì)算輸出
pid- >Iout += pid- >Ki * pid- >error[0];
//存放過去兩次計(jì)算的微分誤差值
pid- >Dbuf[2] = pid- >Dbuf[1];
pid- >Dbuf[1] = pid- >Dbuf[0];
//當(dāng)前誤差的微分用本次誤差減去上一次誤差來計(jì)算
pid- >Dbuf[0] = (pid- >error[0] - pid- >error[1]);
//微分項(xiàng)輸出
pid- >Dout = pid- >Kd * pid- >Dbuf[0];
//對(duì)積分項(xiàng)進(jìn)行限幅
LimitMax(pid- >Iout, pid- >max_iout);
//疊加三個(gè)輸出到總輸出
pid- >out = pid- >Pout + pid- >Iout + pid- >Dout;
//對(duì)總輸出進(jìn)行限幅
LimitMax(pid- >out, pid- >max_out);
}
else if (pid- >mode == PID_DELTA)
{
//增量式PID
//以本次誤差與上次誤差的差值作為比例項(xiàng)的輸入帶入計(jì)算
pid- >Pout = pid- >Kp * (pid- >error[0] - pid- >error[1]);
//以本次誤差作為積分項(xiàng)帶入計(jì)算
pid- >Iout = pid- >Ki * pid- >error[0];
//迭代微分項(xiàng)的數(shù)組
pid- >Dbuf[2] = pid- >Dbuf[1];
pid- >Dbuf[1] = pid- >Dbuf[0];
//以本次誤差與上次誤差的差值減去上次誤差與上上次誤差的差值作為微分項(xiàng)的輸入帶入計(jì)算
pid- >Dbuf[0] = (pid- >error[0] - 2.0f * pid- >error[1] + pid- >error[2]);
pid- >Dout = pid- >Kd * pid- >Dbuf[0];
//疊加三個(gè)項(xiàng)的輸出作為總輸出
pid- >out += pid- >Pout + pid- >Iout + pid- >Dout;
//對(duì)總輸出做一個(gè)先限幅
LimitMax(pid- >out, pid- >max_out);
}
return pid- >out;
}
#define LimitMax(input, max)
{
if (input > max)
{
input = max;
}
else if (input < -max)
{
input = -max;
}
}
PID數(shù)據(jù)清空代碼
有時(shí)候需要清除中間變量,例如目標(biāo)值和中間變量清零。
void PID_clear(pid_type_def *pid)
{
if (pid == NULL)
{
return;
}
//當(dāng)前誤差清零
pid- >error[0] = pid- >error[1] = pid- >error[2] = 0.0f;
//微分項(xiàng)清零
pid- >Dbuf[0] = pid- >Dbuf[1] = pid- >Dbuf[2] = 0.0f;
//輸出清零
pid- >out = pid- >Pout = pid- >Iout = pid- >Dout = 0.0f;
//目標(biāo)值和當(dāng)前值清零
pid- >fdb = pid- >set = 0.0f;
}
-
控制系統(tǒng)
+關(guān)注
關(guān)注
41文章
6642瀏覽量
110720 -
硬件
+關(guān)注
關(guān)注
11文章
3354瀏覽量
66337 -
PID
+關(guān)注
關(guān)注
35文章
1473瀏覽量
85648
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論