国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

PID控制參數(shù)整定(調(diào)節(jié)方法)原理+圖示+MATLAB調(diào)試

這篇具有很好參考價(jià)值的文章主要介紹了PID控制參數(shù)整定(調(diào)節(jié)方法)原理+圖示+MATLAB調(diào)試。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。


Chapter1 PID控制參數(shù)整定(調(diào)節(jié)方法)原理+圖示+MATLAB調(diào)試

原文鏈接:https://blog.csdn.net/viafcccy/article/details/107988093

首先最重要的是了解每個(gè)參數(shù)調(diào)節(jié)了系統(tǒng)響應(yīng)的那些屬性,通過(guò)觀察響應(yīng)從而調(diào)節(jié)參數(shù)改變屬性。

PID的作用概述:
1、P產(chǎn)生響應(yīng)速度和力度,過(guò)小響應(yīng)慢,過(guò)大會(huì)產(chǎn)生振蕩,是I和D的基礎(chǔ)。
2、I在有系統(tǒng)誤差和外力作用時(shí)消除偏差、提高精度,同時(shí)也會(huì)增加響應(yīng)速度,產(chǎn)生過(guò)沖,過(guò)大會(huì)產(chǎn)生振蕩。
3、D抑制過(guò)沖和振蕩,過(guò)小系統(tǒng)會(huì)過(guò)沖,過(guò)大會(huì)減慢響應(yīng)速度。D的另外一個(gè)作用是抵抗外界的突發(fā)干擾,阻止系統(tǒng)的突變。

同時(shí)調(diào)節(jié)的順序是:P>I>D

下面了解的一個(gè)很重要的就是調(diào)節(jié)的目標(biāo),也就是最好的響應(yīng)曲線是什么樣子。

PID 調(diào)節(jié)目標(biāo):

1、衰減比在4-10之間最佳,也就是響應(yīng)曲線的前兩個(gè)峰值B:B1的比值在4-10之間。

2、穩(wěn)態(tài)誤差趨近于0

3、系統(tǒng)響應(yīng)越快越好
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言

一、P參數(shù)選取

tip:在第一步牢記P產(chǎn)生響應(yīng)速度和力度,過(guò)小響應(yīng)慢,過(guò)大會(huì)產(chǎn)生振蕩,是I和D的基礎(chǔ)。

如果想自己調(diào)試嘗試可以打開matlab,運(yùn)行simulink,照著下面的圖進(jìn)行連接,如果想直接應(yīng)用可以直接往后看。

圖中的系統(tǒng)為一個(gè)PID控制二階系統(tǒng)。
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言
拿上面的系統(tǒng)進(jìn)行舉例,首先設(shè)定P=0.1,I=0,D=0觀察響應(yīng)??梢钥吹綀D像沒有超調(diào),說(shuō)明P產(chǎn)生的響應(yīng)速度和力度太小了,
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言
P=1,I=0,D=0觀察系統(tǒng)響應(yīng),超調(diào)量出現(xiàn)但是只有一個(gè)波形,同時(shí)也就意味著調(diào)節(jié)時(shí)間太慢了,繼續(xù)加大P
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言
P=10,I=0,D=0,此時(shí)調(diào)節(jié)時(shí)間顯著下降,可以看到此時(shí)的數(shù)量級(jí)已經(jīng)調(diào)整完成,也就是P參數(shù)只需要微調(diào)
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言
P=100,I=0,D=0,系統(tǒng)開始變得振蕩
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言
如果繼續(xù)加大P,系統(tǒng)會(huì)達(dá)到一個(gè)臨界值,產(chǎn)生等幅振蕩,最后開始發(fā)散。如下圖所示:
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言

二、I的調(diào)節(jié)

tip:I在有系統(tǒng)誤差和外力作用時(shí)消除偏差、提高精度,同時(shí)也會(huì)增加響應(yīng)速度,產(chǎn)生過(guò)沖,過(guò)大會(huì)產(chǎn)生振蕩。

I主要調(diào)節(jié)穩(wěn)態(tài)輸出,消除擾動(dòng)。由于系統(tǒng)沒有擾動(dòng)輸入因此看不到I對(duì)于消除擾動(dòng)的效果。P=10,I=10,D=0,此時(shí)I過(guò)大導(dǎo)致系統(tǒng)振蕩加劇。
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言

P=10,I=1,D=0,此時(shí)響應(yīng)波形基本符合預(yù)期。觀察穩(wěn)態(tài)輸出約為0.963左右。
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言
P=10,I=0.1,D=0,可以看到幾乎響應(yīng)波形沒有變化。說(shuō)明在沒有擾動(dòng)的情況下I只要不過(guò)大影響不大。但是穩(wěn)態(tài)輸出變化為0.916
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言
P=10,I=0,D=0,穩(wěn)態(tài)輸出變?yōu)?.91左右。
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言
最終我們可以通過(guò)I少量調(diào)節(jié)穩(wěn)態(tài)輸出的值,最終將穩(wěn)態(tài)誤差消除。關(guān)于I對(duì)波形影響的作用總結(jié)如下圖:
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言

三、D的調(diào)節(jié)

tip:D抑制過(guò)沖和振蕩,過(guò)小系統(tǒng)會(huì)過(guò)沖,過(guò)大會(huì)減慢響應(yīng)速度。D的另外一個(gè)作用是抵抗外界的突發(fā)干擾,阻止系統(tǒng)的突變。

P=10,I=0.1,D=10,可以看到將所有的沖擊都消除掉了。
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言
P=10,I=0.1,D=1,消除沖擊減弱,此時(shí)顯然衰減比不符合要求
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言
P=10,I=0.1,D=1,此時(shí)基本符合要求。
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言

四、總結(jié)

首先調(diào)節(jié)P的數(shù)量級(jí)達(dá)到一個(gè)只有2個(gè)左右明顯峰值的波形,再調(diào)節(jié)I找到不會(huì)波形振蕩也不會(huì)沒有超調(diào)的的區(qū)間,在區(qū)間內(nèi)找到一個(gè)I將穩(wěn)態(tài)誤差盡可能消除。最終使用D來(lái)控制衰減比和波形的峰值、超調(diào)量。最后根據(jù)要求的穩(wěn)態(tài)值、調(diào)節(jié)時(shí)間、超調(diào)量、上升時(shí)間、峰值時(shí)間等指標(biāo)進(jìn)行微調(diào)達(dá)到目標(biāo)。

最后可以總結(jié)成一個(gè)口訣

參數(shù)整定找最佳,從小到大順序查,
先是比例后積分,最后再把微分加,
曲線振蕩很頻繁,比例度盤要放大,
曲線漂浮繞大灣,比例度盤往小扳,
曲線偏離回復(fù)慢,積分時(shí)間往下降,
曲線波動(dòng)周期長(zhǎng),積分時(shí)間再加長(zhǎng),
曲線振蕩頻率快,先把微分降下來(lái),
動(dòng)差大來(lái)波動(dòng)慢,微分時(shí)間應(yīng)加長(zhǎng),
理想曲線兩個(gè)波,前高后低4比1,
一看二調(diào)多分析,調(diào)節(jié)質(zhì)量不會(huì)低 。

Chapter2 PID參數(shù)調(diào)整,個(gè)人經(jīng)驗(yàn)(配輸出曲線圖)

原文鏈接:https://blog.csdn.net/weixin_44407238/article/details/119255699

Chapter3 PID溫度控制參數(shù)整定方法

原文鏈接:https://blog.csdn.net/pengzhihui2012/article/details/50380780

