一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - C/C++ - 詳解PID控制器原理

詳解PID控制器原理

2021-11-18 13:10Cayla夢云 C/C++

什么是 PID?它是一種在編程中使用的基本方法,如果正確調整,可以令人難以置信的有效和準確,PID代表比例積分微分,3個單獨的部分連接在一起,雖然有時你不需要三個都使用。例如,您可以改為有P控制,PI控制或PD控制

一、p - proportional 比例

想象一下一個全速行進的機器人,假設傳感器上的值為1000。 現在,由于它的速度和慣性,它可能會超過一點, 當編寫程序時,這可能是一個大麻煩,你想盡可能的準確。這個問題如圖所示(x軸上的綠色標記代表理想距離):
在理想世界中,您告訴機器人在哪里停止,它就停止在哪里

詳解PID控制器原理

但是,我們不是理想世界,如果我們突然告訴它停止,我們會有超調的問題,結果可能是這樣的:

詳解PID控制器原理

現在這個超調不會是一個問題,如果它的距離總是相同的。然而,有很多變量可以改變它超出的距離。 例如:

  • 電池電壓。 如果電池電量不足,則電機不能快速運行,會有較少的慣性, 在這種情況下,機器人超調變小
  • 如果機器人碰到一些東西,那么超調會變小
  • 如果某些東西將機器人朝向想要行進的方向推動,則超調將會 變得更大

所以你可以看到,超調不好。 所以p控制器控制速度, 所以p控制器控制速度平穩地,讓它在接近目標時減速,以縮小超調。 這就是為什么它被稱為比例控制器 – 輸出速度與要更改的值成比例,我們稱之為誤差(error)。

它是怎么做的?

你有一個很好的變量,叫做誤差(error)。這將是根據這個值對應的傳感器的讀書,它還在變化,就像前文提到的。例如,誤差可以是剩下要走的距離,剩下的要提升的高度,需要繼續加熱的溫度,等等。
為了計算誤差,我們只需減去傳感器給我們的讀數,這個讀書我們希望傳感器在完成后立即告訴我們。

誤差 =(目標值) - (傳感器讀數)

error = (target value) – (sensor reading)

因此,通過給出一些示例值來說明你想要的距離和它實際走過的距離,你會看到當它接近目標時,誤差會越來越小。

下面是幾個示例值:

目標值 當前傳感器讀數 誤差
1000 200 800
1000 400 600
1000 600 400
1000 800 200
1000 1000 0

我們可以用這個來控制應用程序的速度,如果你想用一個簡單的p控制器,沒有i和d項。為此,我們可以寫:

?
1
2
error = (target value) – (sensor reading);
speed = error;

另外,誤差值可能不太像我們想要的那樣。 這個值可能太高了,所以它超標了很多。 如果過調,它會嘗試和糾正過調(誤差將變成負數),所以你可以在在調試器或窗口觀察值和發生的情況,你將看到誤差在振蕩,超調然后過度校正。

或者,誤差值太小,但通常不會遇到這個問題。

對于任一問題,您可以更改誤差,以保持其比例因子,但你可以將錯誤乘以(或除)另一個數字,一個常數。 你可以稱之為任何你喜歡的名字,但它通常被稱為“kp” – 比例組件的常數。

?
1
2
3
4
5
6
kp = 0.5;
while (condition)
{
    error = (target value) – (sensor reading);
    speed = kp * error;
}

二、i - integral 積分

所以代碼的比例部分已經得到了,所以剩下的誤差是相當小的。比例太小,不能產生很大的差異。這就是積分。積分是之前的誤差的總和。所以當你的誤差非常小,積分起到作用,但它實際上如何工作的呢?

積分想要得到它,使其行進足夠快以縮小誤差,但不要太快,因為那樣可能會有超調的風險.它通過慢慢加速的方式去決定走多快,積分可以想這樣計算

積分=積分+誤差* 時間增量

integral = integral + error*dt

