許多學生不知道PID是什麼,因為許多學生不是自動化的。他們需要資訊和程式來開口說話。很明顯,這種學習方法是錯誤的。至少,首先,您需要理解PID是什麼。首先,我們為什麼要做PID?由於外部原因,汽車的實際速度有時是不穩定的。一是要使汽車在最快的時間內達到既定的目標速度,二是要使汽車在最短的時間內達到既定的目標速度。速度控制系統採用閉環控制,以滿足整個系統的穩定性要求。
速度是系統引數之一。這是第三次。汽車的速度調節肯定不是線性的,有這麼多的外部因素,沒有人能證明它是線性的。如果它是線性的,就用P。例如,當PWM=60%時,速度是2m/S,所以如果你想要3M/S,你可以把PWM增加到90%。因為90/60=3/2,這太多了。完美無缺。那麼它不是線性的,如何控制PWM來達到預期的速度呢?我們應該迅速、準確和無情。(即快速和準無情)系統的速度調節過程必須用一種演算法來調節,這就是通常所說的PID演算法。自動。控制系統的被控物件變化很大,必須改變PID引數才能滿足系統的效能要求。這給使用者,特別是初學者帶來了很大的麻煩。
下面簡要介紹除錯PID引數的一般步驟:
1.負反饋。自動控制理論又稱負反饋控制理論。首先,對系統的接線進行檢查,以確定系統的反饋為負。例如,在電機調速系統中,當電機處於正旋轉(PID演算法中的誤差=輸入-反饋)時,輸入訊號為正,反饋訊號為正,而電機同時處於正旋轉。速度越高,反饋訊號越大。其他系統與此方法相同。基於PID演算法的智慧車輛控制。
2.PID除錯的一般原理。當輸出不振盪時,比例增益P增大。輸出不振盪時,積分時間常數Ti減小。當輸出不振盪時,微分時間常數Td增大。基於PID演算法的智慧車輛控制。
3.一般步驟。A.確定比例增益P。在確定比例增益P時,首先去掉PID的積分和微分項。一般採用Ti=0和td=0(參見PID的引數整定說明)進行PID純比例調節。將輸入設定為系統最大允許值的60%~70%,使比例增益P從0逐漸增大到系統輸出。另一方面,比例增益P逐漸減小,直到系統振盪消失。記錄此時的比例增益P,並將PID的比例增益P設定為當前值的60%~70%。除錯了比例增益P。
4.確定積分時間常數Ti。在確定比例增益P後,設定較大積分時間常數Ti的初始值,然後逐漸減小Ti,直到系統振盪,然後Ti逐漸增加,直到系統振盪消失。記錄此時的Ti,並將PID的積分時間常數Ti設定為當前值。150%~180%。除錯了積分時間常數Ti。
5.確定積分時間常數td。積分時間常數td通常設定為零。要設定它,採取30%無振盪,同樣的方法,磷和鈦。對系統進行空載和有載共調,然後對PID引數進行微調,直至滿足要求。
慣性剋制演算法:
int PID_Control(signed char Position) {
int Temp_P,Temp_D,Temp_PID,Temp_I,k; //宣告三個變數,用於存放P、I、D三分量的運算結果(I沒用上)
if(Position==-128) return (No_black); //錯誤處理(值得改進的地方) else {
Temp_I=Position;
for(k=0;k<5;k++)Temp_I+=Last_Position[k]; Temp_I*=I_coefficient;
Temp_P=P_coefficient*Position; //計算比例分量(P)=比例係數*本次位置差 Temp_D=D_coefficient*(Position-Last_Position[5]); //計算微分分量(D)=微分系數*(本次位置差-前3次的位置差)
//注意由於取樣比較快,用本次位置-前3次位置才有足夠大的控制量
Last_Position[6]=Last_Position[5]; Last_Position[4]=Last_Position[3]; Last_Position[3]=Last_Position[2]; Last_Position[2]=Last_Position[1]; Last_Position[1]=Last_Position[0];
Last_Position[0]=Position; /*儲存前5次的位置,以備用。
Temp_PID=Temp_P+Temp_D+Temp_I; //P分量和D分量相加,得到控制量。 if(Temp_PID>5000) Temp_PID=5000; //防止控制量溢位
if(Temp_PID<-5000) Temp_PID=-5000; //控制量-5000~5000作為左右滿舵 Temp_PID=Temp_PID*1/5; //-1000~+1000是左右滿舵的輸出,因此需要除以0.5
/*微控制器浮點運算非常慢,所以用乘2除5兩次定點運算來替代定點數要先乘後除,才能保證精度,同時要防止溢位,用起來比較麻煩,但CPU和記憶體開銷小。*/
return (Temp_PID);
尋光,避障演算法
沒有障礙物就進入尋光模式 case Barrier_Status : Avoid_Obstacle(); break; //檢測到障礙進入避障狀態 default: break; } }
向量合成,X,Y兩個軸, x=0; y=0;
//1號光敏電阻,無Y軸,X為負 x=x-Intensity*Light[0];
//2號光敏電阻,X為-0.707,Y為0.707,45度 x=x-(Intensity *Light[1]*707)/1000; y=y+(Intensity *Light[1]*707)/1000; //3號光敏電阻,X為0,Y為正 y=y+Intensity * Light[2];
//4號光敏電阻,X,Y都為+0.707,45度 x=x+(Intensity*Light[3]*707)/1000; y=y+(Intensity*Light[3]*707)/1000; //5號光敏電阻,Y為0,X為正 x=x+Intensity*Light[4]; y=y;
採用了TA0來發生紅外線,不干擾CPU的執行:
設定陣列,對應頻率分別為38,41,44,48,54,60,67
TACTL |= TASSEL_2 + TACLR + MC_1 ; //TIMER_A時鐘源選為SMCLK,清TAR TACCR0 = 44; //產生約38KHZ的PWM輸出,SMCLK=4M,105個時鐘週期
TACCTL0 |= OUTMOD_4; //翻轉模式產生佔空比為50%的PWM }
避障底層程式:
void Measure_Distance() {
unsigned char flag_1=0,flag_2=0,flag_3=0,flag_4=0,flag_0=0;
unsigned char i,Frequency[5] = {29,36,44,47,51}; //66,54,44,42,38 for (i=0;i<5;i++)
{ TACCR0 = Frequency[i]; // 1
if(flag_0==0) {
Delay(34); PIRE1_H; // 開啟1號感測器 Delay(34); // 延遲,等待資料穩定
if(IRE1_IN==0) // 如果接收到的訊號為低電平,表明前方有障礙物 {flag_0 = 1;BarrierData[0]=5-i;} else BarrierData[0]=0; PIRE1_L; }
許多學生不知道PID是什麼,因為許多學生不是自動化的。他們需要資訊和程式來開口說話。很明顯,這種學習方法是錯誤的。至少,首先,您需要理解PID是什麼。首先,我們為什麼要做PID?由於外部原因,汽車的實際速度有時是不穩定的。一是要使汽車在最快的時間內達到既定的目標速度,二是要使汽車在最短的時間內達到既定的目標速度。速度控制系統採用閉環控制,以滿足整個系統的穩定性要求。
速度是系統引數之一。這是第三次。汽車的速度調節肯定不是線性的,有這麼多的外部因素,沒有人能證明它是線性的。如果它是線性的,就用P。例如,當PWM=60%時,速度是2m/S,所以如果你想要3M/S,你可以把PWM增加到90%。因為90/60=3/2,這太多了。完美無缺。那麼它不是線性的,如何控制PWM來達到預期的速度呢?我們應該迅速、準確和無情。(即快速和準無情)系統的速度調節過程必須用一種演算法來調節,這就是通常所說的PID演算法。自動。控制系統的被控物件變化很大,必須改變PID引數才能滿足系統的效能要求。這給使用者,特別是初學者帶來了很大的麻煩。
下面簡要介紹除錯PID引數的一般步驟:
1.負反饋。自動控制理論又稱負反饋控制理論。首先,對系統的接線進行檢查,以確定系統的反饋為負。例如,在電機調速系統中,當電機處於正旋轉(PID演算法中的誤差=輸入-反饋)時,輸入訊號為正,反饋訊號為正,而電機同時處於正旋轉。速度越高,反饋訊號越大。其他系統與此方法相同。基於PID演算法的智慧車輛控制。
2.PID除錯的一般原理。當輸出不振盪時,比例增益P增大。輸出不振盪時,積分時間常數Ti減小。當輸出不振盪時,微分時間常數Td增大。基於PID演算法的智慧車輛控制。
3.一般步驟。A.確定比例增益P。在確定比例增益P時,首先去掉PID的積分和微分項。一般採用Ti=0和td=0(參見PID的引數整定說明)進行PID純比例調節。將輸入設定為系統最大允許值的60%~70%,使比例增益P從0逐漸增大到系統輸出。另一方面,比例增益P逐漸減小,直到系統振盪消失。記錄此時的比例增益P,並將PID的比例增益P設定為當前值的60%~70%。除錯了比例增益P。
4.確定積分時間常數Ti。在確定比例增益P後,設定較大積分時間常數Ti的初始值,然後逐漸減小Ti,直到系統振盪,然後Ti逐漸增加,直到系統振盪消失。記錄此時的Ti,並將PID的積分時間常數Ti設定為當前值。150%~180%。除錯了積分時間常數Ti。
5.確定積分時間常數td。積分時間常數td通常設定為零。要設定它,採取30%無振盪,同樣的方法,磷和鈦。對系統進行空載和有載共調,然後對PID引數進行微調,直至滿足要求。
慣性剋制演算法:
int PID_Control(signed char Position) {
int Temp_P,Temp_D,Temp_PID,Temp_I,k; //宣告三個變數,用於存放P、I、D三分量的運算結果(I沒用上)
if(Position==-128) return (No_black); //錯誤處理(值得改進的地方) else {
Temp_I=Position;
for(k=0;k<5;k++)Temp_I+=Last_Position[k]; Temp_I*=I_coefficient;
Temp_P=P_coefficient*Position; //計算比例分量(P)=比例係數*本次位置差 Temp_D=D_coefficient*(Position-Last_Position[5]); //計算微分分量(D)=微分系數*(本次位置差-前3次的位置差)
//注意由於取樣比較快,用本次位置-前3次位置才有足夠大的控制量
Last_Position[6]=Last_Position[5]; Last_Position[4]=Last_Position[3]; Last_Position[3]=Last_Position[2]; Last_Position[2]=Last_Position[1]; Last_Position[1]=Last_Position[0];
Last_Position[0]=Position; /*儲存前5次的位置,以備用。
Temp_PID=Temp_P+Temp_D+Temp_I; //P分量和D分量相加,得到控制量。 if(Temp_PID>5000) Temp_PID=5000; //防止控制量溢位
if(Temp_PID<-5000) Temp_PID=-5000; //控制量-5000~5000作為左右滿舵 Temp_PID=Temp_PID*1/5; //-1000~+1000是左右滿舵的輸出,因此需要除以0.5
/*微控制器浮點運算非常慢,所以用乘2除5兩次定點運算來替代定點數要先乘後除,才能保證精度,同時要防止溢位,用起來比較麻煩,但CPU和記憶體開銷小。*/
return (Temp_PID);
尋光,避障演算法
沒有障礙物就進入尋光模式 case Barrier_Status : Avoid_Obstacle(); break; //檢測到障礙進入避障狀態 default: break; } }
向量合成,X,Y兩個軸, x=0; y=0;
//1號光敏電阻,無Y軸,X為負 x=x-Intensity*Light[0];
//2號光敏電阻,X為-0.707,Y為0.707,45度 x=x-(Intensity *Light[1]*707)/1000; y=y+(Intensity *Light[1]*707)/1000; //3號光敏電阻,X為0,Y為正 y=y+Intensity * Light[2];
//4號光敏電阻,X,Y都為+0.707,45度 x=x+(Intensity*Light[3]*707)/1000; y=y+(Intensity*Light[3]*707)/1000; //5號光敏電阻,Y為0,X為正 x=x+Intensity*Light[4]; y=y;
採用了TA0來發生紅外線,不干擾CPU的執行:
設定陣列,對應頻率分別為38,41,44,48,54,60,67
TACTL |= TASSEL_2 + TACLR + MC_1 ; //TIMER_A時鐘源選為SMCLK,清TAR TACCR0 = 44; //產生約38KHZ的PWM輸出,SMCLK=4M,105個時鐘週期
TACCTL0 |= OUTMOD_4; //翻轉模式產生佔空比為50%的PWM }
避障底層程式:
void Measure_Distance() {
unsigned char flag_1=0,flag_2=0,flag_3=0,flag_4=0,flag_0=0;
unsigned char i,Frequency[5] = {29,36,44,47,51}; //66,54,44,42,38 for (i=0;i<5;i++)
{ TACCR0 = Frequency[i]; // 1
if(flag_0==0) {
Delay(34); PIRE1_H; // 開啟1號感測器 Delay(34); // 延遲,等待資料穩定
if(IRE1_IN==0) // 如果接收到的訊號為低電平,表明前方有障礙物 {flag_0 = 1;BarrierData[0]=5-i;} else BarrierData[0]=0; PIRE1_L; }