最近做了一個(gè)溫度控制相關(guān)的項(xiàng)目,在此記錄一下,方便以后查找,同時(shí)也供大家參考,歡迎指正,所有數(shù)據(jù)均為實(shí)驗(yàn)數(shù)據(jù),絕對(duì)真實(shí)。

  1.  位置式PID控制公式原型:u(t) = kp * e(t) + ki * [e(1) + e(2) + ....+ e(t)] + kd * [e(t) - e(t-1)]
    
  2.  控制對(duì)象:加熱/制冷器(在2分鐘內(nèi)不能再加熱至冷之間切換)控制密封的腔體(空間體積大小15cm*20cm*65cm)溫度。
    
  3.  控制原理:利用MCU的輸出比較模塊(OCM)產(chǎn)生PWM波驅(qū)動(dòng)H橋電路(通過(guò)目標(biāo)溫度和環(huán)境溫度對(duì)比決定加熱或者制冷)。
    
  4.  PID參數(shù)整定
    

恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言
參數(shù)說(shuō)明:

Kc: 只采用比例環(huán)節(jié)控制條件下,控制系統(tǒng)的穩(wěn)態(tài)誤差盡量達(dá)到最小時(shí)的Kp值。

Pc: 只采用比例環(huán)節(jié)控制條件下,控制系統(tǒng)的震蕩周期。

Ti: 控制系統(tǒng)的積分時(shí)間。

Td: 控制系統(tǒng)的微分時(shí)間。

T: PID控制采樣計(jì)算周期。

Kp、Ki、Kd:被整定的參數(shù)。

1):獲取合適的Kc值,設(shè)置Ki,Kd為0。在當(dāng)前溫度進(jìn)入目標(biāo)溫度3.5°內(nèi)開始進(jìn)行PID控制,之前采用90%恒定功率加熱。
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言
圖一(Kc =5)

恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言
圖二(Kc =9)

恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言
圖三(Kc =20)

從上述的四組數(shù)據(jù)中可以看到,當(dāng)Kc=5時(shí),控制系統(tǒng)的穩(wěn)態(tài)誤差是最小的。在目標(biāo)范圍正負(fù)3°之間,選取Kc = 5.

2):計(jì)算Pc值。從上述的圖一(將.csv格式的數(shù)據(jù)文件在excel中轉(zhuǎn)換圖表,將鼠標(biāo)放在曲線上,會(huì)自動(dòng)顯示此點(diǎn)的坐標(biāo),如圖所示),取4個(gè)震蕩周期一共720個(gè)點(diǎn),得出一個(gè)震蕩周期為Pc=720*5/4= 900s。

3):根據(jù)個(gè)人需要采用哪種PID組合來(lái)計(jì)算Ti、Td、Kp、Ki、Kd。溫度控制是屬于滯后控制,而PID控制中的,微分項(xiàng)是具有超前調(diào)節(jié)的作用,因此必須引入;積分項(xiàng)對(duì)誤差的作用取決于時(shí)間的積分,隨著時(shí)間的增加,積分項(xiàng)會(huì)增大。這樣,即便誤差很小,積分項(xiàng)也會(huì)隨著時(shí)間的增加而加大,推動(dòng)控制器的輸出向穩(wěn)態(tài)誤差減小的方向變化,直到穩(wěn)態(tài)誤差等于零。我采用的是PID組合來(lái)控制。得出Ti=9000.5=450s。Td=9000.15=135s。

Kp=50.65=3.25;Ki= KpT/Ti=3.255/450=0.036;Kd= KpTd/T=3.25*135s /5=88。

4):采用PID控制溫度,無(wú)論高溫低溫,穩(wěn)態(tài)誤差均在正負(fù)0.5°范圍之內(nèi)。如下所示:
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言
一般根據(jù)模型計(jì)算的參數(shù)不一定是適合所有的控制系統(tǒng)(這里實(shí)驗(yàn)得到的最佳Kd值為120,而我們算出來(lái)的是88),根據(jù)特定的環(huán)境調(diào)節(jié)參數(shù)范圍,找到最優(yōu)參數(shù),因本系統(tǒng)是滯后系統(tǒng),微分項(xiàng)起主導(dǎo)作用,我暫時(shí)還只做了調(diào)整kd值的實(shí)驗(yàn),Ki一般反應(yīng)在系統(tǒng)達(dá)到穩(wěn)態(tài)的時(shí)候是否存在穩(wěn)定誤差,從實(shí)驗(yàn)結(jié)果得出,穩(wěn)態(tài)誤差幾乎可以忽略。

零下一度的目標(biāo)溫度,連續(xù)8小時(shí)的溫度控制數(shù)據(jù):
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言
附錄://PWM頻率為1Khz,定時(shí)器的計(jì)數(shù)周期為5000(mPID.MaxDuty = 5000*90%),PID返回值和上次的的定時(shí)器技術(shù)值決定本次的占空比。

INT32 PID_calculate(double CurTemp)

{

    INT32 RetValue;

    doubleresult_value;

 

    // Keep previouserror

    mPID.PrevError =mPID.Error;

 

    // calculatecurrent error

    mPID.Error =mPID.Target - CurTemp;

 

    // calculateintegral

    mPID.SumError +=mPID.Error;

 

    if(mPID.Kd >0.0001)

    {

        result_value =mPID.Kp * mPID.Error + mPID.SumError * mPID.Ki +

                mPID.Kd* (mPID.Error - mPID.PrevError);

    }

    else

    {

        result_value =mPID.Kp * mPID.Error + mPID.SumError * mPID.Ki;

    }

    RetValue =(INT32)result_value;

    return RetValue;

}

//Timer interrupt enable control flag, execute temperaturecontrol.

//

void TemperatureControl()

{

    INT32 ret = 0;

    if(mPID.type ==HEAT)

    {

        INT32 DutyValue= OC4RS;

        if(fabs(mPID.Current- mPID.Target) <= PIDControlStartPoint)

        {

           PIDControlStartPoint = 12;

            ret =PID_calculate(mPID.Current);

        }

        elseif(fabs(mPID.Current - mPID.Target) <= TempControlStartPoint)

        {

            OC4RS = INITPWMPERIOD16 * 50 / 100.0;

            ret = 0;

            return ;

        }

        else

        {

            ret = 0;

        }

       

        if( (DutyValue+ ret) > mPID.MaxDuty)

            OC4RS =mPID.MaxDuty;

        else if(DutyValue+ ret < mPID.MinDuty)

            OC4RS =mPID.MinDuty;

        else

           OC4RS +=ret;

    }

    else if(mPID.type== COOL)

    {

        INT32 DutyValue= OC3RS;

       if(fabs(mPID.Current - mPID.Target) <= PIDControlStartPoint)

        {

           PIDControlStartPoint = 12;

            ret =PID_calculate(mPID.Current);

            ret = -ret;// must be negative

        }

        elseif(fabs(mPID.Current - mPID.Target) <= TempControlStartPoint)

        {

           if(mPID.Target > 5.1)

               OC3RS =INITPWMPERIOD16 * 70 / 100.0;

            else

               OC3RS =INITPWMPERIOD16 * 78 / 100.0;

           

            ret = 0;

            return ;

        }

        else

        {

            ret = 0;

        }

       

        if( (DutyValue+ ret) > mPID.MaxDuty)

            OC3RS =mPID.MaxDuty;

        elseif(DutyValue + ret < mPID.MinDuty)

            OC3RS =mPID.MinDuty;

        else

           OC3RS +=ret;

    }

    else

    {}

}

Chapter4 simulink中的PID模塊的使用

原文鏈接:https://blog.csdn.net/wanrenqi/article/details/105278918

1、Simulink中PID模塊的介紹

首先,找到PID模塊,雙擊打開模塊的參數(shù)設(shè)置,如下:
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言
下面介紹幾種常用功能的參數(shù)設(shè)置。

1.1、控制器類型選擇

可以看到Controller:可以選擇PI、PD和PID控制等。

1.2、PID控制器格式

Form:有并行(默認(rèn))和理想型(串行),其傳函如下:

恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言

注意:傳函中的P、I、D系數(shù)就是我們需要整定的三個(gè)PID參數(shù)。

1.3、時(shí)域選擇