以上的設置是這樣的,所以“積分”的新值等于(等號左側)
先前的“積分”值,加上(誤差*時間增量)。忽略時間增量部分,我稍后再來討論這個問題。
積分增加的方式可以如下表中所示(使用誤差為2 做例子):

cycle # previous value for integral error new value for integral
0 0 2 2
1 2 2 4
2 4 2 6
3 6 2 8
4 8 2 10

粗體的數字(new value for integral積分的新值)在不斷增加.

那么我們如何將它添加到現有代碼中呢? 我們把它加起來。所以現在的速度是:

speed = (kp * error) + integral

那么現在加了積分偽代碼就變成這樣:

?
1
2
3
4
5
6
7
kp = 0.5;
while (condition)
{
    error = (target value) – (sensor reading);
    integral = integral + error;
    speed = kp*error + integral;
}

就像比例部分的代碼一樣,我們需要對積分加上一個常數項。我將使用0.2作為ki的一個例子值,盡管和k一樣,它只是一個數字我隨便舉例的。

?
1
2
3
4
5
6
7
8
kp = 0.5;
ki = 0.2;
while (condition)
{
    error = (target value) – (sensor reading);
    integral = integral + error;
    speed = kp*error + ki*integral;
}

前文告訴過你忽略時間增量,但我現在就解釋一下

integral = integral + error*dt

增量時間是必須的,因為循環不會總是花費同樣的時間完成每個周期,但是當每個周期花費同樣的時間時, dt可以合并到ki中,如果每個周期不花費同樣的時間,只需要將代碼用于每個周期,這樣你可以使用這個周期的時間作為你的增量時間

在這個教程里,我們將假設周期之間的時間總是相同的,因此dt將被并入ki。

這里是關于積分的幾個問題:

問題1:

當你的誤差幾近于0時,你的積分可能任然是一個可以保持速度足夠高保持錯誤的變化的值,方程只會自己達到0,如果它超過一個等于0 的誤差,那么負誤差就會減去現有的積分.所以,如果速度任然很高來保持誤差,我們將面臨一個問題,是吧?

對于這個題,有一個非常簡單的解決方案,那就是在誤差達到0時重新設置積分,如下所示

?
1
2
3
4
5
6
7
8
9
10
11
12
kp = 0.5;
ki = 0.2;
while (condition)
{
    error = (target value) – (sensor reading);
    integral = integral + error;
    if (error is 0)
    {
        integral = 0;
    }
    speed = kp*error + ki*integral;
}

問題2:

它被稱為integral wind-up.它可以從一個大誤差開始,一旦循環開始運行,積分將開始構建。所以,在這個積分需要的時候

使用時,它的值已經遠遠超過可用的值。有一些簡單的解決辦法, 我列舉三個解決方案:

解決方案#1 –限制積分所能達到的值。如果太高,為什么不給它加個限度?一個限制可以寫成如下:

?
1
2
3
4
if (integral is greater than or equal to the maximum value)
{
    integral = maximum value;
}

但是,如果積分太大,但它是負的形式(即,使速度相反)快速地,你需要重寫和上面一樣的,但是為負的版本的積分。

解決方案#2 - 限制積分允許建立的范圍。因此,如果錯誤對于積分來說太大了,我們可以禁用該范圍的積分。

?
1
2
3
4
if ( error is greater than useful for the integral )
{
    disable the integral (set the integral to 0);
}

但同樣,就像在解決方案1中一樣,你需要重寫相同的但要是積分的負值?;蛘撸绻木幊陶Z言支持使用一個絕對值的工具,您可以使用它使代碼更短,也許更簡單。
如何在代碼中實現絕對值的工具:

?
1
2
3
4
if ( abs(error) is greater than useful for the integral)
{
    disable the integral (set the integral to 0);
}

解決方案#3–限制積分允許積累的時間。這樣做有點復雜,但仍然可行。

