2008年5月4日 星期日

PID Speed Control

https://4rdp.blogspot.com/2008/05/pid-speed-control.html


LEGO MINDSTORMS NXT 的控制器能夠同時驅動三組伺服馬達,
伺服馬達與一般馬達主要差異在它多了回授系統。
LEGO Servo Motor 能夠回報馬達轉動角度訊息給控制器,
並且可以像步進馬達一樣控制旋轉角度,解析達 1度角,這真是不錯的設計!

本文先討論馬達轉速控制
NXT 玩家們控制馬達時,應該會發現用 NXT 控制馬達的角度或轉數蠻容易,所以用 NXT 精確馬達定位,不成問題
但是想控制馬達定速運轉,這不是一件容易的事
因為 NXT 使用不同電池或者換個地點 (負載狀況不同),相同的程式產出的結果會不同。


馬達轉速慣用單位為 rpm (Revolution(s) Per Minute,每分鐘轉數),NXT馬達轉速不高,Power = 100,全速運轉時約 133 rpm。
使用 NXC (BricxCC) 程式,可以每秒計數 NXT 馬達轉角,所以 133 rpm = 133 x 360° / 60 seconds = 798° / second。

我使用六顆一般充電電池,充飽電後全速可達 850° / second,但是快沒電時,全速運轉約 750° / second。

現在介紹 PID Control,屬於系統控制的領域,這方法可消弭一些外界變異或干擾影響,
讓系統控制可預測,參數設定得好,就可以又快又穩又準

PID (Proportional Integrative Derivative)

E(t) = R(t) – Y(t) // a set point R(t) to reach, measuring value Y(t)

P(t) = E(t)
I(t) = I(t-1) + E(t)
D(t) = E(t) – E(t-1)

U(t) = Kp*P(t) + Ki*I(t) + Kd*D(t)

以上為一般方程式,適用於任何可控制回授系統,
而下列兩式為 NXT 馬達特有方程式。

Power = U(t) / 8
Y(t) = U(t-2)

U(t) 為系統估算出的轉速,依據實驗數據所知,Power = 100 時,全速轉速約為 800° / second,因此 Power = U(t) / 8。
而 Y(t) = U(t-2),是因為 NXT馬達轉速回應有一秒延遲的現象 (1 second deadtime)。

有興趣的朋友試試這個程式,只用馬達 A 不需組裝:

 
#include "NXCDefs.h"
 
#define Kp 40
#define Ki 40
#define Kd 0
 
task main(){
long power;
long set_speed,speed;
long e0,e1;
long x0,x1;
long P,I,D,U;
long time;
string str;
 
ResetAllTachoCounts(OUT_A);
x0 = 0;
e0 = 0;
power = 0;
set_speed = 500;   // degree/second
I = 0;
time = 0;
 
while (1) {
OnFwdRegEx(OUT_A, power, OUT_REGMODE_IDLE, RESET_NONE);
 
x1 = MotorRotationCount(OUT_A);
Wait(1000);                  // wait 1 second
speed = x1 - x0;
x0 = x1;
 
e1 = set_speed - speed;
 
P = e1;
I = I + e1;
D = e1 - e0;
e0 = e1;
 
U = (Kp*P + Ki*I + Kd*D) / 100;
power = U / 8;
if (power>100)
power = 100;
else if (power<-100)                  
power = -100;            
 
str = NumToStr(speed);   
str = StrCat("Speed = ",str);   
TextOut(0, LCD_LINE1, str, true);     
 
str = NumToStr(time);   
str = StrCat("t = ",str);   
TextOut(0, LCD_LINE3, str, false);   
time += 1;   
str = NumToStr(P);   
str = StrCat("P = ",str);   
TextOut(0, LCD_LINE4, str, false);   
str = NumToStr(I);   
str = StrCat("I = ",str);   
TextOut(0, LCD_LINE5, str, false);   
str = NumToStr(D);   
str = StrCat("D = ",str);   
TextOut(0, LCD_LINE6, str, false);     
 
str = NumToStr(power);   
str = StrCat("Power = ",str);   
TextOut(0, LCD_LINE8, str, false);
}
}
 

PS.為了讓程式碼排版正常,程式中使用了全形空格當空行以及全形<>,編譯前請留意修改。

另外附上 線上試算表可以模擬試算,電機系學自動控制的同學,可以藉由這個實驗把 PID 搞懂。
最後提醒各位,網路上有許多 PID control 文章,大家對一般方程式的定義有些許不同,
所以Kp、Ki、Kd數值沒搞清楚定義前不要亂用一通,通常使用 0 <= K <= 2。 NXT 馬達反應速度並不快,因此 Kd = 0 就可以了。
本程式的 K值很大,是因為 NXC 無法使用小數,所以 K = 40,代表 K = 40 / 100 = 0.4。

後記補充,另一篇 Apply PID to control speed and angle 有比較速度與角度控制差異。