Time domain:連續(xù)時(shí)間和離散時(shí)間。
當(dāng)選擇離散時(shí)間時(shí),需要設(shè)置積分器和微分器中的濾波器的離散化方法,有向前歐拉,后向歐拉,
雙線性變換法,如下圖:

恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言

1.4、PID的飽和輸出限制

限制PID的輸出,還有去飽和積分的方法,如,反算法、鉗位法。如圖所示:
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言
當(dāng)然我們也可以自己搭一個(gè)PID控制器。

2 、自建PID模塊

下面搭建一個(gè)常用的離散型帶輸出飽和限制和積分飽和限制的PI控制器。如下:
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言
從這個(gè)離散的PI控制模塊中,可以看出積分環(huán)節(jié)是帶有限幅輸出的,當(dāng)然還要對(duì)這個(gè)積分模塊的限幅進(jìn)行設(shè)置勾選,如圖:
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言
為什么我們需要對(duì)積分環(huán)節(jié)進(jìn)行單獨(dú)的限制輸出??磦€(gè)例子:
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言
這個(gè)是帶有積分飽和限制的PI控制器調(diào)節(jié)出來(lái)的系統(tǒng)響應(yīng)。

恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言
這個(gè)是用simulink系統(tǒng)自帶的PI控制器調(diào)節(jié)出來(lái)的系統(tǒng)響應(yīng),兩個(gè)PI控制器的參數(shù)設(shè)置一樣。但是帶抗飽和積分的PI控制器調(diào)節(jié)出來(lái)的系統(tǒng)響應(yīng)效果明顯更好。

那么什么時(shí)候需要加積分環(huán)節(jié)限制輸出呢?當(dāng)系統(tǒng)在抗擾動(dòng)時(shí),需要一個(gè)大的Ki參數(shù)來(lái)快速消除穩(wěn)態(tài)誤差,而在開始從0到穩(wěn)態(tài)這個(gè)過(guò)程又會(huì)因?yàn)閗i太大而引起過(guò)大超調(diào)時(shí),這個(gè)時(shí)候就需要加積分過(guò)飽和限制。

Chapter5 simulink實(shí)現(xiàn)模糊PID控制

原文鏈接:https://blog.csdn.net/qq_36949278/article/details/105569943

模糊系統(tǒng)建立

在matlab命令行輸入fuzzy打開模糊系統(tǒng)設(shè)計(jì)器,設(shè)定輸入個(gè)數(shù)為2,范圍均為[-3,3],輸出個(gè)數(shù)為3,范圍均為[-1,1],模糊系統(tǒng)如下圖。根據(jù)相關(guān)文獻(xiàn)定義規(guī)則,將建立好的模糊文件命名為Fuzzy_PID并保存到本地文件中,用于下一步的導(dǎo)入。
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言

simulink實(shí)現(xiàn)

主程序設(shè)計(jì)
通過(guò)階躍函數(shù)模擬輸入信號(hào),將輸入信號(hào)分別傳入自帶PID模塊與編寫的模糊PID模塊,將兩個(gè)模塊的控制結(jié)果及階躍信號(hào)值通過(guò)scope函數(shù)進(jìn)行展示,整體程序框圖如下。
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言
PID模塊參數(shù)設(shè)置為P:0.05,I:0.01,D:0.005。

模糊PID模塊

將階躍信號(hào)傳入系統(tǒng),系統(tǒng)通過(guò)反饋計(jì)算誤差及誤差變化率,將誤差及誤差變化率乘以各自的量化因子,模糊系統(tǒng)的誤差及誤差變化率的值域均為[-3,3],假設(shè)實(shí)際的誤差范圍為[-8,8],誤差變化率范圍為[-16,16],則量化因子分別為0.375和0.1875。量化后的值通過(guò)saturation函數(shù)處理后傳入模糊系統(tǒng),模糊系統(tǒng)設(shè)定如下圖,其中Fuzzy_PID應(yīng)在命令行通過(guò)如下語(yǔ)句導(dǎo)入到系統(tǒng)中。

Fuzzy_PID = readfis(‘Fuzzy_PID’)

恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言
模糊系統(tǒng)設(shè)定輸出的范圍均為[-1,1],因此也應(yīng)根據(jù)相關(guān)經(jīng)驗(yàn)乘以量化因子,并與初始PID參數(shù),即P:0.05,I:0.01,D:0.005求和,處理后的參數(shù)傳入PID系統(tǒng)中,結(jié)合了模糊規(guī)則及PID控制的系統(tǒng)即為模糊PID控制系統(tǒng),系統(tǒng)的程序框圖如下。
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言

結(jié)果展示

運(yùn)行程序,點(diǎn)擊scope可查看運(yùn)行結(jié)果如下圖,可以看出模糊PID比單獨(dú)PID更早到達(dá)設(shè)定值,具有更好的響應(yīng)速度。
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言

Chapter6 飛思卡爾智能車----模糊PID算法通俗講

在講解模糊PID前,我們先要了解PID控制器的原理(本文主要介紹模糊PID的運(yùn)用,對(duì)PID控制器的原理不做詳細(xì)介紹)。PID控制器(比例-積分-微分控制器)是一個(gè)在工業(yè)控制應(yīng)用中常見的反饋回路部件,由比例單元P、積分單元I和微分單元D組成。PID控制的基礎(chǔ)是比例控制;積分控制可消除穩(wěn)態(tài)誤差,但可能增加超調(diào);微分控制可加快大慣性系統(tǒng)響應(yīng)速度以及減弱超調(diào)趨勢(shì)。

1.1傳統(tǒng)PID控制

恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言
傳統(tǒng)PID控制器自出現(xiàn)以來(lái),憑借其結(jié)構(gòu)簡(jiǎn)單、穩(wěn)定性好、工作可靠、調(diào)整方便等優(yōu)點(diǎn)成為工業(yè)控制主要技術(shù)。當(dāng)被控對(duì)象的結(jié)構(gòu)和參數(shù)具有一定的不確定性,無(wú)法對(duì)其建立精確的模型時(shí),采用PID控制技術(shù)尤為方便。PID控制原理簡(jiǎn)單、易于實(shí)現(xiàn),但是其參數(shù)整定異常麻煩。對(duì)于小車的速度控制系統(tǒng)而言,由于其為時(shí)變非線性系統(tǒng)不同時(shí)刻需要選用不同的PID參數(shù),采用傳統(tǒng)的PID控制器,很難使整個(gè)運(yùn)行過(guò)程具有較好的運(yùn)行效果。

1.2模糊PID控制

模糊PID控制,即利用模糊邏輯并根據(jù)一定的模糊規(guī)則對(duì)PID的參數(shù)進(jìn)行實(shí)時(shí)的優(yōu)化,以克服傳統(tǒng)PID參數(shù)無(wú)法實(shí)時(shí)調(diào)整PID參數(shù)的缺點(diǎn)。模糊PID控制包括模糊化,確定模糊規(guī)則,解模糊等組成部分。小車通過(guò)傳感器采集賽道信息,確定當(dāng)前距賽道中線的偏差E以及當(dāng)前偏差和上次偏差的變化ec,根據(jù)給定的模糊規(guī)則進(jìn)行模糊推理,最后對(duì)模糊參數(shù)進(jìn)行解模糊,輸出PID控制參數(shù)。
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言

2.1模糊化