對于本教程,我們將使用解決方案#2,因為它是最簡短的.
適合計算積分的范圍將為+/- 40,但只是一個隨機數。 下面代碼的完整版(如果剩下的話會被稱為“pi控制“[比例積分控制])將是這樣的:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
kp = 0.5;
ki = 0.2;
while (condition)
{
    error = (target value) – (sensor reading);
    integral = integral + error;
    if (error = 0)
    {
        integral = 0;
    }
    if ( abs(error) > 40)
    {
        integral = 0;
    }
    speed = kp*error + ki*integral;
}

三、d - derivative 導數

pid代碼的最后一點——導數!導數的工作就是預測未來的誤差價值,然后進行相應的速度行為。例如,如果它認為它會過調,會使它慢下來。

為了能夠預測下一個誤差,我們需要知道先前的誤差,然后找到這兩者的區別。
derivative = ( (current error) – (previous error) ) / dt

這個公式將發現當前誤差和之前的誤差之間的變化,然后我們可以通過將其添加到當前誤差中來預測下一個誤差。就像積分一樣,導數是由dt影響的,但是一個循環的周期話費的時間總是相同的,dt可以合并到kd。

這里有一個表,展示了未來可能發生的誤差的例子,通過導數計算的:

current error previous error next error (error + derivative)
50 55 45
20 30 10
2 3 1
5 15 -5

在我們的代碼中,導數是用上面的方程計算出來的,然后加到速度上(在這里也乘以kd來達到縮放的目的)。

我們需要創建一個新的整數,來命名先前的誤差(或者任何一個你喜歡的方式,只要它表示之前的誤差值),我們讓它更新自己在我們我們計算完導數后。我們可以用簡單的方式讓它更新,設置它的值為誤差值。

一下是完整的控制pid的偽代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
kp = 0.5;
ki = 0.2;
kd = 0.1;
while (condition)
{
    error = (target value) – (sensor reading);
    integral = integral + error;
    if (error = 0)
    {
        integral = 0;
    }
    if ( abs(error) > 40)
    {
        integral = 0;
    }
    derivative = error – previous_error;
    previous_error = error;
    speed = kp*error + ki*integral + kd*derivative;
}

四、調整常數項

這是費時又費力的工作。 有很多不同的方法來調整kp,ki和kd,我會盡我所能地解釋一下他們。 調整pid常數可以通過計算機程序完成,通過數學計算或通過手動調整, 我強烈建議您隨時查看誤差,速度等等,所以你可以看到距離到達目標還剩下多少需要改變。 使用調試器或類似的監視工具來檢查結果。

首先,了解調節pid控制器的規則很重要。 當每個常數增加時有什么改變如下表所示。 常數 術語在左側的列中,并且它們具有的效果在頂行列出。

效果如下:

  • rise time - 從起點到目標點所需的時間
  • overshoot - 改變的量太大了; 值比錯誤更大
  • settling time - 遇到變化時需要解決的時間
  • steady-state error - 均衡時的誤差
  • stability - 速度的“平滑度”

當每個常數增加時會發生什么?

constant: rise time: overshoot: settling steady-state stability: stability:
kp decrease increase small change decrease degrade
ki decrease increase increase decrease degrade
kd minor change decrease decrease no effect improve (if small enough)

手工調優:

手動調優是完全由你自己完成的——沒有涉及到數學,但有時也會有些低效。我個人使用手動調優方法,因為我可以溫和地增加每一個常量,并且知道什么時候會變得太高,而像ziegler - nichols方法這樣的數學方法,你永遠不會知道事情會怎樣發展,直到你嘗試之后。畢竟,在理論上,實踐和理論是一樣的,但在實踐中,它們不是。我調整常量的方式如下:

1.將kp、ki和kd設置為0。這將使他們暫時癱瘓。

2.增加kp直到誤差相當小,但是它仍然從開始到結束足夠快。

3.增加kd,直到任何超過你可能擁有的覆蓋。但是小心kd——太多會使它過度

4.增加ki,直到任何仍然存在的錯誤被消除。從一個非常小的數字開始,不要驚訝,如果它小到0.0001甚至更小。