98 則留言:

  1. 您好,
    我是個機械系畢業也正在從事機械設計相關工作。
    如你所說,,創造自己的不可替代性就是維持生存的要件...........
    有幸瀏覽您的Blog,讓我深刻體會持續維持學習的習慣的重要性!!
    Thanks.

    John.

    回覆刪除
  2. 很高興能在網路上認識您,由於近期工作忙碌,也沒有每天上網,無法及時回應您的留言,敬請見諒。

    機械也是現代工業重要的應用學科,凡舉材料、硬度、結構、重量、溫度、光澤、應變等等,都是產品設計必須考量的。

    日後有機會向您請教相關知識,也感謝您對研發養成所的支持。

    Thanks.

    回覆刪除
  3. 您好:
    我是雲科大機械系的學生,最近我也是在用pid來控制轉速,看到你的文章真的讓我受益良多,謝謝!!
    不過小弟不才,想冒昧問一下問題,我現在是用來控制氣動馬達,並且使用encoder抓取轉速的訊號,程式上面我是用labview。我想請問一下:Power = U(t) / 8,我在這裡是用氣壓氣壓元件的比例閥來調整開度大小,請問一下跟原本輸出的倍率要怎麼調整會比較好呢??謝謝!!

    回覆刪除
  4. Hubert 您好,

    關於您的問題,因為有些細節不是很清楚,只能粗略答覆。

    首先,您應該先確認控制系統的氣壓馬達是轉速控制還是角度控制,轉速控制必須一直通電維持恆定速度,而角度控制則是達到定角後就不通電。我不清楚這個比例閥開度大小與馬達控制是上述那一類?如果屬於角度控制,您需要參考本部落格另一篇,PID角度控制專文。

    現在假設是轉速控制形式,當轉速U(t)=N,比例閥可達到100%全開,那麼 Power = U(t) / K , K = N / 100% ,本文中 K = 8 就是這樣得來的。

    回覆刪除
  5. 薛老師,

    謝謝您意見回饋,PID 控制是目前科技最順暢的控制方法,也就是控制不會有不連續的轉折情形,值得大家一起研究。

    回覆刪除
  6. 請問在NXC中讀取角度的Function:MotorRotationCount()、MotorTachoCount()..........都可以讀取馬達角度值...請問這兩者有何差異

    再請問當我下達 RotateMotor(OUT_A,80,320) 指令後,再讀取馬達角度MotorTachoCount(OUT_A)時,往往不相同也就是馬達沒有精確的的停在320度.....請問要如何解決才能準確停在320度

    謝謝

    回覆刪除
  7. Rik 您好,

    MotorTachoCount()會因每次 RotateMotor 指令執行,而重置清除馬達角度值,但是 MotorRotationCount()不會,因此 MotorRotationCount()會一直累積馬達角度值,直到執行 ResetAllTachoCounts(OUT_A)才清除。

    RotateMotor 指令,為 open loop 控制指令,它無法精確控制角度,會因電池電力大小或負載情形,造成角度有誤差。你可以嘗試 RotateMotorPID(OUT_A,80,320,P,I,D),P=50,I=50,D=50,這裡 PID 數值不是最佳值,您需要自行調整數值,PID控制後,才能修正回設定點。

    如果還有問題,歡迎您再留言。

    回覆刪除
  8. 請問,我現在也在做馬達的速度控制,轉速大約也落在130rpm左右,其實我一直有個問題是,我的速度會經由一個轉換式後得到一個V值。
    但V值如果去除半徑就會等於角速度,這種除法除出來的值一定是浮點數,處理上比較麻煩,回授ENCODER 是給我PULSE數多少時間內取到的PUSLE數,問題就是在這,一般會去把度全轉成PULSE數?還是把PULSE數轉成速度去回授,但因為轉換應該都會變成有小數點的情形,第一次做也不太清楚,正常在這部分會怎麼處理?

    回覆刪除
  9. Wallace 您好,

    我猜想您的問題可能是因為你的控制系統無法使用浮點數。你可能想在螢幕顯示角速度,可是變數又無法保留小數值,以致於轉速難以穩定控制或是總是有個偏差。

    ENCODER 在轉速控制中是很重要的組件,對轉速精確度具有重大影響性,本篇例子是用 PULSE 控制轉速(NXT 馬達一轉360 度 可產生 360 pulses),PID 程式可以控制在 +/- 1 pulse 誤差範圍內,但是輸出 power 卻只能 0 ~ 100 設定,因此馬達轉速就難以定速不動。像這樣的馬達,如果用 rpm 控制,然後變數又無法儲存小數,那麼控制誤差會達到 +/- 6 pulses。

    回覆刪除
  10. 其實pulse數取回來要處理比較簡單,不管是轉成rpm或pulse/min,但因為初始參考的速度V是經由運動學算來的,所以假設要算成RPM,這一個轉換就勢必要遇到小數點了,又我的CPR不是很高,所以小數點的部分是有點麻煩。

    WINDUP的問題是不是說像我是用10bit的值去當我的duty cycle,所以等於我的u>1023時要等於u=1023,但是處理這步時,我看書上寫了一句要更新積分量為臨界飽合,這句不災要不要寫在程式裡。

    回覆刪除
  11. Wallace 您好,

    看來你的問題是知道初始速度,需要換算成rpm或是pulse,但是不知道何者比較好?你何不設計三種版本程式比較看看。關於小數處理有個變通方式,就是數值多乘100可以保留兩位小數,參考本文範例。

    10 bits輸出控制,最大值為1023,系統設計時應保留一些餘裕,可以把1000當做正常使用的最大輸出,windup方法是避免系統超出極限控制(〉1023),你也可以試試看寫兩個程式比較有無windup的差異。

    回覆刪除
  12. bridan非常成謝您的回覆,我昨天有做了,我的程式依照您提供的寫法去寫,例如rpm=100的地方,可能因為讀取的pulse差一兩個後的u在這裡的輸出跳動會有點大大,但這應該是合理的,但是我明顯看到馬達的抖動很大。
    剛看您的回覆,其實我沒有想到這個問題就是可以把1023限在1000就好了。我也是先算U值,在把U值的比例分配到1023,我的例子是U的範圍是0~15,U經PID計算後,可能一開始跳的很高超過15了,就U=15,後面再一行是
    S=(U-KP*err-KD*e_d),S是累積誤差量,看書上的理論是要更新誤差量,但我只要大於15後等於全速在開,他就不會收斂了,所以覺得很奇怪。
    另外一個小問題KP通常不是大於1嗎,為什麼您的設定會0.4呢?我也疑惑的是馬達在書上的參數理論上是二階系統,當然可能因為忽略某些項變為一階系統,但一階系統好像就不用有overshoot的現象了。這邊其實是我看書時一直卡住的地方

    回覆刪除
  13. 另外想請教一下,速度控制能單用P,或PD的控制嗎?因為這兩個沒有誤差累積量,我一直想不到單用這兩個的方法

    回覆刪除
  14. Wallace 您好,

    單獨使用P控制,它會是OPEN LOOP 控制,缺乏I控制項,遇到加載會產生控制偏移情形,也就是永遠無法達到控制速度。

    回覆刪除
  15. Wallace您好,

    發現遺漏你的長篇問題在此補充,為了徹底了解你的糸統狀況,請你說明下列參數值:
    目前你設定的PID係數?
    360度有多少pulse?
    你是以rpm還是用pulse當控制基準?
    power範圍是0~1023嗎?
    U(t)=Kp*P(t)+Ki*I(t)+Kd*D(t) 數值範圍0~15?

    有這些參數值就可以明瞭你的系統一些奇怪現象,比如輸出跳動有點大。Kp〉1代表系統輸出就給予很強的出力,相對的就要搭配負值的Ki與Kd否則速度無法控制。使用Kp=0.4是讓系統爬升速度放慢一點,避免overshoot。當你省略Kd系統就變成一階,這與PID控制的微分方程式有關,但是一階微分方程並不代表就沒有overshoot,有興趣請詳閱大學的工程數學。

    回覆刪除
  16. dear bridan:
    您好,其實我現有用是dspic在寫,我現在想做一個直流馬達的速度控制器,我是能用浮點數的,但是後面我要移值到8bit的pic上去寫,所以浮點的計算對我的pic算是一個影響。

    我的馬達一圈只有980pulse,所以我的取樣方法是一段時間內產生多少pulse數,來計算,又因為pulse數量不夠多,我現在是採用20ms取樣一次,但是在直接穩定電源下測試轉速時就會因為差一到兩個pulse,讓算出來的rpm會有一點誤差,我的輸入會一個速度,我現在的寫法比較直覺,就是轉到角速度上去做,V(mm/s)=rw,
    r=50.8mm,用w當成我的輸入,V值的最大上限等於馬達的最大上限為745mm/s,所以w的範圍約等於0~14.66。

    我的pi loop{
    ep=err; //kp誤差量(kp=1.3)
    Sum=Sum+err; //ki誤差量(ki=0.2)
    u=(KP*en+KI*Sum);
    }
    因為馬達為12V,用PWM控制,PWM的DUTY CYCLE的解析度為1023

    if (u>14.6){u = 14.6;}
    else if(u<1){u=1;}
    //這邊你們應該是寫成if(u<-14.6){u=-14.6}但我不了解這邊u=0不就等於沒輸出了嗎?

    最後在把(u/14.6)*1023=pwm輸出的duty cyele,現在這樣的寫法如果u大於14.6我的馬達就全速運轉了,不會修正回來,大概目前是這樣寫的,但感覺怪怪的

    回覆刪除
  17. Wallace 您好,

    由你提供的資料,現在比較清楚整個系統概況,首先需要檢討的是 20ms 取樣時間,根據數據資料可以推得下列關係:
    745 mm/sec = 14.66 radian/sec = 840 degree/sec = 140 rpm = 2286.66 pulse/sec

    最快轉速時,只能在 20ms 週期內最多取得 45 pulse,2286.66/50 = 45.73 pulse。每20ms +/- 1 pulse,代表 +/-50 pulse/sec = 3.06 rpm = 18.367 degree/sec = 0.32 radian/sec = 16.29 mm/sec,這樣轉速很不穩定。如果你沒有每 20ms 必須修正轉速一次的需求,建議你改成每秒修正轉速一次,可以獲得更穩定的速度,降低這 2% 誤差。

    你選擇以 radian/sec 為 U(t)控制單位,因此會有一個輸出與輸入關係式
    Max power = 1023 PWM = 14.66 * 69.78
    PWM = (U/14.66)*1023 公式是對的。
    為了獲取平順的控制,14.66 radian/sec 應該計算到小數第二位,這樣每一個 PWM 約可控制 0.01 radian/sec。
    另外測試 PWM 1023 及最大負載時的轉速,假設它為 14 radian/sec,表示只能用到 PWM 976.94 (975 以下數值比較安全,也許還會受到溫度環境影響),當你的最大轉速輸出。

    正常U 是不會有負值,除非你定義負值為反轉控制,當 U = 0 確實是不輸出。

    有些系統是不允許任何 overshoot 或是過大 overshoot,如果你的系統有此限制,那麼請將Kp<1,以上是我的建議提供你參考。

    回覆刪除
  18. dear bridan:
    你算的跟我的推的都差不多,我現在只有幾個問題就是windup在程式裡要怎麼寫,因為之前您有提到積分的limit的問題,那裡我不是很懂,然後我現在只是單純做一個馬達的控制器,等於說以後我只要給他速度,它自己就會追值,但馬達的追值的反應速度到底要多快,或許我現在的問題是我的馬達編碼器解析不夠高,那在做這種馬達控制時到底需不需要OVERSHOOT這個問題我也不太清楚,根據書上定義有沒有OVERSHOOT應該是階數有關等於跟我的輸入也有關係,因為我並沒有馬達的參數,我只能用TUNE的,所以我現在單純確定WINDUP這段寫入程式,整個PID的LOOP是不是這樣寫的確認,我自己再慢慢試了,對了我是在做機器人的移動平台啦,這個等於是一個LOW LEVEL CONTROL,主平台輸入什麼速度,他就反應什麼速度,但是問題就是我剛剛說的馬達的反應拉長成一秒內反應完會很慢嗎?我之前是用50ms做取樣,誤差會更小更穩定。
    非常感謝您的解答,第一次做問題總是特別多,萬分感謝

    回覆刪除
  19. dear bridan:

    我繼續做實驗有個小問題,我雖然有
    if(u>14.66)
    u=14.66;的判斷
    但是我今天的輸入目標指令為10rad/s=95rpm左右,我在那試kp,ki,maybe kp and ki調的比較大時,我的u>14.66,但它就維持在14.66就修正不回來了,是不是程式少加了什麼式子?

    回覆刪除
  20. Wallace 您好,

    Windup的判斷式,並非使用 if(u>14.66) u=14.66;
    而是 if (I(t)〉limit) I(t) = limit;
    至於 limit = ? 與 Ki 大小有關, 假設 Ki = 0.4, limit 大約為 14.66 / 0.4 = 36
    用 u 是無法修正回來的

    回覆刪除
    回覆
    1. 您好
      請問這裡的l(t)是什麼呢?

      刪除
  21. Wallace 您好,

    取樣時間與你的机器人移動平台剎車距離有關,假設想在全速行進中於100mm內停車,100ms取樣時間應該足夠,745 X 0.1 = 74.5mm,以現有的馬達編碼器解析度應該足夠,如果取樣時間改為0.1sec,那PWM只要8bits就可以了,2286.66 pulse x 0.1 = 228.66。如果你這机器人移動平台是載人的,那過大overshoot會讓人不舒服,一坐上車就立即往前衝。

    PID控制很多東西是實務經驗加上自己思考,許多東西書本是不會有的,一切靠自己定義與想像,最後提醒你,改變取樣時間所有參數都要全部重調,祝你順利成功。

    回覆刪除
  22. 不好意思,
    才看一小段就卡住了.
    Y(t) = U(t-2)
    可是Y(t)不是量測得來的數字嗎?
    U(t)不是經過計算得來的數字嗎?
    (U(t) = Kp*P(t) + Ki*I(t) + Kd*D(t))
    為什麼兩者可以相等,
    我好困惑,想不懂,
    盼望您給予指點!謝謝!!

    回覆刪除
  23. Flora 您好,

    剛學習 PID 控制會有這些困惑很正常,個人也是歷經許久才慢慢頓悟其中道理,請先了解下列三者的定義:
    R(t) 設定的轉速
    Y(t) 透過 encoder 量測的回授轉速
    U(t) PID 控制估算出來的轉速

    你可以把 U(t) 當作 R(t) 的分身,R(t) 是轉速控制的最終目標,它是不變的。而 U(t) 是轉速控制過程的過渡目標,因為馬達不可能一下子從靜止馬上爬升到高速,它是一步一步慢慢爬升上來,因此我們是透過 PID 計算式,一步一步設定中程目標慢慢趨近,透過它求出下一步應該如何供電,讓馬達可以平順穩定地達到希望的轉速。

    U(t) 是一個先行指標,透過它計算出下一步要供電多少,等馬達被驅動後,才有辦法量取轉速 Y(t),因此兩者之間會有個時間差,這就是 Y(t)=U(t-2) 的由來。

    回覆刪除
  24. 謝謝!解釋得很清楚,我再確定一下是不是這樣的意思呢:

    利用PID算出要輸出給馬達的目標值U(t),
    下一個時間馬達執行後得到Y(t+1),
    再下一個時間透過量測的動作得到的值是Y(t+2).
    所以U(t)=Y(t+2)-->U(t-2)=Y(t)

    回覆刪除
  25. Flora您好,

    你的理解是正確的,利用PID算出要輸出給馬達的目標值 U(t), 下一個時間馬達執行後得到Y(t+1),因為 NXT 馬達的檢知有一秒鐘延遲,需再等下一個時間透過量測的動作得到 的值是Y(t+2). 所以U(t)=Y(t+2)-->U(t-2)=Y(t)

    祝你新年快樂

    回覆刪除
  26. 感謝您~新年快樂!!

    回覆刪除
  27. Flora 您好,

    很高興認識你,再補充一點,本文 NXC 程式每秒鐘計數轉速一次,因此時間間隔單位為秒,如果你以 500ms 為週期,那麼相關時間都要配合修正。

    回覆刪除
  28. dear bridan

    抱歉那麼久才回覆我的東西,之前跟您討討的pid,我的source code也放在這給人參考一下,跟你的因該是大同小異。

    err=目標速度-目前的速度;//誤差量
    e_kp=err; //kp用的誤差量
    Sum_ki=Sum_ki+err; //ki用的誤差量
    e_kd=err-err_old; //kd用的誤差量
    err_old=err; //更新kd的誤差量

    u=(KP*e_kp+KI*Sum_ki+KD*e_kd);// 輸出給馬達

    if (u>馬達的最大正轉速值)
    {
    u=馬達的最大正轉速值;
    Sum_ki=(u-KP*e_kp-KD*e_kd);//不更新這次的積分累積誤差量
    }
    else if (u<馬達的最大逆轉速值)
    {
    u=馬達的最大逆轉速值;
    Sum_ki=(u-KP*e_kp-KD*e_kd);//不更新這次的積分累積誤差量
    }
    set_PWM(u);//送出pwm

    主要是把我的馬達上下限那段寫出來給大家參考一下。謝謝

    回覆刪除
  29. Wallace 您好,

    謝謝你的分享,在這裡留下討論過程,雖然花了很多時間,可是有助於大家相互學習,當做前人種樹後人乘涼。

    祝你新年快樂。

    回覆刪除
  30. 您好!
    假設sensor與控制的點A有一段距離,這時signal從A到sensor會有time delay的問題, 請問要如何解決time delay的問題造成PID效果不好?Thanks.

    回覆刪除
  31. CH您好,

    你所提的問題描述我不是很清楚,猜測感測器安裝位置與馬達控制的中心點有段距離,而無法精確控制,你必須列出數學模型,才能估計或修正這些誤差,它應該跟時間延遲沒有直接關係。

    本週六(2011/3/26)將會發一篇NXT控制的新文,可能跟你的問題有些關聯,可以參考某些觀點,敬請期待。

    回覆刪除
  32. 你好,
    我是剛接觸 NXT 的新手,您文章中有提到 NXT 無法使用小數點,不解的是,我看BCC的文件的作法
    http://bricxcc.sourceforge.net/nbc/nxcdoc/nxcapi/ex__atan_8nxc-example.html
    他有宣告使用 float,我把firmware升級到1.31還是不能使用 atan 三角函數,請問我缺了甚麼動作嗎?

    回覆刪除
  33. 熱血黃蜂您好,

    不能用浮點數是因為我的NXT是第一代,並且沒有更新,而且這篇是多年前舊文。

    你在程式開頭處加入,#include "NXCDefs.h"
    應該可以執行。

    回覆刪除
  34. 恕我雞婆一下:

    This function requires the enhanced NBC/NXC firmware

    atan函數需要用到NXC改版的韌體。

    回覆刪除
  35. 邱老師謝謝,

    熱血黃蜂表示他的firmware版本為1.31,表示NXT已經支援浮點運算(NXC要1.28以上版本),這應該是他的NXC程式少了 #include "NXCDefs.h",把函式庫含入程式中。

    回覆刪除
  36. 好像官版1.26 FW以後就可以支援浮點運算。
    不過在印象中,NXC中atan等三角函數是使用John Hansen的Enhanced Firmware才能使用。不只是程式中h檔案的宣告。
    我不是很清楚韌體的內容,但是似乎需要韌體內部的指令,才能使用相關三角函數。
    還請Bridan確認一下。謝謝!

    回覆刪除
  37. 謝謝邱老師提醒,

    樂高官方韌體不保證支援 NXC,因此想用 NXC 的人,最好安裝 NXC 韌體,確保功能正常。

    回覆刪除
  38. 我用可變結構滑動模式定位,效果還不錯,而PID在逼近期望值會有顫動的現象。

    http://cmackimo.blogspot.com/2011/06/nxt.html

    回覆刪除
  39. 薛老師您好,

    恭喜有好的進展,並且運用可變結構滑動模式來控制,你說在逼近期望值會有顫動的現象,應該是指 overshoot 吧?如果是那很正常,只要不要超過太多即可。如果不是,老師需要說明一下。

    回覆刪除
  40. Bridan您好,
    我對你這邊文章很感興趣,
    1.我不解的是還是在於
    Power = U(t) / 8,
    是否可以再解釋的清楚一些;
    2.你提到馬達轉速回應有一秒的延遲時間,
    可是我有遇到的是在程式裡面直接寫取樣時間25ms,頂多延遲5ms,
    ex:0.03 ms -> 18.52 r.p.m.
    0.06 ms -> 63.22 r.p.m.
    所以我想了解它是可以控制的,還是都固定一秒,
    3.你一開始初始角度給500(set_speed = 500;),這邊給的角度代表甚麼用意,假設給其它角度可以嗎?你好像是用角度去讀取power値,那如果改用power去讀取角度値也可以嗎?
    麻煩你解答一下了,謝謝。

    回覆刪除
  41. Bridan您好,
    我還少提了一個東西,
    你提出是用PID Speed Control,
    但是你有一行指令啊
    OnFwdRegEx(OUT_A, power, OUT_REGMODE_IDLE, RESET_NONE);
    就是那個OUT_REGMODE_IDLE這指令,
    如果改OUT_REGMODE_SPEED,或者是我有用兩個樂高伺服馬達時,改OUT_REGMODE_SYNC,是不是有差別啊,拜託您解答哩,謝謝。

    回覆刪除
  42. 您好

    這個程式的整體設計,採用每秒鐘取樣一次角度,
    因此 我的 U(t) 最大值為 800度/sec
    配合 Power = 100 可產生最大轉速,
    所以公式 Power = U(t) / 8 就是這樣推算出來

    當你調節取樣時間時,Power = U(t) / 8 的公式就要配合修正,
    以 25 ms 取樣一次,公式應該修改成 Power = U(t) * 5
    因為 25 ms,U(t) 最大值為 20度/25ms = 800度/sec

    關於馬達轉速回應一秒延遲的原因,是因為這個程式每秒取樣一次,
    所以有一次的延遲。至於你提供 0.03ms、0.06ms 數據,我不懂其意義,無法評論。

    因為 NXT 馬達最高轉速為 800度/sec,所以提供一個 500度/sec 轉速控制的例子,
    其實 PID 馬達轉速控制,是要你輸入一個可控制範圍內的轉速,
    程式會自動調節供應電壓,達到轉速穩定的目的
    所以應先感測目前馬達轉速,再計算供應電力
    而不是感測電力,去計算馬達轉速,請勿本末倒置。

    雖然縮短取樣時間有利於加快反應調整時間,但是用於馬達轉速控制有兩大缺點:
    一、轉速控制不易穩定,25 ms 差一度,相當於每秒差 40 度
    二、轉速控制無法細微調整,例如採用 25 ms 取樣一次,是無法控制 799 度/sec
    只能控制 1度/25 ms ~ 20度/25 ms

    主要的原因在馬達轉速與時間相關,它是一段時間的累計,
    有興趣你可以實驗不同取樣時間的影響

    關於 OnFwdRegEx(OUT_A, power, OUT_REGMODE_IDLE, RESET_NONE);
    因為目前整個 NXT 馬達是由我的程式計算 PID 控制
    如果改成 OUT_REGMODE_SPEED 或是 OUT_REGMODE_SYNC
    那將產生不可預期的結果,因為這兩個參數會改變馬達出力
    也許一般情形沒問題,但是受到阻力時,可能會造成出力忽大忽小
    因為 NXC 的韌體不是我設計的,我不清楚這些參數會如何控制馬達
    因此使用 OUT_REGMODE_IDLE 才可以確保控制正常

    回覆刪除
  43. 回覆
    1. Marie,

      聞道有先後,術業有專攻,在此記錄與分享,歡迎討論。

      刪除
  44. 您好 版主 想信您請教一個問題 !!
    就是 我使用 NXT 機器人 !! 想做 類似 segway的平衡控制 !!
    但我從控制相關書籍中讀到 要知道一個系統的 轉移函數
    才能對他去做一些參數或迴授的控制等等 !!
    (因為這樣才能透過響應圖看出該調整 暫態 或是 穩態 以及 根軌跡)

    但我無法知道 NXT做segway 的 轉移函數
    我寫了一個 PID 的程式 但 PID 三個參數
    因為沒有轉移函數 所以無法從響應圖中看出
    具體的改變 , 因此我的 PID 三個參數都只能亂調,
    請問有什麼方法可以教我嗎 ?

    可以不知道一個系統的 轉移函數 就調參數嗎 ?

    回覆刪除
    回覆
    1. 你好,

      先提供你兩個網址,詳閱相關內容後,再來討論你的疑問之處,
      http://zh.wikipedia.org/wiki/%E6%8E%A7%E5%88%B6%E7%90%86%E8%AE%BA
      http://4rdp.blogspot.tw/2010/05/discuss-about-segway.html
      http://4rdp.blogspot.tw/2013/11/pid-control-1.html

      在實務上,我常不知道該系統轉移函數,以 Ki = 1, Kp = Kd = 0 來控制,前題是硬體可以快速反應。
      不然就從 Kp = Ki = 1, Kd = 0 開始試調。

      刪除
  45. Bridan 你好 ! 目前我是學生
    想像您請教一個問題
    看完了 您的文章後 對PID有稍微瞭解了一些
    得知 角度控制在 NXT中 為 :
    P(t) = Kp*E(t)
    I(t) = Ki*[I(t-1) + E(t)]
    D(t) = Kd*[E(t) – E(t-1)]
    U(t) = P(t) + I(t) + D(t)
    Power = U(t) / 8
    Y(t) = U(t-2)
    但若我今天 是用 Hitechnic 的 Gyro sensor 去做平衡控制
    我的 E(t) 為 (當下的感測值) 減去 ( 一開始平衡時的感測值)
    請問我該如何換算 去應用在 上面打的 角度控制PID中呢 ?
    請教您了 謝謝

    回覆刪除
  46. 同學你好,

    Hitechnic 的 Gyro sensor 正確來說是用來偵測旋轉速度,當物件旋轉時,它可以測得角速度,如果只是傾斜靜止不動,那讀值會等於零 (扣除偏差後)。

    我沒有這個檢知器,只能線上指導你,訊息越充分,給予的意見會越正確。

    猜想你應該是應用於 Segway,先想想看 NXT 從直立到完全傾倒需要多久時間,你能算出速度嗎?
    再來是應該用多少旋轉把它扶正?

    從我的實驗資料顯示,電力設定100,平均轉速為800度/秒,那根據你的PID K值,可以估計 U(t),
    再來就可以找 Power = U(t) / X 關係式。

    我有個問題想問,為什麼會選用 Gyro sensor 而不用 Angle sensor?

    回覆刪除
  47. 同學,你的留言又不見了,我補貼上

    您好 謝謝您的指導 我會去測試看看
    另外 會使用 Gyro 是因為一開始google時看到 很多人使用這個去做
    所以才買這顆感測器 !! 另外 有買 三軸加速規 我之前也有在網路上問過
    那位網友是跟我說 做segway 無法用 三軸加速歸去做 請問是真的嗎 ?

    另外 因為我的程式可能還沒寫很好 所以我一開始是直接用手 讓他先站立
    然後啟動我寫的程式 手再放掉 一放掉他就直接倒了 不知怎計算他速度
    我一直搞不請出 程式中的 取樣時間 要怎麼去寫
    是指說 迴圈執行一次的時間 就是他取樣的時間嗎 ?

    回覆刪除
    回覆
    1. 原來是參考網路上討論買的,看來大家被這個 Gyro 這個字義騙了。Hitechnic 有四款跟角度有關的 sensor,分別為

      角度 Angle
      角速度 Gyro
      三軸加速規 Acceleration / Tilt
      地磁羅經 Compass

      Segway 的直立與地面角度有關,因此直接用角度感測器比較容易設計,角度差多少就平衡多少。
      Gyro 感測器,則需要從角速度,用數學積分推算目前的傾角,如果程式寫不好就容易斜斜的,甚至如你的狀況,直接傾倒。
      三軸加速規,難度又更高,相當於已知加速度狀況下,以數學推算 Segway 的傾角,在還未仔細評估整個系統的性能,感測器精度、性能前,我也沒有把握能設計出來。

      其實,現階段不是寫程式解決問題的時候,在你還沒弄清楚控制關鍵前,所寫的程式絕對無法適當控制。
      此時,你需要運用國高中的物理力學,測量 Segway 的高度、質量分布,重心位置,已知地球重力加速度 9.8 m/sec^2 情形下,會多快傾倒,以及如何由測量的角速度,來推估目前傾角。

      解決上面問題後,就是寫程式控制取樣時間,取樣時間就是兩次讀取 Sensor 的間隔時間。如果時間不需要精準,那就用 Wait()指令等待,如果很在意精度,那你先試寫一個計時程式,再用碼表測量,應該可以計算出一個迴圈的平均時間。我們研發人員遭遇各種問題,總是會靜思各種可行的解決之道,祝你成功。

      刪除
    2. 真的很謝謝您 給我這麼多資訊 !! 我會好好比較這幾種感測器
      會使用 Gyro 是因為看到 Hitechnic 官網上 也是使用 Gyro 去做segway
      只是是使用G 語言 我想將他用 LabVIEW 去做 目前還在研究中。

      我有去查了一下 NXT Angle Sensor 他好像是要用 旋轉他
      才能去測量角度的變化 , 若使用他 則兩邊馬達都要裝設
      且體積怕變太大 , 但確實感覺上 好像會比較容易去做
      因為我現在就是卡在 不知如何 將Gyro 值 去做積分 得到頃角。

      另外我想問一下 若做segway 我PID 程式 對於兩顆馬達 是不是要分開寫
      不能一個PID值 同時控制兩顆馬達 ,另外用Gyro去做 是不是就一定要做 角度控制的PID ?

      真的很謝謝你

      刪除
    3. Angle sensor 使用一顆即可,只要它能直接反應 Segway 的傾角即可,並且它可以隨時讀取角度。

      使用 Gyro 推估傾角,應使用公式 X(n) = X(n-1) + Vt,假設採用每秒一次取樣,則 t = 1,V 為從 Gyro 測得的角速度,X(n-1) 為前一秒的傾角,剛開始直立為 0,這樣你就可以每秒重複計算估算現在傾角。

      處理兩顆馬達,你自己要思考這問題,在研發方面有時會遇到抉擇,就像現在到底是要用一套還是兩套,有什麼理由要用到兩套?如果用一套沒辦法解決問題嗎?自己找個理由說明為什麼非要用它,或是為什麼不要用它?這個功課由你來做。

      其實現在,我有想到一個不用 PID 控制 Segway 的方法,你可以幫我實驗看看,依據我之前實驗方法得知,馬達 power = 1 時,可以每秒轉 8 度,因此可以傾斜超過 X 度就轉一下修正,其它時間就靜止,這樣也不用搞數學模型。

      網路上,我從別人的紀錄獲益良多,在這我貢獻所長回饋鄉民,希望未來你有能力時,也能服務他人,我想設置這個部落格並定期發文就有它的意義。

      刪除
    4. 您好 謝謝您 回覆我 您給的功課 我一定加以測試 想出其理由
      另外想請問幾個問題 是我看不懂的部分
      (1)
      公式 X(n) = X(n-1) + Vt , 其中 Vt 為 Gyro 測出的角速度值 , X(n) 為傾角
      這點我有點不懂 , 因Gyro 量出值 就是 角速度 , 那所謂得頃角 就是要透過積分
      算出來的角度嗎 ? 還是為馬達轉動的角度 ? 因在labview中 有個 read rotation 的圖塊
      這邊的頃角 就是指這個嗎 ?
      (2)
      公式中的 Vt 是 V的意思 還是 V*t 的意思 ?? 不好意思 資質駑鈍....

      真的很謝謝您˙ 看到你後面說的那方法 我會馬上試試看 能否不用 數學模型就做出

      刪除
    5. 漏打了兩個問題
      (3)
      Hitechnic 的 angle 感測器 是要裝橫桿上去 帶動他轉動 才能測期轉動角度
      若不兩顆馬達都裝 不是只能測到其中ㄧ顆馬達嗎 ?
      (4) X(n) = X(n-1) + Vt 因我還不懂 X(n) 的意思 , 所以不懂為什用 + Vt

      刪除
    6. X(n) = X(n-1) + V*t,這公式就是利用積分的概念,將每瞬間角速度轉化為傾角,它也可以運用於其它跟時間有關的運動上。
      開始時直立令, X(0) = 0
      經過一秒,從 Gyro 取得角速度讀值 V,角速度就是每秒鐘旋轉的角度,假設這瞬間 V = 2,,那表示這一秒鐘,傾角變成 2 度, X(1) = X(0) + V*t = 0 + 2 * 1 = 2,
      再假設下一秒測得 V = 3,那 X(2) = X(1) + V*t = 2 + 3 * 1 = 5
      這公式就是估算 Segway 傾角,請勿與馬達轉動角度混淆。

      我不清楚你指的 LabView 圖塊是哪一個,是 Gyro 還是馬達的? 如果是 Gyro 那就是了,不過注意 Gyro 的讀值有偏差 (offset) 要記得扣除。

      現在仔細看 Angle sensor,確實它是要裝十字橫桿去轉動它測角度,直接接到馬達上,你測量的是馬達的角度並不是傾角,需要自己修改機構設計去實際測量真正的傾角,難怪沒人用它於 Segway。

      刪除
    7. 看自動控制書時 在 root locus 章裡看到 控制設計時先 PD 後 PI 但在 frequency responce章裡時
      看到 設計要先 PI 後 PD 而在實務上 因D為高通濾波器 放大雜訊 所以一般 都使用 P 或 PI 即可
      必要時才納入 D 請問 這原因是什麼 ? 為何兩章 設計方式 不一樣 因為我有點看不懂

      刪除
    8. 關於 D 項目,你可以參考 PID Control 精彩討論 (2) ─ 微分項與負載,http://4rdp.blogspot.tw/2013/11/pid-control-2.html

      現在我手中沒有自動控制方面的書籍,無法立即回覆這個問題 (root locus ),你可以複製一段內容或提供網址再回覆。

      刪除
    9. 好的 謝謝您 等我有新進度出來 有不懂得 再請教您 真的很謝謝你唷 ,
      另外 root locus 我看得是原文書中的, 不好節錄,,我會去學校請教學教老師
      有答案 在告知您唷

      刪除
    10. 好,期待你分享新的進展。

      刪除
  48. 我已建構好segway 自我平衡成品,運作正常,可以執行程式自我平衡,但想要於程式執行中,經由平板的App-Inventor程式藍芽遙控兩輪前進、進而平衡,請問我如何於segway程式執行中,同時受藍芽訊號控制。感恩 !

    回覆刪除
    回覆
    1. 你好,
      因為沒有仔細系統描述,所以假設你用樂高 LEGO NXT/EV3 組了一個 segway,可以參考舊文 http://4rdp.blogspot.tw/2011/01/segway-and-bluetooth.html,從留言了解你可以原地平衡,現在的難題在如何加入前進後退的控制機制?

      這裡給你的建議是分時控制,例如每前進一兩秒,就執行平衡一次,等平衡後再執行下一段動作,如果你想讓行進控制更加順暢,而不是停停頓頓,那你就要自己想想辦法,我並未對 Segway 有深入研究,只能先給你粗淺的控制方法,當你能自己找出解決方案時,表示你的研發功力就更上一層樓。

      刪除
  49. 不知道為何 Google 部落格留言發生甚麼問題,有篇讀者來信顯示不出來,因此重貼

    你好 拜讀了您Speed Control的文章 也參考了你的試算表 想請教您問題
    "I"係數是累計誤差的參數 實際應用時 累計誤差超越暫存器大小 必會發生問題
    請問在哪個時機點適合讓"I"歸零(持續運轉狀況下)
    我的應用是以BLDC馬達切割物品 並控制DUTY以維持定轉速

    以下是我的答覆:
    在定速控制的狀況,I 控制項勢必不為零,如果 I = 0,表示轉速也為零。可以參考
    http://4rdp.blogspot.tw/2008/12/apply-pid-to-control-lego-nxts-speed.html 說明。

    回覆刪除
  50. 不好意思,對於您在2012年7月4日 下午6:07的回覆,我有些疑問,你說以 25 ms 取樣一次,公式應該修改成 Power = U(t) * 5,但我用133rpm*360度/60秒/4(變25ms)=199.5,這樣不是應該寫成Power = U(t) /2,想請問一下我觀念是哪裡出問題了?

    回覆刪除
    回覆
    1. 你的計算式有誤,一秒鐘有 1000 ms,
      如果是 25 ms 取樣,應該是 133rpm*360度/60秒/40 (變25ms)=19.95
      如果是 250 ms 取樣,應該是 133rpm*360度/60秒/4 (變250ms)=199.5
      因此 ,25 ms 取樣,Power = U(t) * 5
      若是 250 ms 取樣,則 Power = U(t) / 2,也就是 Power = 100 時,為全力輸出,這是 NXT 伺服馬達的定義

      刪除
  51. 你的後兩個貼文不見了,因此再補貼,補貼一

    謝謝Bridan的回覆,沒注意到這地方還請問真是不好意思。
    我還可以在請教一下,你說過NXT馬達轉速回應有一秒延遲的現象,你是怎麼測試出來的呢?因為我使用的是dspic?

    另外再請問一下2011年2月8日 下午4:39wallace的回覆,他當中有超過最大值時的判斷,但是不更新這次的積分累積誤差量,這行程式碼是甚麼意思呢?

    希望能得到一些建議,卡了有段時間了,謝謝。

    回覆刪除
  52. 補貼二,

    謝謝Bridan的回覆,沒想到問題出在這種地方,真是抱歉。

    我可以再請問一下,你說 NXT馬達轉速回應有一秒延遲的現象,你是用什麼方法測出來的呢?因為我使用的是dspic33?

    我看到你和wallace在2011年2月8日 下午4:39討論的地方有個疑問,Sum_ki=(u-KP*e_kp-KD*e_kd);//不更新這次的積分累積誤差量,這個意思是說消除穩態誤差嘛?還是?

    回覆刪除
    回覆
    1. 這兩補貼意思相同,在此一同回覆,

      NXT馬達轉速一秒鐘的延遲是用常識判斷出來的,NXT只能提供 MotorRotationCount,檢測角度,我是一秒鐘累計轉動多少角度,因此一定是一秒後才知道這一秒中轉多少角度,如果你把角度檢測改成 25 ms,那就是要等 25 ms才知道前一刻的轉速。

      關於 wallace 的回覆,涉及 2010年12月 Windup 的討論,建議你採用 2010年12月27日 下午7:53 的回覆,以避免過大積分誤差超出可控範圍,造成控制異常。

      刪除
  53. 請教一下,關於PID的控制我只需要一個可以回授的LEGO Servo Motor,不同馬達的特性會影響嗎?
    像是直流、伺服之類,若是有影響,想請問一下有哪些參數會影響,像是轉距、馬達電壓不同的電流變化等

    回覆刪除
    回覆
    1. Noel您好,

      PID控制參數與馬達以及負載特性相關,你提問的項目都有關聯,基本上它會綜合表現於PID控制變化上,無需知道馬達詳細數學模型。

      如你想獲得較精確的答覆,請把問題再更精確描述,謝謝。

      刪除
  54. Bridan您好,因為目前我在撰寫馬達PID的控制,在思考要怎麼觀察的他反應速度,因為我沒有用軟體來模擬,所以我只能從實際的馬達來觀察
    ,我目前想到的是將馬達的電流電壓用示波器來顯示,不知道有沒有更好的表現方法。

    回覆刪除
    回覆
    1. Noel,

      你沒述明馬達是那一類型,我就假設是直流馬達採電壓控制,示波器是可以觀測電壓電流,不過還少了轉速,你需要個轉速計。

      刪除
  55. 我使用的是有刷直流馬達,給的電壓越大轉速也越快,這樣還需要轉速計來測量PID的穩定度嗎?
    因為觀察電壓和電流的變化是否就能驗證馬達的穩定度和補償時間?

    回覆刪除
    回覆
    1. Noel,

      這要看你控制什麼項目,是要定電壓、定電流還是定轉速?有刷直流馬達,電流大小與轉矩成正比,與轉速無直接關聯,即使加大電壓,使電流變大,增加了轉矩,但因負載變化,轉速也會變動,除非你控制項目無關轉速,不然應該加個轉速監控。

      如果你的負載恆定,是可以觀察電壓電流穩定度,兩者時間差是延遲時間。

      刪除
  56. Bridan您好,
    若我想控制的項目為定轉速。但負載可能會有變化,就點像是跑步機上有人在跑步,但馬達需要定速,所以我控制的電壓電流都需要改變。
    假設這種情況,我的轉速監控可否用電壓電流變化來代替,只要我的電壓和電流趨近穩定,斜率接近0時,相當於我PID已經做好定速功能了。

    回覆刪除
    回覆
    1. Noel 你好,

      一般指稱的定轉速,是設定馬達多少 rpm,馬達也實際輸出一樣的轉速,即使你知道馬達的數學模型,想利用電壓電流控制輸出的轉速=期望轉速,這是不可能的,還缺少負載資料。

      這種狀況建議你,定電壓控制就好,反正負載穩定時,轉速也穩定,電壓調高,轉速也增快,反正你只是要『穩定轉速控制』非一般『定轉速控制』,至於實際轉速值為何,不是關注的重點。

      刪除
  57. Bridan您好,

    所以說我應該先了解我使用的負載範圍,再去調整當中最適合的PID是嗎?

    目前我控制的部分是電壓,但是我的負載不是穩定的負載,就像是一個人在跑步機上跑步不會每一步都踏一定的力道。
    我是想說若是負載突然變輕,我的電壓也要下降,相反負載變重,我的電壓要上升提高轉速來帶動負載,這樣轉速才 會維持跟原來一樣,不知道這想法是否正確。

    回覆刪除
    回覆
    1. Noel您好,

      能了解負載狀況是最好不過,通常直接測量負載是困難的,就像跑步機負載忽大忽小。

      我說過不知道系統數學模式PID也可以控制,從你的描述,你很在意速度控制,既然如此唯有加裝encoder才能測量轉速,並且控制它。

      這讓我想起學生時代,用紙板打洞,再加個光耦合器,就可以計數轉速,或許你可以試看看。

      你描述電壓控制轉速的想法是正確的,PID確實是這樣調控電壓,以因應負載變化,讓轉速穩定。

      刪除
  58. Bridan您好,

    我先嘗試你提供的ENCODER的方法,一般PID使用,如果沒有ENCODE還是可以?

    學生時代真的不少人選擇PID的專題,但要弄懂了解的人真的不多阿。

    回覆刪除
    回覆
    1. Neol 您好,

      PID 控制都有一個控制標的,想控制角度,就必須量角度,想控制轉速,就必須測轉速,
      因此沒有 ENCODER 就無法測轉速,沒有轉速就無法 PID 轉速控制,
      PID 沒辦法量其它物理量來控制轉速,除非你已知數學模式,可以推算正確的轉速。

      是啊,PID 控制我也是工作二十年後才悟道的,現在就是以最淺顯方式傳授知識給各位,
      希望大家獲益後回饋社會。

      刪除
  59. Bridan您好,

    感覺有點了解PID的架構了,剩下就是開始實作了,謝謝你給了不少的意見,若是有新發現或是遇到問題再一起討論。

    希望有朝一日也能悟道來普渡眾生阿!呵呵

    回覆刪除
    回覆
    1. Noel 您好,

      很高興在此與你技術討論,等你有實驗結果,我們再繼續討論。
      另外想認識你,歡迎在 http://4rdp.blogspot.tw/2014/01/2014-reader-survey.html 留言。

      刪除
  60. 原文遺失,補貼如下

    Bridan您好,

    1.我目前測試都是P參數給0.4,I參數給0.3,每一秒會去偵測ENCODER的讀值來去做轉速的變化,空載在13秒會降太多、16秒左右的時候會有衝過頭的情形,如果我試著調P、I參數往下降都沒辦法消除,我是不是該考慮加上D參數,不過我聽到很多人都說控制馬達P、I就很棒了
    下面是它的轉速圖
    http://upload.pmp4.net/view/g/20150623162740rdel4.jpg.html

    2.不知道是不是因為我用的是直流有刷馬達+ENCODER所以才不穩定,因為我在網路上以穩定性來講大家都是用伺服驅動器,它的PID表現也非常的穩定,不會像我現在的圖形一樣。

    3.我看過你說建議用半載情形來調參數,或是空載及滿載參數取平均值,假設說我要最多會用到700KG,我要用一個穩定的350KG來調出漂亮的波形。因為不是很清楚,所以我先用空載的PID參數去壓一個彈簧來看RPM轉速,因為彈簧越壓力量越大,所以我是從0~700KG的RPM轉速,結果都很難穩在100RPM
    下面是它的轉速圖
    http://upload.pmp4.net/view/g/20150623170623da2po.jpg.html

    回覆刪除
    回覆
    1. Noel 您好,

      很高興再次於網路上討論你的案例,不過看到轉速圖,真的出乎意料!

      在解決有載狀況前,應先處理無載情況,從圖一來看,個人直覺認為,在你的系統 P=0.4有些大,先建議 P=0, I=1, D=0 無載測試,如果速度仍不太穩定,就要調整轉速取樣時間,因為有變動頻繁且很大的負載,建議改成 0.1 秒取樣一次。

      另外,轉速不穩定的原因,也有可能自製的 ENCODER 計數不精確,例如用電腦數,但是電腦的時間中斷有長有短,因而忽快忽慢。

      刪除
  61. Bridan您好,

    1.你上次先建議 P=0, I=1, D=0 無載測試,這是為了讓我調整取樣時間的意思嗎?
    如果是的話,調整PID的參數的步驟研究出的結果是
    1-P=0, I=1, D=0 調整出取樣時間
    2-加上P參數來調整
    3.若真的速度還不穩定再加上D參數
    不知道我的想法是否正確?
    之後測試接負載時,到穩定的時間勢必比較慢,照理來說我要調大P跟I的參數值來補償,因為空載跟無載的參數值是不一樣的?

    2.我發現在低轉速像是10RPM馬達晃動很大,變成像是步進馬達,我去查了一下,馬達在低轉速的時候才是PID最難控制的地方,會在7~11RPM的飄動,我試著調成1ms一次才勉強像步進馬達,不然根本是開關開關的感覺。

    3.至於電腦中斷我是用一個陣列存放每次TIMER中斷計算的RPM,最後再一次觀察結果。

    回覆刪除
    回覆
    1. Noel 您好,

      正確,是以 P=0,I=1,D=0 來調整取樣時間,不過有個先決條件,那就是計算 RPM 必須穩定,從你的描述來看,我很擔心自製的 ENCODER 穩定性不足,要先確認轉速忽快忽慢是否與此相關,有四個要素會影響轉速忽快忽慢:(請空載或定載測試)
      一、馬達的電源系統不夠穩定,馬達輸入定電壓,用示波器觀察馬達電壓
      二、不良的 ENCODER,給定電壓,耳聽馬達轉速聲,如果兩者皆穩定,就轉速測量不穩,就是 ENCODER 不良
      三、錯誤的 PID 參數
      四、取樣時間過短

      如果是第二項問題,建議用 Arduino 做個計速器,中斷時間就可以穩定精確,不要用電腦的中斷,有太多不確定性。
      對了,你的 ENCODER 一圈總共打幾個洞?

      10 rpm = 60 degree/sec = 60 / 360 = 1 / 6 = 166 ms,檢查一下,你的系統是否與這時間有任何關連?

      除非特殊需求,否則 PID 參數通常是定值,不會因為空載或滿載而參數不同,因此會調出一個讓系統平衡及適當穩定的 PID。

      刪除
  62. 再補充一下,我更換一顆小顆的馬達來測試10RPM,它卻可以在9~10RPM,一樣都是直流馬達,莫非這是甚麼馬達特性的影響嗎?

    回覆刪除
    回覆
    1. 從這裡的線索,轉速不穩定應與馬達電流大小有關,有可能馬達驅動器驅力不足,讓你的馬達忽快忽慢,不過蠻奇怪,一般而言驅力不足,電壓是會掉下來。

      刪除
  63. 遺失貼文補上,

    Noel 已針對您的文章「PID Speed Control」留下新意見:

    Bridan您好,

    1.電壓的穩定度我確認過很穩定,只有0.0*V的電壓跳動。基本上現在可以控制的誤差在1RPM以內,不過是空載,等我負載OK後就來測試看看

    2.關於ENCDOER我不是用自製的,而是加裝上去的,所以幾個洞的話不是很確定。題外話:想請教一下自製的ENCODER該如何製作?
    有點說錯了,我是用ICD3來模擬,然後轉速值我顯示在電腦上,值應該是蠻準的。

    3.目前我程式是以120MHz的速度在執行,指令速度是60MHz,每10ms修正馬達轉速,然後1s為基準抓讀值。感覺跟166ms有點關係的我只有想到指令速度(1/60MHz)=16.6ns,可是好像也不是問題所在?目前空載60~1600RPM都可以在誤差1RPM,可是10RPM就像我上次講的誤差率頗大。

    4.我記得我曾看過你說過若是要量滿載~空載的PID,要取半載情況時的PID會比較準確,這差別只是可以快一點達到穩定沒錯吧?

    回覆刪除
    回覆
    1. 遺失貼文補上

      Noel 您好,

      1.不知你是用甚麼儀器量電壓?如果是用直流電表,一些高頻訊號是會被濾掉,應用示波器觀察,另外有沒有高次諧波?1 RPM 對 10 RPM 來說有 10% 誤差,你確定這樣的精度可以接受?

      2.有兩種方法可以做 ENCODER,方法一,弄個圓形紙板或塑膠板每 30 度打洞,以光耦合器偵測單位時間內光穿過洞的次數。方法二,在馬達轉軸上貼反光貼紙,利用反射型光耦合器計數單位時間內反射次數。ICD3?? 你指的是 Microchip 單晶片的發展工具?你的馬達是直流步進馬達嗎?

      3.轉速修正應與抓取轉速同步,如果你 10 ms 修正轉速一次,那讀取轉速也需要 10 ms 讀取,PID 控制是根據所回饋的最新資料,立即控制下一步輸出,目前你的方式,難怪會轉速不穩。

      4.半載可以確定系統會處在工作區,所求出的參數也會在中間值,要微調比較容易,用太偏的地方找參數不好找。

      刪除
  64. 補充一下,我這次講的平均值和有效值是我用示波器量出來的。

    回覆刪除
    回覆
    1. 示波器一般是三位半的精度,不知你的數位電表是多少位數顯示?

      刪除
  65. 遺失貼文補上

    Bridan您好,

    感覺留言的文章好像很常遺失,而且其他人好像也有類似的情況,不知道是因為網路不穩定或是其他原因嗎?

    我上次的值是用三用電表量測出來的,平均值會有0.4V的晃動,而有效值則是0.1V的晃動,以馬達來說應該還是以有效值為主吧?
    高次諧波你指的是高頻的時候會失真的情況嗎?如果是的話我用示波器來看是沒有。

    是 Microchip 單晶片的發展工具沒錯,但我使用的是直流有刷馬達+ENCODER去控制。

    關於誤差我目前有在思考是否是我的電路或是馬達的影響,因為我今天試著用定電壓輸出,我觀察馬達穩定後的轉速,居然還有+-6~12RPM,
    越高轉速越大,照這樣推斷如果我要得到更精準的轉速應該要往硬體方面著手嗎?

    回覆刪除
    回覆
    1. Noel您好,

      留言遺失原因不明,目前只好補貼處理。

      很抱歉,我看不懂第二段的說明,你指的晃動是儀器上讀值在某個範圍內變動?例如,平均值為 3.0 ~ 3.4 V,有效值為 3.2 ~ 3.3 V?如果是這樣,請告訴我轉速以及電壓範圍,資訊越清楚越好。

      另外,你是不是用 PWM 控制馬達轉速?如果是,這也可能會使馬達轉速不穩定,不知 PWM 頻率多少?

      直流有刷馬達給予定電壓,竟有如此大轉速變動,需要好好檢查原因,目前還看不出原因所在,請告知馬達基本資料,電壓、功率、輸出馬力、最高轉速等。還有你的直流電源供應器,規格為何?

      刪除
  66. 遺失貼文補上

    Bridan您好,

    很抱歉拖了一段時間才回覆。

    http://upload.pmp4.net/view/g/2015071008351167wfl.jpg.html
    上圖為我測試的馬達波型,我使用的是H橋的架構,CH1.2分別為馬達兩端,中間紅色的波型則是用CH1-CH2得出的波型,CH2均方根會在19.46~19.59V,CH2平均值15.81~16.02V,CH1均方根則是22.81~23.31V,CH1平均值21.78~22.30V,因為不確定馬達該看均方根還是平均值我就都PO了,
    轉速約在936~948RPM,會有12RPM的誤差,關於這個12RPM,我覺得是因為我10ms補償PID一次計算的誤差放大的關係,我的RPM=ENCODER每一次的變化量 * 6000 (60000ms/10ms每次PID的補償時間)/ 500PPR * 4,只看ENCODER每一次的變化量後面,6000/2000 = 3,
    而我ENCODER抓到的值本身就有4左右的變化,這個我估計是馬達的解析度,雖然馬達我就不是很了解,直流有刷馬達現在好像也快被淘汰了,很多人都不推,若是要解決此RPM的誤差,我是想到說把PID補償時間拉大,雖然這要花多一點時間才能到你需要的速度
    ,或是更換更精準的ENCODER,不過這就非常貴了。

    http://datasheet.octopart.com/SE-600-24-Meanwell-datasheet-7274772.pdf
    我使用的SE-600-24來當電源供應器,VOLTAGE TOLERANCE是+-1% 、LINE REGULATION+-0.5%,LOAD REGULATION+-0.5%,看起來應該是個不錯的電源供應。
    至於馬達的資料是小公司做的,沒有詳細的資料,他只提供我是DC24V,3000RPM,20Amp以下還有尺寸。

    回覆刪除
    回覆
    1. Noel 您好,

      馬達轉速不穩,應該與控制器有很大的關聯,
      建議先移除控制器,就很單純電源供應器直接接馬達,
      然後定電壓測轉速,例如空載 3V、滿載 3V、空載 23V、滿載 23V
      這樣才能建立馬達特性與控制的基本資料,也可以看出電源供應穩定的狀況。

      由示波器得知馬達轉速不穩,與 ch1-ch2 波形有極窄的負向電壓相關,
      它會造成瞬間馬達反轉降速,這是必須改善的地方。
      基本上,馬達轉速與 ch1-ch2 的均方根值成正比,並且不能有負向窄波。

      另外,控制週期採 50 us,相當於 20 kHz,如果耳朵會聽到高頻不悅耳雜音,
      建議可把週期縮短,讓耳朵舒服點。

      假設馬達轉速 900 rpm,每 10 ms ENCODER 應該讀取
      900 rpm / 60 sec x 500 ppr x 0.01 sec = 75 pulse per 10 ms
      反換算,假設某 10 ms 取樣得 76 pulse
      76 pulse / 0.01 sec x 60 sec / 500 ppr = 912 rpm
      表示你的取樣週期太密,若改成 100 ms,轉速誤差將縮為 1.2 rpm,其它類推

      先這樣,靜候你的佳音

      刪除
  67. 有位 SD 網友留言,因本篇部落格文留言過多致使系統異常而不見,因此補充回覆,他提問 I(t) 的意義為何?
    I(t) 在 PID 控制中代表誤差的積分項,它儲存系統的累計誤差,t表示在第某刻時間點。

    回覆刪除