模糊控制器主要由三個(gè)模塊組成:模糊化,模糊推理,清晰化。具體如下圖所示。而我們將一步步講解如何將模糊PID算法運(yùn)用到智能車上。(最好用筆一步步自己寫一遍?。。。?/p>

恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言

首先我們的智能車會(huì)采集到賽道的相關(guān)數(shù)據(jù),例如攝像頭車,其采集到的數(shù)據(jù)經(jīng)過(guò)算法處理之后會(huì)得到與中線的偏差E,以及當(dāng)前偏差和上次偏差的變化(差值)EC兩個(gè)值(即此算法為2維輸入,同理也可以是1維和3維,但2維更適合智能車)。例如此時(shí)車偏離中線的距離為150,而上一時(shí)刻偏離中線的距離為120,則E為150,EC為150 - 120 = 30。

其次我們要對(duì)這兩個(gè)值進(jìn)行模糊化。這里我們對(duì)E進(jìn)行舉例。攝像頭車采集回來(lái)的E是有范圍的,即與中線的偏差是在一個(gè)區(qū)間內(nèi)可行的。在這里我們假設(shè)該區(qū)間為-240到240,即小車偏離中線的最大距離為240,正負(fù)即為左右。再假設(shè)中線偏差變化率的可行區(qū)間為-40到+40。

接著我們要對(duì)這兩個(gè)值進(jìn)行模糊化。我現(xiàn)在將E的區(qū)間(-240 到 240)分成8個(gè)部分,那么他們分別為-240 ~ -180,-180 ~ -120 ,-120 ~ -60,-60 ~ 0,0 ~ 60,60 ~ 120,120 ~ 180,180 ~ 240。然后我們把-180,-120,-60,0,60,120,180分別用NB,NM,NS,ZO,PS,PM,PB表示(個(gè)人理解N為negative,P為positive,B為big,M為middle,S為small,ZO為zero)。例如,當(dāng)E = 170時(shí),此時(shí)的E屬于PM和PB之間,而此時(shí)的E也會(huì)對(duì)應(yīng)2(或1)個(gè)隸屬度。E隸屬于PM(120)的百分比為(180 - 170) / (180 - 120) = 1 / 6 ,而同理隸屬于PB(180)的百分比為(170 - 120) / (180 - 120) = 5 / 6 。意思就是120到180進(jìn)行線性分割了,E離PM和PB哪個(gè)更近,則隸屬于哪個(gè)就更大(當(dāng)輸出值E大于180(PB)時(shí),則隸屬度為1,隸屬度值為PB,即E完全隸屬于PB,同理當(dāng)E小于 - 180 (NB)時(shí)也一樣)。同理也可以對(duì)EC進(jìn)行模糊化。

2.2 模糊推理

對(duì)于采集回來(lái)的E和EC,我們可以推出它們各所占的隸屬度,此時(shí)我們可以根據(jù)模糊規(guī)則表去找出輸出值所對(duì)應(yīng)的隸屬度。
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言

我們假設(shè)為E的兩個(gè)隸屬度值為PM、PB,E屬于PM的隸屬度為a(a < 1),則屬于PB的隸屬度為(1 - a)。再假設(shè)EC的兩個(gè)隸屬度值為NB、NM,EC屬于NM的隸屬度為b,則屬于NB的隸屬度為(1 - b)。而在假設(shè)中,E屬于PM的隸屬度為a,EC屬于NB的隸屬度為( 1 - b ),則輸出值屬于ZO的隸屬度為a *( 1 - b )(看圖)。

恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言
同理我們可以得出,當(dāng)輸出值屬于ZO的另外兩個(gè)隸屬度為a * b, ( 1 - a ) * ( 1 - b) ,而輸出值屬于NS的隸屬度為( 1 - a ) * 1 - b。

   在這里我們先證明一個(gè)條件,將這四個(gè)隸屬度加起來(lái),剛好等于1。這是因?yàn)?
    (a + (1 - a)) * (b + (1 - b)) = a * b + ( 1 - a ) *  b  + a * ( 1 - b ) + ( 1 - a ) * ( 1 - b )   (下圖)

   即一個(gè)十字相乘的概念。這個(gè)等式說(shuō)明輸出值的隸屬度之和等于1(第三步求解的時(shí)候需要用到隸屬度之和)。

恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言
因此,我們知道了輸出值為ZO的隸屬度和為 a * b + a * ( 1 - b ) + ( 1 - a ) * ( 1 - b ) ,輸出值為NS的隸屬度為 ( 1 - a ) * b 。

2.3 清晰化

對(duì)于輸出值,我們同樣采用給予隸屬度的辦法。例如,我們把輸出值假設(shè)為[1000,1400](即舵機(jī)的擺角值范圍)的區(qū)間同樣劃分為八個(gè)部分,即7個(gè)隸屬值NB,NM,NS,ZO,PS,PM,PB。根據(jù)上一步所得出的結(jié)論,我們就可以用隸屬度乘以相應(yīng)的隸屬值算出輸出值的解,即 (a * b + a * ( 1 - b ) + ( 1 - a ) * ( 1 - b ) ) * ZO + ( 1 - a ) * b * NS。到此為止,整個(gè)模糊過(guò)程就結(jié)束了。

3 模糊PID

我們已經(jīng)知道了整個(gè)模糊的過(guò)程,但上述的過(guò)程還不夠完美。因?yàn)槲覀兊妮敵鲋抵挥幸粋€(gè)輸出,并沒有實(shí)現(xiàn)PID。因此我們可以先對(duì)E和EC進(jìn)行模糊化,然后分別對(duì)kp和ki和kd(PID的三個(gè)參數(shù))進(jìn)行求解,再套入公式。
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言
一般的我們也可以只用kp,kd,不用ki。而模糊規(guī)則表一般的論文已經(jīng)基本給出。因此帶入算法之后我們的難度也只是在于調(diào)節(jié)kp,kd,和適當(dāng)調(diào)節(jié)規(guī)則表。當(dāng)然調(diào)節(jié)的難度會(huì)大于普通的PID,因?yàn)檫€要定kp,kd的輸出范圍,調(diào)得不好可能效果并沒有普通的PID好。

4. 部分解釋

4.1對(duì)于部分論文所說(shuō)的重心法解模糊,其實(shí)就是上述方法。公式如下。
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言
式中μ(Zi) * Zi相當(dāng)于文章上面的(a * b + a * ( 1 - b ) + ( 1 - a ) * ( 1 - b ) ) * ZO + ( 1 - a ) * b * NS,即隸屬度乘以隸屬度值之和,而μ(Zi)之和就是輸出值的隸屬度之和,我們已經(jīng)證明它是等于1的。

Chapter7 模糊自適應(yīng)整定PID控制

原文鏈接

Chapter8 自適應(yīng)模糊PID(位置式)C語(yǔ)言實(shí)現(xiàn)

原文鏈接:https://blog.csdn.net/qq_30759585/article/details/122382396

一、自適應(yīng)模糊PID原理

自適應(yīng)模糊PID 控制系統(tǒng)結(jié)構(gòu)如圖所示??刂葡到y(tǒng)以偏差e和偏差變化率ec作為輸入量,利用模糊規(guī)則進(jìn)行模糊推理,輸出Δkp,Δki,Δkd。對(duì)PID三個(gè)參數(shù)進(jìn)行在線分析與調(diào)整,而自適應(yīng)模糊PID 控制器輸出u( t) 作用Mosfet開關(guān)管上,從而使sepic的輸出電壓達(dá)到要求的實(shí)時(shí)穩(wěn)定性。
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言

圖 4.2.1 模糊PID結(jié)構(gòu)圖
系統(tǒng)采用兩輸入一輸出的模糊控制器的形式,以密度偏差e 和偏差變化率ec 作為模糊控制器的輸入量,以PID 參數(shù)的修正量Δkp,Δki,Δkd分別為模糊控制器的輸出量。其變量、基本論域、模糊子集、模糊論域、量化因子、比例因子如表所示??紤]到論域覆蓋范圍和靈敏度,并且為了F28027計(jì)算簡(jiǎn)便,各模糊子集采用三角形隸屬函數(shù)。
表 4.2.1 ΔKp模糊規(guī)則表
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言

表4.2.2ΔKi模糊規(guī)則表
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言
表4.2.3ΔKd模糊規(guī)則表
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言
圖4.2.2 隸屬度函數(shù)
根據(jù)已經(jīng)確立的模糊控制規(guī)則和隸屬度函數(shù),采用Mamdani推理方法,面積重心法非模糊化。
恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言
總結(jié)一下,整個(gè)模糊自適應(yīng)PID的運(yùn)算工程如下所示:

恒溫控制pid matlab,嵌入式MCU,matlab,開發(fā)語(yǔ)言

二、代碼實(shí)現(xiàn)

該工程來(lái)自https://github.com/FlameAlpha/fuzzy-pid
某位國(guó)內(nèi)大佬編寫,頂禮膜拜。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-780333.html

fuzzy_pid.h

#ifndef _FUZZY_PID_H_
#define _FUZZY_PID_H_

#ifdef __cplusplus
extern "C" {
#endif


#include "math.h"
#include "stdlib.h"
#include "User_Component/mySci/printf.h"



#ifndef bool
#define bool char
#endif

#ifndef false
#define false (char)0
#endif

#ifndef true
#define true (char)1
#endif


// Fuzzy quantity fields
enum quantity_fields
{
    qf_small = 5,
    qf_middle = 7,
    qf_large = 8
};

#define qf_default qf_middle

struct fuzzy
{
    unsigned int input_num;
    unsigned int output_num;
    unsigned int fo_type;
    unsigned int *mf_type;
    int *mf_params;
    unsigned int df_type;
    int *rule_base;
    float *output;
};

struct PID
{
    float kp;
    float ki;
    float kd;

    float delta_kp_max;
    float delta_ki_max;
    float delta_kd_max;

    float delta_kp;
    float delta_ki;
    float delta_kd;

    float error_max;
    float delta_error_max;

    float last_error;
    float current_error;

    float intergral;
    float intergral_limit;

    float dead_zone;
    float feed_forward;

    float output;

    int output_min_value;
    int output_middle_value;
    int output_max_value;

    float linear_adaptive_kp;

    struct fuzzy *fuzzy_struct;
};

#define NB -3
#define NM -2
#define NS -1
#define ZO 0
#define PS 1
#define PM 2
#define PB 3



//#define fuzzy_pid_debug_print
//#define fuzzy_pid_dead_zone
//#define fuzzy_pid_integral_limit
//#define fuzzy_pid_rule_base_deep_copy

#define pid_params_count 7

#define torque_mode 1
#define position_mode 2
#define control_mode position_mode

#if control_mode == position_mode
#define max_error 5.0f
#define max_delta_error 5.0f
#else
#define max_error 12.0f
#define max_delta_error 12.0f
#endif

#define min_pwm_output 250
#define middle_pwm_output 1500
#define max_pwm_output 2900

struct fuzzy *fuzzy_init(unsigned int input_num, unsigned int output_num);

void fuzzy_params_init(struct fuzzy *fuzzy_struct, unsigned int mf_type, unsigned int fo_type, unsigned int df_type,
                       int mf_params[], int rule_base[][qf_default]);

void fuzzy_control(float e, float de, struct fuzzy *fuzzy_struct);



struct PID *raw_fuzzy_pid_init(float kp, float ki, float kd, float integral_limit, float dead_zone,
                               float feed_forward, float error_max, float delta_error_max, float delta_kp_max,
                               float delta_ki_max, float delta_kd_max, unsigned int mf_type, unsigned int fo_type,
                               unsigned int df_type, int *mf_params, int rule_base[][qf_default],
                               int output_min_value, int output_middle_value, int output_max_value);

//float params[pid_params_count] = {kp, ki, kd, integral_limit, dead_zonefeed_forward, linear_adaptive_kp};


struct PID *fuzzy_pid_init(float *params, float delta_k, unsigned int mf_type, unsigned int fo_type,
                           unsigned int df_type, int mf_params[], int rule_base[][qf_default]);


struct PID **
fuzzy_pid_vector_init(float params[][pid_params_count], float delta_k, unsigned int mf_type, unsigned int fo_type,
                      unsigned int df_type, int *mf_params, int rule_base[][qf_default],
                      unsigned int count);


float fuzzy_pid_control(float real, float idea, struct PID *pid);

int direct_control(int zero_value, int offset_value, bool direct);


int fuzzy_pid_motor_pwd_output(float real, float idea, bool direct, struct PID *pid);

void delete_pid(struct PID *pid);

void delete_pid_vector(struct PID **pid_vector, unsigned int count);

#ifdef __cplusplus
}
#endif

#endif //_FUZZY_PID_H_

fuzzy_pid.c

#include "User_Component/myPID/fuzzy_pid.h"

struct fuzzy *fuzzy_init(unsigned int input_num, unsigned int output_num)
{
    struct fuzzy *fuzzy_struct = (struct fuzzy *) malloc(sizeof(struct fuzzy));
    fuzzy_struct->input_num = input_num;
    fuzzy_struct->output_num = output_num;
    fuzzy_struct->mf_type = (unsigned int *) malloc((input_num + output_num) * sizeof(unsigned int));
#ifdef fuzzy_pid_rule_base_deep_copy
    fuzzy_struct->mf_params = (int *) malloc(4 * qf_default * sizeof(int));
    fuzzy_struct->rule_base = (int *) malloc(output_num * qf_default * qf_default * sizeof(int));
#endif
    fuzzy_struct->output = (float *) malloc(output_num * sizeof(float));
    return fuzzy_struct;
}

void delete_fuzzy(struct fuzzy *fuzzy_struct)
{
    free(fuzzy_struct->mf_type);
    free(fuzzy_struct->output);
    free(fuzzy_struct);
}

void fuzzy_params_init(struct fuzzy *fuzzy_struct, unsigned int mf_type, unsigned int fo_type, unsigned int df_type,
                       int mf_params[], int rule_base[][qf_default])
{
    for (unsigned int i = 0; i < fuzzy_struct->input_num + fuzzy_struct->output_num; ++i)
    {
        fuzzy_struct->mf_type[i] = mf_type;
    }

    for (unsigned int i = 0; i < fuzzy_struct->output_num; ++i)
    {
        fuzzy_struct->output[i] = 0;
    }

#ifdef fuzzy_pid_rule_base_deep_copy
    for (unsigned int j = 0; j < 4 * qf_default; ++j)
    {
        fuzzy_struct->mf_params[j] = mf_params[j];
    }

    for (unsigned int k = 0; k < fuzzy_struct->output_num * qf_default; ++k)
    {
        for (unsigned int i = 0; i < qf_default; ++i)
        {
            fuzzy_struct->rule_base[k * 7 + i] = rule_base[k][i];
        }
    }
#else
    fuzzy_struct->mf_params = mf_params;
    fuzzy_struct->rule_base = (int *) rule_base;
#endif

    fuzzy_struct->fo_type = fo_type;
    fuzzy_struct->df_type = df_type;
}

#define inverse(parameter) 1.0f/(float)parameter

// Gaussian membership function
float gaussmf(float x, float sigma, float c)
{
    return expf(-powf(((x - c) / sigma), 2.0f));
}

// Generalized bell-shaped membership function
float gbellmf(float x, float a, float b, float c)
{
    return inverse(1.0f + powf(fabsf((x - c) / a), 2.0f * b));
}

// Sigmoidal membership function
float sigmf(float x, float a, float c)
{
    return inverse(1.0f + expf(a * (c - x)));
}

// Trapezoidal membership function
float trapmf(float x, float a, float b, float c, float d)
{
    if (x >= a && x < b)
        return (x - a) / (b - a);
    else if (x >= b && x < c)
        return 1.0f;
    else if (x >= c && x <= d)
        return (d - x) / (d - c);
    else return 0.0f;
}

// Triangular membership function
float trimf(float x, float a, float b, float c)
{
    return trapmf(x, a, b, b, c);
}

// Z-shaped membership function
float zmf(float x, float a, float b)
{
    if (x <= a)
        return 1.0f;
    else if (x >= a && x <= (a + b) / 2.0f)
        return 1.0f - 2.0f * powf((x - a) / (b - a), 2.0f);
    else if (x >= (a + b) / 2.0f && x < b)
        return 2.0f * powf((x - b) / (b - a), 2.0f);
    else return 0;
}