5.使用調整常量的規則(在上一頁的表格中),您可以稍微更改一些常量,以使其工作到最佳性能。

數學方式

@todo 試過再補充

工具方式

@todo試過再補充

五、補充

while循環:

您可能已經注意到,在我的所有偽代碼示例中,我將主代碼放在while循環中。 這是因為誤差變化時需要重新計算誤差,積分,微分和速度。 例如,如果您將速度計算一次,但不再次計算,則無法重新刷新并相應地更改速度 - 它將以原始速度繼續運行!

循環對pid控制器至關重要 - 不要忘記添加一個!

那么,你如何讓它最終退出循環,每次當它完成了它的工作?

其中的一個常見的方法是,如果你知道它需要多長時間才能完成,你 可以將循環設置為指定的時間量(但顯然比它需要的稍微多一點),以確保它確實完成了循環。

另一種方法是檢測一旦誤差達到零,并且已經完成。如果你選擇這種方式,一定要注意確保它已經完全停止。舉個例子,如果你告訴它運行循環直到誤差達到0,如果有任何過度,沒什么能做的,因為它將會停止(過度,錯誤必須通過一個點(0)。所以,你可以得到循環多長時間內誤差保持在0。如果它只是在一個非常短的時間內處于0,那么很有可能它已經被過度并且需要重新調整自己。或者,如果它在一段較長時間內保持在0的值,那么說它已完全停止是安全的。

重新設置積分和之前的錯誤:

我前面已經講過了,有時你需要把積分重置為0,但是最后一次需要0的值。當您開始循環時,代碼會自動假設這個積分是0,之前的誤差是它應該的值。但是,如果循環已經運行,那么這個積分的值和之前的錯誤仍然是原來的值。

這可以通過在循環開始之前設置積分值和前一個錯誤的值來確定。

六、總結

proportional-你的誤差,在真實值和預期值之間。

? error = (target value) – (sensor reading)

integral – 先前誤差的運行和,用于在誤差很小的時候進行精細的調整。

? integral = integral + error*dt

derivative – 誤差的變化,用來預測下一個誤差可能是什么。

? derivative = ( (current error) – (previous error) ) / dt

the loop – 所有的計算都需要在循環中運行-不要忘記包含它!

將三個組件放在一起,再加上一些對kp、ki和kd的精確值,您將擁有一個非常一致和精確的控制器。

七、調試口訣

參數整定找最佳,從小到大順序查,先是比例后積分,最后再把微分加,
曲線振蕩很頻繁,比例度盤要放大,曲線漂浮繞大灣,比例度盤往小扳,
曲線偏離回復慢,積分時間往下降,曲線波動周期長,積分時間再加長,
曲線振蕩頻率快,先把微分降下來,動差大來波動慢,微分時間應加長,
理想曲線兩個波,前高后低4比1

八、具體方法

(1)確定比例系數kp

確定比例系數kp時,首先去掉pid的積分項和微分項,可以令ti=0、td=0,使之成為純比例調節。輸入設定為系統允許輸出最大值的60%~70%,比例系數kp由0開始逐漸增大,直至系統出現振蕩;再反過來,從此時的比例系數kp逐漸減小,直至系統振蕩消失。記錄此時的比例系數kp,設定pid的比例系數kp為當前值的60%~70%。

(2)確定積分時間常數ti

比例系數kp確定之后,設定一個較大的積分時間常數ti,然后逐漸減小ti,直至系統出現振蕩,然后再反過來,逐漸增大ti,直至系統振蕩消失。記錄此時的ti,設定pid的積分時間常數ti為當前值的150%~180%。

(3) 確定微分時間常數td

微分時間常數td一般不用設定,為0即可,此時pid調節轉換為pi調節。如果需要設定,則與確定kp的方法相同,取不振蕩時其值的30%。

(4) 系統空載、帶載聯調

對pid參數進行微調,直到滿足性能要求。

以上就是詳解pid控制器原理的詳細內容,更多關于pid控制器的資料請關注服務器之家其它相關文章!

原文鏈接:https://blog.csdn.net/xmy306538517/article/details/72771269

延伸 · 閱讀

精彩推薦
  • C/C++深入理解goto語句的替代實現方式分析

    深入理解goto語句的替代實現方式分析

    本篇文章是對goto語句的替代實現方式進行了詳細的分析介紹,需要的朋友參考下...

    C語言教程網7342020-12-03
  • C/C++C語言中炫酷的文件操作實例詳解

    C語言中炫酷的文件操作實例詳解

    內存中的數據都是暫時的,當程序結束時,它們都將丟失,為了永久性的保存大量的數據,C語言提供了對文件的操作,這篇文章主要給大家介紹了關于C語言中文件...

    針眼_6702022-01-24
  • C/C++c++ 單線程實現同時監聽多個端口

    c++ 單線程實現同時監聽多個端口

    這篇文章主要介紹了c++ 單線程實現同時監聽多個端口的方法,幫助大家更好的理解和學習使用c++,感興趣的朋友可以了解下...

    源之緣11542021-10-27
  • C/C++C++之重載 重定義與重寫用法詳解

    C++之重載 重定義與重寫用法詳解

    這篇文章主要介紹了C++之重載 重定義與重寫用法詳解,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下...

    青山的青6062022-01-04
  • C/C++學習C++編程的必備軟件

    學習C++編程的必備軟件

    本文給大家分享的是作者在學習使用C++進行編程的時候所用到的一些常用的軟件,這里推薦給大家...

    謝恩銘10102021-05-08
  • C/C++詳解c語言中的 strcpy和strncpy字符串函數使用

    詳解c語言中的 strcpy和strncpy字符串函數使用

    strcpy 和strcnpy函數是字符串復制函數。接下來通過本文給大家介紹c語言中的strcpy和strncpy字符串函數使用,感興趣的朋友跟隨小編要求看看吧...

    spring-go5642021-07-02
  • C/C++C語言實現電腦關機程序

    C語言實現電腦關機程序

    這篇文章主要為大家詳細介紹了C語言實現電腦關機程序,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    xiaocaidayong8482021-08-20
  • C/C++C/C++經典實例之模擬計算器示例代碼

    C/C++經典實例之模擬計算器示例代碼

    最近在看到的一個需求,本以為比較簡單,但花了不少時間,所以下面這篇文章主要給大家介紹了關于C/C++經典實例之模擬計算器的相關資料,文中通過示...

    jia150610152021-06-07
主站蜘蛛池模板: 欧美作爱福利免费观看视频 | 日韩国产欧美一区二区三区 | 无码欧美喷潮福利XXXX | 国产日韩高清一区二区三区 | 国产精品国产精品国产三级普 | 国内精品久久久久久久久 | 亚洲国产精品婷婷久久久久 | 盲井在线 | 亚洲日本视频在线观看 | 97影院伦理 | 日韩精品成人免费观看 | 91久久综合 | 久久久亚洲国产精品主播 | 日本道在线播放 | 涩涩国产精品福利在线观看 | 91色porny| 日日碰碰 | 国产麻豆剧果冻传媒观看免费视频 | 亚洲国产天堂 | 黑白配高清hd在线视频 | 亚洲黄色免费在线观看 | 国产精品制服丝袜白丝www | 草草影院在线 | 女黑人尺寸bbb | 久久精品视频91 | 国模一区二区三区视频一 | 成人综合网站 | 久久亚洲精品中文字幕60分钟 | 欧美日韩高清观看一区二区 | 蜜桃免费 | 四虎影院最新网址 | 啪哆哆| 精品视频在线播放 | 好湿好紧太硬了我太爽了网站 | 好大好猛好爽好深视频免费 | 亚洲欧美激情日韩在线 | 99在线免费播放 | 日本xx高清视频免费观看 | 午夜熟女插插XX免费视频 | 精品国产品国语在线不卡丶 | 秘书在办公室疯狂被hd |