新浪博客我不是奔跑哥看到一篇好文章分享給大家版權貴原作者所有:
多數的Arduino控制器都是基于Atmel公司的AVR系列單片機的,AVR單片機的片內資源非常的豐富,有ADC、定時器、外部中斷、SPI、IIC、PWM等功能,且Arduino控制器的PWM采用的是定時器相位修正PWM(頻率約為490Hz)和快速PWM(頻率約為980Hz,Uno的5、6和Leonardo的3、11),這也就導致了全部的定時器都被被占用了,從而不能很方便的使用定時器設置一個中斷來實現一個周期的任務,而一般需要通過讀取系統已運行時間來判斷定時時間是否已經達到。例如,通過增量式編碼器來測量電機的轉速,常規的單片機的程序架構是通過定時器來實現精確的時間定時,并利用外部中斷來實現對脈沖數目的計數,然后計算出一定時間內脈沖的數目,從而得到轉速數值并輸出。
多數的Arduino控制器都是基于Atmel公司的AVR系列單片機的,AVR單片機的片內資源非常的豐富,有ADC、定時器、外部中斷、SPI、IIC、PWM等功能,且Arduino控制器的PWM采用的是定時器相位修正PWM(頻率約為490Hz)和快速PWM(頻率約為980Hz,Uno的5、6和Leonardo的3、11),這也就導致了全部的定時器都被被占用了,從而不能很方便的使用定時器設置一個中斷來實現一個周期的任務,而一般需要通過讀取系統已運行時間來判斷定時時間是否已經達到。例如,通過增量式編碼器來測量電機的轉速,常規的單片機的程序架構是通過定時器來實現精確的時間定時,并利用外部中斷來實現對脈沖數目的計數,然后計算出一定時間內脈沖的數目,從而得到轉速數值并輸出。
直流電機是Arduino機器人制作中的主要動力來源,但是由于電機的參數一致性有所差別,即使是相同型號的電機在相同電壓下的轉速都不完全相同,而且在帶負載或負載不同的情況下,更加會導致電機轉速發生變化,這就會導致制作的Arduino輪式機器人不能實現直線行走,因為這是一個開環控制,沒有任何反饋信號返回。如果給直流電機加上編碼器作為反饋器件,也就可以測量得到電機的當前轉速,如果將其與設定值計算差值,并通過PID算法計算得到新的控制信號,從而可以動態的測量和控制電機的轉速,形成一個閉環控制系統。
下面我們利用帶有編碼器的直流電機、Arduino控制器、直流電機驅動板和LabVIEW上位機軟件以實驗探索的形式來設計一個直流電機轉速比例控制實驗。
1.TimerOne定時器庫
1.1下載及使用方法
TimerOne定時器庫使用AVR單片機內部的定時器1實現定時中斷的功能,其下載地址為:https://code.google.com/p/arduino-timerone/,只需要更改幾個參數即可使用定時器中斷來實現周期性執行的任務。需要注意的是,如果使用了TimerOne定時器庫,也就不能在相應的引腳輸出PWM電壓,Uno上的定時器與PWM引腳的關系如表1所示。
表1 定時器與PWM引腳的關系
定時器
|
OC0A
|
OC0B
|
OC1A
|
OC1B
|
OC2A
|
OC2B
|
PWM引腳
|
6
|
5
|
9
|
10
|
11
|
3
|
TimerOne定時器庫函數庫中自帶的ISRBlink程序如程序代碼1所示,可以實現13號管腳上LED的5Hz頻率的閃爍。
程序代碼1:ISRBlink示例程序
#include
void setup() {
}
void loop(){
//主函數,用于執行非周期性任務
}
void timerIsr(){
}
1.2評估定時時間的準確性
僅僅憑靠眼睛不能判斷定時時間是否準確,下面我們設計一個實驗來評估定時時間的準確性。我們需要將上面示例代碼中的Timer1.initialize(100000)更改為Timer1.initialize(1000),digitalWrite( 13, digitalRead( 13 ) ^ 1 )更改為digitalWrite(2, digitalRead( 2) ^ 1 ),通過反轉I/O的電平實現數字端口2輸出500Hz的近似方波。
同時,我們使用NI USB-6009便攜式數據采集卡和LabVIEW 2012軟件實現一個簡易的模擬量采集器,將Arduino 控制器上的數字端口2和GND分別與NI USB-6009便攜式數據采集卡上的AI0/AI0+和AI4/AI0-相連接,NI USB-6009便攜式數據采集卡接口示意圖如圖1所示,Arduino Uno控制器與USB-6009便攜式數據采集卡的連接圖如圖2所示。然后使用10kps的采樣率,5秒的采樣時間的參數采集Arduino 控制器上的數字端口2輸出的方波信號,取其前20ms的波形如圖3所示,通過波形頻率分析工具測量得到其頻率為499.901Hz。
另外,我們又將定時時間設置為100微秒、50微秒和25微秒,并使用NI USB-6009便攜式數據采集卡和LabVIEW 2012軟件以45kps的采樣率和2秒的采樣時間分別采集了數字端口2輸出的波形數據并進行頻率分析,得到其頻率分別為4999.01Hz,9998.03Hz,19996Hz。從以上數據對比分析可知,定時器的定時時間非常準確,頻率測量誤差主要來自于I/O反轉操作延時導致的。
最后,我們還測試了OCROBOT MEGA 2560控制器、Arduino Uno控制器山寨版輸出的500Hz的方波信號頻率,分別為500.435Hz和499.764Hz。
圖1 NI USB-6009接口示意圖
圖3定時器中斷產生的500Hz方波信號
2.轉速測量
2.1測量轉速方法
測量轉速方法有3種,分別為測頻法(M法)、 測周法(T法)及混合法(M/T法)。
測頻法是在一定時間內,通過測量旋轉引起的單位時間內的脈沖數,實現對旋轉軸轉速測量的一種方法,適用于高、中轉速的測量。該法本質上屬于定時測角法,為提高測量的準確度,有時采用多標記或開齒的方法,其不確定度主要取決于時間測量和計數量化。
測周法是在轉速脈沖的間隔內,用時鐘脈沖來測量轉速的一種方法,適合于低轉速測量。該法實際上就是定角測量法,即用時標填充的方法來測量相當于某一旋轉角度的時間間隔。在高、中轉速時,可采用多周期平均來提高測量準確度,其不確定度主要取決于時間測量、計數量化及觸發的不確定度。
混合法是在測頻法的基礎上,吸取測周法的優點匯集而成的一種轉速測量方法。它是在轉速傳感器輸出脈沖啟動定時脈沖的同時,計取傳感器輸出脈沖個數和時鐘脈沖個數,而當到達測量時間時,先停止對傳感器輸出脈沖的計數,在下一個定時脈沖啟動之前再停止時鐘脈沖的計數。因此,該種方法可在較寬的范圍內使用。
此處,我們選擇測頻法來測量轉速,其工作原理為:當被測信號在特定時間段T內的周期個數為N時,則被測信號的頻率f=N/T。
2.2轉速測量程序設計
利用TimerOne定時器庫來實現定時,通過外部中斷對電機編碼器輸出的脈沖進行計數,計數值除以定時時間即為一定時間內的轉速。實現1秒內轉速測量的程序如程序代碼2所示。
程序代碼2:轉速測量程序
#include
long counter_val[2] = {0,0}; //定義數組,用于存放外部中斷計數值
byte CurCnt = 0; //定義當前計數器標志,用于判斷當前正在計數的數組
int j=0; //定義定時器中斷標志,用于判斷是否發生中斷
void setup() {
}
void loop()
{
}
//外部中斷處理函數
void counter()
{
}
//定時器中斷處理函數
void timerIsr()
{
}
2.3驗證頻率測量的準確性
前面提到了Arduino的模擬輸出(PWM)的頻率約為490Hz,且轉速測量采用的是測頻法,此時用來正好來驗證一下程序設計的正確性。在上面的轉速測量程序中的void setup()里面delay(2000)之前增加如下代碼,以產生方波。串口輸出的頻率測量結果如圖4所示。
pinMode(3,OUTPUT);
analogWrite(3,127);
圖4 PWM頻率測量結果
在圖4所示的PWM頻率測量結果中,去除前兩個,可以發現頻率值穩定在490和491,且4個490之后出現一個491,基本可以認為是490Hz。
同時,為了進一步的確認PWM的頻率為490Hz,已驗證頻率測量的準確性,利用NI USB-6009便攜式數據采集卡和LabVIEW 2012軟件實現一個簡易的模擬量采集器,使用10kps的采樣率,5秒的采樣時間的參數分別采集了PWM的占空比為10/255、127/255和245/255時的波形圖,取波形圖的前0.01秒,如圖5、圖6和圖7所示,在0.01秒內約有5個周期,同時使用頻率分析工具對占空比為127/255的波形數據進行分許,得到其頻率為490.099Hz。
通過對基于Arduino與TimerOne定時器庫的頻率測量與基于LabVIEW和數據采集卡的數據對比與分析,得出頻率測量非常準確。
圖7 占空比為245/255時的波形
2.4搭建測量轉速的平臺
在驗證了基于Arduino與TimerOne定時器庫的頻率測量的準確性之后,我們就可以著手搭建一個直流電機轉速測量系統。
2.4.1 硬件平臺
直流電機轉速測量系統的直流電機和編碼器有兩者分離式,使用聯軸器將兩者連接起來,也有帶有編碼器的直流電機,此處為了簡化設計,直接選用帶有編碼器的直流電機。JGB37-371-12V-228RPM帶有編碼器的直流減速電機如圖8所示,額定電壓為12V,額定空載轉速為228rpm,其編碼器為334線增量式光電編碼器,其接口有6根數據線,黃色和橙色是電機電源,綠色和白色是AB相脈沖輸出,紅色和黑色是編碼器的電源端和接地端。
圖9 OCROBOT Motor Shield
OCROBOT Motor Shield 是基于Arduino Motor Shield 設計的增強版本的電機驅動器,如圖9所示,電機驅動器采用獨立供電、GND分離技術,且與Arduino控制器之間采用光耦隔離,這充分保證了Arduino控制器在大負載、大功率、急剎車、瞬時正反轉等惡劣電磁環境下的穩定性。需要注意的是:Arduino控制器與電機驅動器應使用兩塊電池或者兩個獨立的電源,保證電機驅動板與Arduino控制板電源完全獨立,從而保證其電氣隔離性。OCROBOT Motor Shield的I/O口的控制功能如表2所示,如果使用電機時還會接駁其他設備應避免占用這些I/O口。
表2 OCROBOT Motor Shield的控制引腳
功能
|
電機A
|
電機B
|
方向
|
D12
|
D13
|
速度(PWM)
|
D3
|
D11
|
制動(剎車)
|
D9
|
D8
|
搭建的直流電機轉速測量系統如圖10所示。OCROBOT Motor Shield 直接堆疊在Arduino Uno控制器上,OCROBOT Motor Shield采用7.4V的鋰電池供電,Arduino Uno控制器使用方口USB線連接至計算機上,提供電源且可以方便的通過串口上傳數據至計算機上。電機的黃色和橙色連接至OCROBOT Motor Shield電機接口A,綠色和白色分別連接至Arduino Uno控制器的數字端口2、3,紅色和黑色連接至Arduino Uno控制器的電源端口5V、GND。
圖10 直流電機轉速測量系統
2.4.2 軟件設計
由于JGB37-371-12V-228RPM直流減速電機的編碼器輸出AB相脈沖,為了充分利用兩相脈沖以提高測量準確性,在程序代碼2轉速測量程序中的attachInterrupt(0, counter, RISING)之后增加如下代碼,將B相脈沖輸出也用來計數,以實現2倍頻測量。JGB37-371-12V-228RPM直流減速電機的編碼器為334線增量式光電編碼器,也就說電機旋轉一圈輸出334個脈沖,2倍頻之后即為668個脈沖。
attachInterrupt(1, counter, RISING);//設置編碼器B相位上升沿中斷
修改完編碼器部分,需要增加電機驅動部分的代碼,以實現驅動直流電機旋轉。由于硬件上將直流電機的電源線接在L298P的A端口,其控制信號為3、9和12,分別為PWM信號、制動信號和方向信號。需要在void setup()中的delay(2000)之后增加如下代碼。當PWM值為80時,串口輸出的轉速如圖8所示,且當PWM低于80時,減速電機輸出軸不轉動;將PWM設置為255時,串口輸出的轉速如圖9所示。
pinMode(12,OUTPUT);
analogWrite(3,80); //設置PWM值
3.轉速的比例控制
3.1PID控制方法
PID控制器(比例-積分-微分控制器),由比例單元P、積分單元I和微分單元D組成。通過Kp,Ki和Kd三個參數的設定來實現對某個變量的實時控制,主要適用于基本上線性,且動態特性不隨時間變化的系統。
PID控制器是一個在工業控制應用中常見的反饋控制方法,其原理如圖10所示,其將采集的數據和設定參考值進行比較,然后將這個差值通過PID三個模塊計算出新的控制值用于執行,計算差值的目的是讓系統的數據達到或者保持在設定的參考值。PID控制器可以根據歷史數據和差別的出現率來調整輸入值,使系統更加準確而穩定。
圖10 PD控制基本原理
3.2 轉速比例控制的程序設計
實現了電機轉速的測量,下面就要對電機轉速進行比例控制了。為了提高控制系統響應的速度,將程序代碼2轉速測量程序中的定時時間更改為10毫秒,也就是轉速的采樣頻率為100Hz,且由圖8和圖9可知,電機減速前的1秒鐘轉速在4500和12650之間,即10毫秒的轉速在45至127之間,此處將轉速設置為100,比例系數設置為3。轉速比例控制的程序設計如程序代碼3所示。
程序代碼3:轉速比例控制的程序設計
#include
#define Kp 3
#define set_point 100
long counter_val[2] = {0,0};
byte CurCnt = 0;
int j=0;
int output_value=0;
void setup()
{
}
void loop()
{
if(output_value <0) //限制PWM在0-255范圍內
}
//外部中斷處理函數
void counter()
{
}
//定時器中斷處理函數
void timerIsr()
{
}
通過串口輸出的電機實際轉速與PWM值的數據如圖11和圖12所示。其中圖11為系統剛啟動的時候,此時可以看出電機逐漸上升,達到128之后逐漸降至100以下,這屬于系統初期的振蕩;圖12是系統運行一段時間之后的轉速和PWM數據,轉速穩定在100±2,PWM穩定在145左右。
圖11 PWM為80時轉速數據
圖12 PWM為255時轉速數據
圖11和圖12中的串口輸出數據看起來沒有圖形那么直觀,為此我們使用LabVIEW2012和VISA 5.3編寫一個轉速顯示程序。前面板如圖13所示,程序框圖如圖14所示,其中的數據解析子VI的程序框圖如圖15所示,其功能是解析出串口數據中的轉速值和PWM值。
除了上位機顯示程序之外,我們還需要對轉速的比例控制程序進行部分修改,具體如下:
將
Serial.print( lTemp); //發送轉速數據
修改為
if((lTemp/100) ==0)
Serial.print( lTemp);
將
Serial.println(output_value); //發送PWM數據
修改為
if((output_value /100) ==0)
Serial.print(output_value);
圖13 LabVIEW上位機前面板
圖15 數據解析程序框圖
在LabVIEW上位機軟件上選擇Arduino Uno控制器對應的串口號,即可將電機的轉速和PWM值實時的顯示在LabVIEW前面板上,如圖16所示。
圖16 轉速和PWM顯示在LabVIEW上位機上
3.3 比例參數的整定及采樣時間設置
搭建LabVIEW上位機軟件的目的正是通過圖形化的顯示方式,觀察轉速和PWM的曲線來判斷比例系數的設置值是否合適,同時借助LabVIEW上位機軟件也可以較方便的實現PID控制參數的整定。下面我們在轉速采樣頻率為100Hz的情況下將多次調整比例系數且獲取其轉速和PWM曲線,并對其進行分析,以尋找到合適的比例系數,而且也是一個探索的實驗過程。
圖17為Kp=3時轉速和PWM波形圖,從圖中可以看出,系統前期的振蕩較大,在800ms內經過7次振蕩以后逐漸趨于穩定,且穩定之后的PWM波形變化較大,說明Kp的取值略過大,使得系統對轉速偏差過于敏感。
圖18為Kp=4時轉速和PWM波形圖,從圖中可以看出,由于Kp的取值過大,直接導致系統振蕩而不能正常工作。
圖18 Kp=4時轉速和PWM波形圖
圖19為Kp=2時轉速和PWM波形圖,從圖中可以看出,系統前期的振蕩幅度較大,次數較多,PWM在600ms內經過4次振蕩以后逐漸趨于穩定,且PWM波動較小,轉速在30ms時達到最大值,并在400ms內經過3次振蕩之后趨于穩定。
圖19 Kp=2時轉速和PWM波形圖
圖20為Kp=1時轉速和PWM波形圖,從圖中可以看出,系統前期的振蕩較小,PWM在400ms內經過2次振蕩之后逐漸趨于穩定,且PWM波形很小,轉速在30ms時達到最大值,并在400ms內經過2次小幅振蕩后逐漸趨于穩定。
圖20 Kp=1時轉速和PWM波形圖
圖21為Kp=0.5時轉速和PWM波形圖,從圖中可以看出,系統前期的振蕩較小,PWM在400ms內經過1次調整之后逐漸趨于穩定,且PWM波形很小,轉速在50ms時達到最大值,并在400ms內經過1次小幅調整后逐漸趨于穩定。轉速的上升速度略微有點慢。
圖21 Kp=0.5時轉速和PWM波形圖
圖22為Kp=0.3時轉速和PWM波形圖,從圖中可以看出,系統前期的振蕩較小,PWM在400ms內經過1次調整之后逐漸趨于穩定,且PWM波形很小,轉速在200ms時達到最大值,在400ms內經過1次小幅調整后逐漸趨于穩定。系統的超調量較小,且轉速的上升速度較慢,起始的響應較差。
圖22 Kp=0.3時轉速和PWM波形圖
圖23為Kp=0.1時轉速和PWM波形圖,從圖中可以看出,系統基本無振蕩,PWM在200ms之后逐漸趨于穩定,且PWM波形基本不變,轉速在300ms之后逐漸趨于穩定。系統的超調量非常小,且轉速的上升速度非常慢,起始的響應非常差。
圖23 Kp=0.1時轉速和PWM波形圖
綜合圖17-圖23的波形圖,根據圖24控制系統效果評判,得出比例系數在0.5~1之間比較合適,有較快的上升速度,超調量適當,穩定性較高。
圖24 控制系統效果評判
圖17~圖23是在轉速采樣頻率為100Hz的情況下調整比例系數獲取的轉速和PWM曲線,通過觀察曲線的形狀來尋求最優的比例系數。下面我們在比例系數為1的情況,分別更改采樣周期為50Hz和200Hz,即定時時間分別為20ms和5ms,20ms內的轉速為200,5ms內的轉速為50,轉速和PWM的曲線分別如圖25和圖26所示。與圖20相比,圖25的振蕩明顯過大,圖26的穩定時間過長,這說明比例系數和采樣速率有很大的關系,一般情況下,先確定采樣頻率,然后不斷調整比例系數。