// Membership function
float mf(float x, unsigned int mf_type, int *params)
{
    switch (mf_type)
    {
    case 0:
        return gaussmf(x, params[0], params[1]);
    case 1:
        return gbellmf(x, params[0], params[1], params[2]);
    case 2:
        return sigmf(x, params[0], params[2]);
    case 3:
        return trapmf(x, params[0], params[1], params[2], params[3]);
    case 5:
        return zmf(x, params[0], params[1]);
    default: // set triangular as default membership function
        return trimf(x, params[0], params[1], params[2]);
    }
}

// Union operator
float or (float a, float b, unsigned int type)
{
    if (type == 1)   // algebraic sum
    {
        return a + b - a * b;
    }
    else if (type == 2)     // bounded sum
    {
        return fminf(1, a + b);
    }
    else     // fuzzy union
    {
        return fmaxf(a, b);
    }
}

// Intersection operator
float and (float a, float b, unsigned int type)
{
    if (type == 1)   // algebraic product
    {
        return a * b;
    }
    else if (type == 2)     // bounded product
    {
        return fmaxf(0, a + b - 1);
    }
    else     // fuzzy intersection
    {
        return fminf(a, b);
    }
}

// Equilibrium operator
float equilibrium(float a, float b, float params)
{
    return powf(a * b, 1 - params) * powf(1 - (1 - a) * (1 - b), params);
}

// Fuzzy operator
float fo(float a, float b, unsigned int type)
{
    if (type < 3)
    {
        return and (a, b, type);
    }
    else if (type < 6)
    {
        return or (a, b, type - 3);
    }
    else
    {
        return equilibrium(a, b, 0.5f);
    }
}

// Mean of centers defuzzifier, only for two input multiple index
void moc(const float *joint_membership, const unsigned int *index, const unsigned int *count, struct fuzzy *fuzzy_struct)
{

    float denominator_count = 0;
//    float numerator_count[fuzzy_struct->output_num];
    //注意 TI的C99編譯器并不是完全支持動(dòng)態(tài)數(shù)組的特性,所以這里改變了一下(c89寫法)
    float *numerator_count= (float *)malloc(fuzzy_struct->output_num*sizeof(float));

    for (unsigned int l = 0; l < fuzzy_struct->output_num; ++l)
    {
        numerator_count[l] = 0;
    }

    for (int i = 0; i < count[0]; ++i)
    {
        for (int j = 0; j < count[1]; ++j)
        {
            denominator_count += joint_membership[i * count[1] + j];
        }
    }

    for (unsigned int k = 0; k < fuzzy_struct->output_num; ++k)
    {
        for (unsigned int i = 0; i < count[0]; ++i)
        {
            for (unsigned int j = 0; j < count[1]; ++j)
            {
                numerator_count[k] += joint_membership[i * count[1] + j] *
                                      fuzzy_struct->rule_base[k * qf_default * qf_default + index[i] * qf_default +
                                                index[count[0] + j]];
            }
        }
    }

#ifdef fuzzy_pid_debug_print
    printf("output:\n");
#endif
    for (unsigned int l = 0; l < fuzzy_struct->output_num; ++l)
    {
        fuzzy_struct->output[l] = numerator_count[l] / denominator_count;
#ifdef fuzzy_pid_debug_print
        printf("%f,%f,%f\n", numerator_count[l], denominator_count, fuzzy_struct->index[l]);
#endif
    }
    free(numerator_count);//有借有還再借不難
}

// Defuzzifier
void df(const float *joint_membership, const unsigned int *output, const unsigned int *count, struct fuzzy *fuzzy_struct,
        int df_type)
{
    if (df_type == 0)
        moc(joint_membership, output, count, fuzzy_struct);
    else
    {
        printf("Waring: No such of defuzzifier!\n");
        moc(joint_membership, output, count, fuzzy_struct);
    }
}

void fuzzy_control(float e, float de, struct fuzzy *fuzzy_struct)
{
    float membership[qf_default * 2]; // Store membership
    unsigned int index[qf_default * 2]; // Store the index of each membership
    unsigned int count[2] = {0, 0};

    {
        int j = 0;
        for (int i = 0; i < qf_default; ++i)
        {
            float temp = mf(e, fuzzy_struct->mf_type[0], fuzzy_struct->mf_params + 4 * i);
//            if (temp > 1e-4)
//            {
                membership[j] = temp;
                index[j++] = i;
//            }
        }

        count[0] = j;

        for (int i = 0; i < qf_default; ++i)
        {
            float temp = mf(de, fuzzy_struct->mf_type[1], fuzzy_struct->mf_params + 4 * i);
//            if (temp > 1e-4)
//            {
                membership[j] = temp;
                index[j++] = i;
//            }
        }

        count[1] = j - count[0];
    }

#ifdef fuzzy_pid_debug_print
    printf("membership:\n");
    for (unsigned int k = 0; k < j; ++k)
    {
        printf("%f\n", membership[k]);
    }

    printf("index:\n");
    for (unsigned int k = 0; k < j; ++k)
    {
        printf("%d\n", index[k]);
    }

    printf("count:\n");
    for (unsigned int k = 0; k < 2; ++k)
    {
        printf("%d\n", count[k]);
    }
#endif

    if (count[0] == 0 || count[1] == 0)
    {
        for (unsigned int l = 0; l < fuzzy_struct->output_num; ++l)
        {
            fuzzy_struct->output[l] = 0;
        }
        return;
    }

    // Joint membership
//注意 TI的C99編譯器并不是完全支持動(dòng)態(tài)數(shù)組的特性,所以這里改變了一下(c89寫法)
//    float joint_membership[count[0] * count[1]];
    float *joint_membership= (float *)malloc(count[0] * count[1]*sizeof(float));

    for (int i = 0; i < count[0]; ++i)
    {
        for (int j = 0; j < count[1]; ++j)
        {
            joint_membership[i * count[1] + j] = fo(membership[i], membership[count[0] + j], fuzzy_struct->fo_type);
        }
    }

    df(joint_membership, index, count, fuzzy_struct, 0);

    free(joint_membership);
}

struct PID *raw_fuzzy_pid_init(float kp, float ki, float kd, float integral_limit, float dead_zone,
                               float feed_forward, float error_max, float delta_error_max, float delta_kp_max,
                               float delta_ki_max, float delta_kd_max, unsigned int mf_type, unsigned int fo_type,
                               unsigned int df_type, int mf_params[], int rule_base[][qf_default],
                               int output_min_value, int output_middle_value, int output_max_value)
{
    struct PID *pid = (struct PID *) malloc(sizeof(struct PID));
    pid->kp = kp;
    pid->ki = ki;
    pid->kd = kd;

    pid->delta_kp_max = delta_kp_max;
    pid->delta_ki_max = delta_ki_max;
    pid->delta_kd_max = delta_kd_max;

    pid->delta_kp = 0;
    pid->delta_ki = 0;
    pid->delta_kd = 0;

    pid->error_max = error_max;
    pid->delta_error_max = delta_error_max;

    int output_count = 1;
    if (ki > 1e-4)
    {
        output_count += 1;
        if (kd > 1e-4)
            output_count += 1;
    }

    pid->fuzzy_struct = fuzzy_init(2, output_count);
    fuzzy_params_init(pid->fuzzy_struct, mf_type, fo_type, df_type, mf_params, rule_base);

    pid->last_error = 0;
    pid->current_error = 0;

    pid->intergral = 0;
    pid->intergral_limit = integral_limit;

    pid->dead_zone = dead_zone;
    pid->feed_forward = feed_forward;

    pid->output_max_value = output_max_value;
    pid->output_middle_value = output_middle_value;
    pid->output_min_value = output_min_value;

    return pid;
}

struct PID *fuzzy_pid_init(float *params, float delta_k, unsigned int mf_type, unsigned int fo_type,
                           unsigned int df_type, int mf_params[], int rule_base[][qf_default])
{
    return raw_fuzzy_pid_init(params[0], params[1], params[2], params[3], params[4], params[5], max_error,
                              max_delta_error, params[0] / delta_k, params[1] / delta_k, params[2] / delta_k, mf_type,
                              fo_type, df_type, mf_params,
                              rule_base, min_pwm_output, middle_pwm_output, max_pwm_output);
}


int round_user(float parameter)
{
    if ((int)(parameter * 10.0) % 10 >= 5)
        return parameter + 1;
    else
        return parameter;
}

int limit(int value, int max_limit, int min_limit)
{
    if (value > max_limit)
        return max_limit;
    if (value < min_limit)
        return min_limit;
    return value;
}
float limits(float value, float max_limit, float min_limit)
{
    if (value > max_limit)
        return max_limit;
    if (value < min_limit)
        return min_limit;
    return value;
}

float fuzzy_pid_control(float real, float idea, struct PID *pid)
{
    pid->last_error = pid->current_error;
    pid->current_error = idea - real;
    float delta_error = pid->current_error - pid->last_error;
    float uk;
#ifdef fuzzy_pid_dead_zone
    if (pid->current_error < pid->dead_zone && pid->current_error > -pid->dead_zone)
    {
        pid->current_error = 0;
    }
    else
    {
        if (pid->current_error > pid->dead_zone)
            pid->current_error = pid->current_error - pid->dead_zone;
        else
        {
            if (pid->current_error < -pid->dead_zone)
                pid->current_error = pid->current_error + pid->dead_zone;
        }
    }
#endif

    //關(guān)鍵代碼
    fuzzy_control(pid->current_error / pid->error_max * 3.0f, delta_error / pid->delta_error_max * 3.0f,
                  pid->fuzzy_struct);

//    pid->delta_kp = limits(pid->fuzzy_struct->output[0]/3.0f * pid->delta_kp_max, pid->delta_kp_max ,-pid->delta_kp_max);
    pid->delta_kp = limits(pid->fuzzy_struct->output[0], pid->delta_kp_max ,-pid->delta_kp_max);

    if (pid->fuzzy_struct->output_num >= 2)

//        pid->delta_ki = limits(pid->fuzzy_struct->output[1]/3.0f * pid->delta_ki_max, pid->delta_ki_max ,-pid->delta_ki_max);
        pid->delta_ki = limits(pid->fuzzy_struct->output[1], pid->delta_ki_max ,-pid->delta_ki_max);
    else pid->delta_ki = 0;

    if (pid->fuzzy_struct->output_num >= 3)

//        pid->delta_kd =limits(pid->fuzzy_struct->output[2]/3.0f * pid->delta_kd_max, pid->delta_kd_max ,-pid->delta_kd_max);
        pid->delta_kd =limits(pid->fuzzy_struct->output[2], pid->delta_kd_max ,-pid->delta_kd_max);

    else pid->delta_kd = 0;

#ifdef fuzzy_pid_debug_print
    printf("kp : %f, ki : %f, kd : %f\n", pid->kp + pid->delta_kp, pid->ki + pid->delta_ki, pid->kd + pid->delta_kd);
#endif

//    printf("kpkikd:%f,%f,%f,%f\n", pid->kp + pid->delta_kp, pid->ki + pid->delta_ki, pid->kd + pid->delta_kd,0.0);

    pid->intergral += (pid->ki + pid->delta_ki) * pid->current_error;
#ifdef fuzzy_pid_integral_limit
    if (pid->intergral > pid->intergral_limit)
        pid->intergral = pid->intergral_limit;
    else
    {
        if (pid->intergral < -pid->intergral_limit)
            pid->intergral = -pid->intergral_limit;
    }
#endif
    // //這里位置式PID算法

//    pid->output = (pid->kp + pid->delta_kp) * pid->current_error + pid->intergral +
//                  (pid->kd + pid->delta_kd) * (pid->current_error - pid->last_error);

    uk = (pid->kp + pid->delta_kp) * pid->current_error + pid->intergral +
                  (pid->kd + pid->delta_kd) * (pid->current_error - pid->last_error);

//    pid->output += pid->feed_forward * (float) idea;

    uk +=pid->feed_forward * (float) idea;//前饋環(huán)節(jié)

    pid->output = uk;

    //限幅
    if(pid->output<pid ->output_min_value)
        pid->output=pid ->output_min_value;
    else if (pid->output>pid ->output_max_value)
        pid->output=pid ->output_max_value;

    return pid->output;
}


void delete_pid(struct PID *pid)
{
    if (pid->fuzzy_struct != NULL)
    {
        delete_fuzzy(pid->fuzzy_struct);
    }
    free(pid);
}

void delete_pid_vector(struct PID **pid_vector, unsigned int count)
{
    for (unsigned int i = 0; i < count; ++i)
    {
        delete_pid(pid_vector[i]);
    }
    free(pid_vector);
}



struct PID **
fuzzy_pid_vector_init(float params[][pid_params_count], float delta_k, unsigned int mf_type, unsigned int fo_type,
                      unsigned int df_type, int *mf_params, int rule_base[][qf_default],
                      unsigned int count)
{
    struct PID **pid = (struct PID **) malloc(sizeof(struct PID *) * count);
    for (unsigned int i = 0; i < count; ++i)
    {
        pid[i] = fuzzy_pid_init(params[i], delta_k, mf_type, fo_type, df_type, mf_params, rule_base);
    }
    return pid;
}

int direct_control(int zero_value, int offset_value, bool direct)
{
    if (direct == true)
    {
        return zero_value + offset_value;
    }
    else
    {
        return zero_value - offset_value;
    }
}

int fuzzy_pid_motor_pwd_output(float real, float idea, bool direct, struct PID *pid)
{
    return limit(direct_control(pid->output_middle_value, fuzzy_pid_control(real, idea, pid), direct),
                 pid->output_max_value, pid->output_min_value);
}

調(diào)用方法

//全局變量定義方式
struct PID **pid_vector;

//main函數(shù)中初始化

     int rule_base[][qf_default] = {
            //delta kp rule base
            {PB, PB, PM, PM, PS, ZO, ZO},
            {PB, PB, PM, PS, PS, ZO, NS},
            {PM, PM, PM, PS, ZO, NS, NS},
            {PM, PM, PS, ZO, NS, NM, NM},
            {PS, PS, ZO, NS, NS, NM, NM},
            {PS, ZO, NS, NM, NM, NM, NB},
            {ZO, ZO, NM, NM, NM, NB, NB},
            //delta ki rule base
            {NB, NB, NM, NM, NS, ZO, ZO},
            {NB, NB, NM, NS, NS, ZO, ZO},
            {NB, NM, NS, NS, ZO, PS, PS},
            {NM, NM, NS, ZO, PS, PM, PM},
            {NM, NS, ZO, PS, PS, PM, PB},
            {ZO, ZO, PS, PS, PM, PB, PB},
            {ZO, ZO, PS, PM, PM, PB, PB},
            //delta kd rule base
            {PS, NS, NB, NB, NB, NM, PS},
            {PS, NS, NB, NM, NM, NS, ZO},
            {ZO, NS, NM, NM, NS, NS, ZO},
            {ZO, NS, NS, NS, NS, NS, ZO},
            {ZO, ZO, ZO, ZO, ZO, ZO, ZO},
            {PB, PS, PS, PS, PS, PS, PB},
            {PB, PM, PM, PM, PS, PS, PB}};

     // Default parameters of membership function
     int mf_params[4 * qf_default] = {-3, -3, -2, 0,
                                     -3, -2, -1, 0,
                                     -2, -1,  0, 0,
                                     -1,  0,  1, 0,
                                      0,  1,  2, 0,
                                      1,  2,  3, 0,
                                      2,  3,  3, 0};

     float fuzzy_pid_params[1][pid_params_count] = {{25.4597502f,  10.0053997f,    15.59500027f,    1800, 0, 0, 1}};

     struct PID **subpid_vector = fuzzy_pid_vector_init(fuzzy_pid_params, 4.0f, 4, 1, 0, mf_params, rule_base, 1);

     pid_vector=subpid_vector;
     
//中斷中調(diào)用
        control_uk = fuzzy_pid_control(Voltage_Real, pid.Ref, pid_vector[0]);
        if(control_uk<150)
            control_uk=150;
        else if (control_uk>2800)
            control_uk=2800;


到了這里,關(guān)于PID控制參數(shù)整定(調(diào)節(jié)方法)原理+圖示+MATLAB調(diào)試的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【Simulink】仿真_PID控制器調(diào)諧/調(diào)參/整定

    【Simulink】仿真_PID控制器調(diào)諧/調(diào)參/整定

    如何使用PID調(diào)諧器自動(dòng)調(diào)優(yōu)PID控制器塊? 模型下載: 轉(zhuǎn)速閉環(huán) PID調(diào)諧器提供了一種快速和廣泛適用的 single-loop PID通過(guò)Simulink控制塊的整定方法。通過(guò)這種方法,可以調(diào)優(yōu)PID控制器參數(shù),以實(shí)現(xiàn)具有所需響應(yīng)時(shí)間(response time)的魯棒(robust)設(shè)計(jì)。 PID調(diào)諧器的典型設(shè)計(jì)工作流程包括

    2024年02月05日
    瀏覽(23)
  • simulink學(xué)習(xí)筆記:基于模型的控制和pid整定

    simulink學(xué)習(xí)筆記:基于模型的控制和pid整定

    在學(xué)習(xí)的時(shí)候發(fā)現(xiàn)了一個(gè)很好的學(xué)習(xí)simulink的網(wǎng)站,打算來(lái)練練手:Introduction: Simulink Control,過(guò)程中會(huì)涉及到搭建動(dòng)力學(xué)模型和設(shè)計(jì)pid控制器(整定pid參數(shù))。該模型描述的是火車的兩節(jié)車廂,對(duì)前一節(jié)車廂施力,控制其速度按照跟隨指定的方波。我在我的資源里也把我建好

    2024年02月13日
    瀏覽(32)
  • 智能車攝像頭三輪PID參數(shù)調(diào)節(jié)

    智能車攝像頭三輪PID參數(shù)調(diào)節(jié)

    代碼已上傳CSDN,包含攝像頭和PID控制,設(shè)置了VIP可取這個(gè)小門檻,有興趣可以點(diǎn)擊下方鏈接自取哈。 https://download.csdn.net/download/weixin_53129688/87714428 https://download.csdn.net/download/weixin_53129688/87714428 ?

    2024年02月11日
    瀏覽(18)
  • STM32通過(guò)K210進(jìn)行PID巡線,使用藍(lán)牙模塊與電腦通信從而進(jìn)行P,I,D參數(shù)的調(diào)節(jié)

    目錄 一.前言部分(廢話部分) 二.K210色塊識(shí)別 1.必要知識(shí) 2.色塊識(shí)別 3.單片機(jī)的接收代碼 三.通過(guò)藍(lán)牙連接在電腦上實(shí)現(xiàn)PID的調(diào)參 我使用的是HAL庫(kù),如果你使用的是標(biāo)準(zhǔn)庫(kù)的話可以根據(jù)對(duì)應(yīng)標(biāo)準(zhǔn)庫(kù)的函數(shù)進(jìn)行更改即可 因?yàn)橹笆褂没叶葌鞲衅鬟M(jìn)行巡線,即使用上PID,最后的效果也

    2024年02月14日
    瀏覽(39)
  • PID循跡機(jī)器人及整定

    PID循跡機(jī)器人及整定

    如何對(duì)線路循跡機(jī)器人進(jìn)行編程 (robotresearchlab.com) PID調(diào)諧文章:http://robotresearchlab.com/2019/02/16/pid-line-follower-tuning/ 介紹人們選擇對(duì) 循跡機(jī)器人 進(jìn)行線路編程的兩種主要方式,并比較兩者。將詳細(xì)比較“簡(jiǎn)單循跡”和“PID 循跡”。在低速下,簡(jiǎn)單的循跡算法是完全可以接受的

    2024年02月15日
    瀏覽(53)
  • 掌上單片機(jī)實(shí)驗(yàn)室 – 實(shí)現(xiàn)PID自整定(11)

    掌上單片機(jī)實(shí)驗(yàn)室 – 實(shí)現(xiàn)PID自整定(11)

    一、背景 ????????上一篇實(shí)現(xiàn)了小車運(yùn)動(dòng)控制,在程序框架下,基于FreeRTOS編寫了驅(qū)動(dòng)任務(wù),包含電機(jī)控制、測(cè)速、PID調(diào)速、行走距離控制等和運(yùn)動(dòng)相關(guān)的功能。但 PID 調(diào)速只是完成了算法,并未真正實(shí)現(xiàn)調(diào)速,因?yàn)?PID 調(diào)速的核心是PID 參數(shù)的確定,即 整定 !而 整定是

    2023年04月08日
    瀏覽(33)
  • 【抗擾PID控制】干擾抑制PID控制器研究(Matlab代碼實(shí)現(xiàn))

    【抗擾PID控制】干擾抑制PID控制器研究(Matlab代碼實(shí)現(xiàn))

    ???????? 歡迎來(lái)到本博客 ???????? ??博主優(yōu)勢(shì): ?????? 博客內(nèi)容盡量做到思維縝密,邏輯清晰,為了方便讀者。 ?? 座右銘: 行百里者,半于九十。 ?????? 本文目錄如下: ?????? 目錄 ??1 概述 ??2 運(yùn)行結(jié)果 ??3?參考文獻(xiàn) ??4 Matlab代碼、Simulink、文

    2024年02月11日
    瀏覽(27)
  • matlab自動(dòng)控制狀態(tài)反饋 設(shè)計(jì)PID控制回路、保證控制效果

    1、內(nèi)容簡(jiǎn)介 略 36-可以交流、咨詢、答疑 2、內(nèi)容說(shuō)明 系統(tǒng)描述 已知系統(tǒng)的傳遞函數(shù)為 ?,以T=0.25s對(duì)系統(tǒng)采樣,要求: 1)設(shè)計(jì)PID控制回路,能夠?qū)崿F(xiàn)閉環(huán)系統(tǒng) ? ,穩(wěn)態(tài)誤差在斜坡輸入情況下為0。 理論分析 2.1 極點(diǎn)求解 已知閉環(huán)系統(tǒng)的性能要求為 ?, ,則系統(tǒng)的2個(gè)閉環(huán)極

    2024年01月23日
    瀏覽(25)
  • 用純C語(yǔ)言分別實(shí)現(xiàn)增量式與位置式的PID自整定算法

    1、對(duì)于增量式PID自整定算法,C語(yǔ)言代碼如下: 2、位置式PID控制是一種常用的控制方法,可以實(shí)現(xiàn)給定值與實(shí)際值之間的閉環(huán)控制。下面是使用C語(yǔ)言編寫的一個(gè)位置式PID自整定算法的代碼,包含詳細(xì)的注釋: 這個(gè)代碼實(shí)現(xiàn)了一個(gè)位置式PID自整定算法,它包括了兩個(gè)函數(shù) pr

    2024年02月15日
    瀏覽(16)
  • 【PID控制原理及其算法】

    【PID控制原理及其算法】

    本文以自己的學(xué)習(xí)過(guò)程總結(jié)而來(lái),將自己的經(jīng)驗(yàn)寫出來(lái)以供大家一起學(xué)習(xí),如有錯(cuò)誤請(qǐng)多指教 PID就是比例、積分、微分,PID算法可以說(shuō)是在自動(dòng)控制原理中比較經(jīng)典的一套算法,在現(xiàn)實(shí)生活中應(yīng)用比較廣泛。 常規(guī)的模擬 PID 控制系統(tǒng)原理框圖如下圖所示: 那么使用PID的目的

    2023年04月24日
    瀏覽(25)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包