新聞中心

        EEPW首頁 > 測試測量 > 設(shè)計應(yīng)用 > 基于Arduino與LabVIEW的直流電機轉(zhuǎn)速控制系統(tǒng)

        基于Arduino與LabVIEW的直流電機轉(zhuǎn)速控制系統(tǒng)

        作者: 時間:2017-01-06 來源:網(wǎng)絡(luò) 收藏
        多數(shù)的Arduino控制器都是基于Atmel公司的AVR系列單片機的,AVR單片機的片內(nèi)資源非常的豐富,有ADC、定時器、外部中斷、SPI、IIC、PWM等功能,且Arduino控制器的PWM采用的是定時器相位修正PWM(頻率約為490Hz)和快速PWM(頻率約為980Hz,Uno的5、6和Leonardo的3、11),這也就導(dǎo)致了全部的定時器都被被占用了,從而不能很方便的使用定時器設(shè)置一個中斷來實現(xiàn)一個周期的任務(wù),而一般需要通過讀取系統(tǒng)已運行時間來判斷定時時間是否已經(jīng)達到。例如,通過增量式編碼器來測量電機的轉(zhuǎn)速,常規(guī)的單片機的程序架構(gòu)是通過定時器來實現(xiàn)精確的時間定時,并利用外部中斷來實現(xiàn)對脈沖數(shù)目的計數(shù),然后計算出一定時間內(nèi)脈沖的數(shù)目,從而得到轉(zhuǎn)速數(shù)值并輸出。

        直流電機是Arduino機器人制作中的主要動力來源,但是由于電機的參數(shù)一致性有所差別,即使是相同型號的電機在相同電壓下的轉(zhuǎn)速都不完全相同,而且在帶負載或負載不同的情況下,更加會導(dǎo)致電機轉(zhuǎn)速發(fā)生變化,這就會導(dǎo)致制作的Arduino輪式機器人不能實現(xiàn)直線行走,因為這是一個開環(huán)控制,沒有任何反饋信號返回。如果給直流電機加上編碼器作為反饋器件,也就可以測量得到電機的當前轉(zhuǎn)速,如果將其與設(shè)定值計算差值,并通過PID算法計算得到新的控制信號,從而可以動態(tài)的測量和控制電機的轉(zhuǎn)速,形成一個閉環(huán)控制系統(tǒng)。

        本文引用地址:http://www.104case.com/article/201701/337030.htm

        下面我們利用帶有編碼器的直流電機、Arduino控制器、直流電機驅(qū)動板和LabVIEW上位機軟件以實驗探索的形式來設(shè)計一個直流電機轉(zhuǎn)速比例控制實驗。

        1.TimerOne定時器庫

        1.1下載及使用方法

        TimerOne定時器庫使用AVR單片機內(nèi)部的定時器1實現(xiàn)定時中斷的功能,其下載地址為:https://code.google.com/p/arduino-timerone/,只需要更改幾個參數(shù)即可使用定時器中斷來實現(xiàn)周期性執(zhí)行的任務(wù)。需要注意的是,如果使用了TimerOne定時器庫,也就不能在相應(yīng)的引腳輸出PWM電壓,Uno上的定時器與PWM引腳的關(guān)系如表1所示。

        表1定時器與PWM引腳的關(guān)系

        定時器

        OC0A

        OC0B

        OC1A

        OC1B

        OC2A

        OC2B

        PWM引腳

        6

        5

        9

        10

        11

        3

        TimerOne定時器庫函數(shù)庫中自帶的ISRBlink程序如程序代碼1所示,可以實現(xiàn)13號管腳上LED的5Hz頻率的閃爍。

        程序代碼1:ISRBlink示例程序

        #include

        void setup() {

        pinMode(13, OUTPUT);

        Timer1.initialize(100000); //設(shè)置定時器中斷時間,基本單位為微秒,如設(shè)置為100000,則定時時間為0.1秒,頻率為10Hz。

        Timer1.attachInterrupt( timerIsr ); //設(shè)置用戶自定義的定時器中斷服務(wù)函數(shù),每發(fā)生一次定時器中斷,均會執(zhí)行一次定時器中斷服務(wù)函數(shù)。

        }

        void loop(){

        //主函數(shù),用于執(zhí)行非周期性任務(wù)

        }

        void timerIsr(){

        //反轉(zhuǎn)I/O口電平

        digitalWrite( 13, digitalRead( 13 ) ^ 1 );

        }

        1.2評估定時時間的準確性

        僅僅憑靠眼睛不能判斷定時時間是否準確,下面我們設(shè)計一個實驗來評估定時時間的準確性。我們需要將上面示例代碼中的Timer1.initialize(100000)更改為Timer1.initialize(1000),digitalWrite( 13, digitalRead( 13 ) ^ 1 )更改為digitalWrite(2, digitalRead( 2) ^ 1 ),通過反轉(zhuǎn)I/O的電平實現(xiàn)數(shù)字端口2輸出500Hz的近似方波。

        同時,我們使用NI USB-6009便攜式數(shù)據(jù)采集卡和LabVIEW 2012軟件實現(xiàn)一個簡易的模擬量采集器,將Arduino控制器上的數(shù)字端口2和GND分別與NI USB-6009便攜式數(shù)據(jù)采集卡上的AI0/AI0+和AI4/AI0-相連接,NI USB-6009便攜式數(shù)據(jù)采集卡接口示意圖如圖1所示,Arduino Uno控制器與USB-6009便攜式數(shù)據(jù)采集卡的連接圖如圖2所示。然后使用10kps的采樣率,5秒的采樣時間的參數(shù)采集Arduino控制器上的數(shù)字端口2輸出的方波信號,取其前20ms的波形如圖3所示,通過波形頻率分析工具測量得到其頻率為499.901Hz。

        另外,我們又將定時時間設(shè)置為100微秒、50微秒和25微秒,并使用NI USB-6009便攜式數(shù)據(jù)采集卡和LabVIEW 2012軟件以45kps的采樣率和2秒的采樣時間分別采集了數(shù)字端口2輸出的波形數(shù)據(jù)并進行頻率分析,得到其頻率分別為4999.01Hz,9998.03Hz,19996Hz。從以上數(shù)據(jù)對比分析可知,定時器的定時時間非常準確,頻率測量誤差主要來自于I/O反轉(zhuǎn)操作延時導(dǎo)致的。

        最后,我們還測試了OCROBOT MEGA 2560控制器、Arduino Uno控制器山寨版輸出的500Hz的方波信號頻率,分別為500.435Hz和499.764Hz。

        圖1 NI USB-6009接口示意圖

        圖2 NI USB-6009與Arduino連接示意圖

        圖3定時器中斷產(chǎn)生的500Hz方波信號

        2.轉(zhuǎn)速測量

        2.1測量轉(zhuǎn)速方法

        測量轉(zhuǎn)速方法有3種,分別為測頻法(M法)、測周法(T法)及混合法(M/T法)。

        測頻法是在一定時間內(nèi),通過測量旋轉(zhuǎn)引起的單位時間內(nèi)的脈沖數(shù),實現(xiàn)對旋轉(zhuǎn)軸轉(zhuǎn)速測量的一種方法,適用于高、中轉(zhuǎn)速的測量。該法本質(zhì)上屬于定時測角法,為提高測量的準確度,有時采用多標記或開齒的方法,其不確定度主要取決于時間測量和計數(shù)量化。

        測周法是在轉(zhuǎn)速脈沖的間隔內(nèi),用時鐘脈沖來測量轉(zhuǎn)速的一種方法,適合于低轉(zhuǎn)速測量。該法實際上就是定角測量法,即用時標填充的方法來測量相當于某一旋轉(zhuǎn)角度的時間間隔。在高、中轉(zhuǎn)速時,可采用多周期平均來提高測量準確度,其不確定度主要取決于時間測量、計數(shù)量化及觸發(fā)的不確定度。

        混合法是在測頻法的基礎(chǔ)上,吸取測周法的優(yōu)點匯集而成的一種轉(zhuǎn)速測量方法。它是在轉(zhuǎn)速傳感器輸出脈沖啟動定時脈沖的同時,計取傳感器輸出脈沖個數(shù)和時鐘脈沖個數(shù),而當?shù)竭_測量時間時,先停止對傳感器輸出脈沖的計數(shù),在下一個定時脈沖啟動之前再停止時鐘脈沖的計數(shù)。因此,該種方法可在較寬的范圍內(nèi)使用。

        此處,我們選擇測頻法來測量轉(zhuǎn)速,其工作原理為:當被測信號在特定時間段T內(nèi)的周期個數(shù)為N時,則被測信號的頻率f=N/T。

        2.2轉(zhuǎn)速測量程序設(shè)計

        利用TimerOne定時器庫來實現(xiàn)定時,通過外部中斷對電機編碼器輸出的脈沖進行計數(shù),計數(shù)值除以定時時間即為一定時間內(nèi)的轉(zhuǎn)速。實現(xiàn)1秒內(nèi)轉(zhuǎn)速測量的程序如程序代碼2所示。

        程序代碼2:轉(zhuǎn)速測量程序

        #include

        long counter_val[2] = {0,0};//定義數(shù)組,用于存放外部中斷計數(shù)值

        byte CurCnt = 0;//定義當前計數(shù)器標志,用于判斷當前正在計數(shù)的數(shù)組

        int j=0;//定義定時器中斷標志,用于判斷是否發(fā)生中斷

        void setup() {

        delay(2000);

        Serial.begin(115200);//初始化波特率為115200

        attachInterrupt(0, counter, RISING);//設(shè)置中斷方式為上升沿

        Timer1.initialize(1000000); //設(shè)置定時器中斷時間,單位微秒,此處為1秒

        Timer1.attachInterrupt( timerIsr ); //打開定時器中斷

        interrupts();//打開外部中斷

        }

        void loop()

        {

        long lTemp = 0; //定義臨時存儲數(shù)據(jù)變量

        if(j==1)//判斷是否發(fā)生定時器中斷,即定時時間是否到達

        {

        j=0; //清除定時器中斷標志位

        if((CurCnt&0x01) == 0) //當前使用的是偶數(shù)計數(shù)器,則上次頻率值存放在第二個元素中

        {

        lTemp = counter_val[1];//讀取數(shù)組第二個元素中的數(shù)值

        counter_val[1]=0;//讀完清除原來的數(shù)值,以便下次使用

        }

        else//當前使用的是奇數(shù)計數(shù)器,則上次頻率值存放在第一個元素中

        {

        lTemp = counter_val[0];//讀取數(shù)組第二個元素中的數(shù)值

        counter_val[0]=0;//讀完清除原來的數(shù)值,以便下次使用

        }

        Serial.print("S");//發(fā)送幀頭大寫S

        Serial.print( lTemp);//發(fā)送頻率數(shù)據(jù),并回車換行

        }

        }

        //外部中斷處理函數(shù)

        void counter()

        {

        //通過當前計數(shù)器來實現(xiàn)對外部中斷計數(shù)值存儲的切換

        counter_val[CurCnt& 0x01] += 1;//發(fā)生一次中斷則加1

        }

        //定時器中斷處理函數(shù)

        void timerIsr()

        {

        j=1;//置位定時器中斷標志位

        CurCnt++; //當前計數(shù)器的值加1,實現(xiàn)另一個計數(shù)值切換

        }

        2.3驗證頻率測量的準確性

        前面提到了Arduino的模擬輸出(PWM)的頻率約為490Hz,且轉(zhuǎn)速測量采用的是測頻法,此時用來正好來驗證一下程序設(shè)計的正確性。在上面的轉(zhuǎn)速測量程序中的void setup()里面delay(2000)之前增加如下代碼,以產(chǎn)生方波。串口輸出的頻率測量結(jié)果如圖4所示。


        上一頁 1 2 3 下一頁

        評論


        技術(shù)專區(qū)

        關(guān)閉
        主站蜘蛛池模板: 濮阳市| 沭阳县| 伊川县| 信阳市| 花垣县| 淅川县| 维西| 永昌县| 五常市| 鹤庆县| 阿拉善盟| 上高县| 鹤峰县| 凤山县| 拉萨市| 怀来县| 伊金霍洛旗| 宿州市| 正镶白旗| 抚顺县| 临城县| 桑日县| 新津县| 松滋市| 嵊泗县| 昌吉市| 互助| 分宜县| 抚松县| 普宁市| 邹平县| 土默特右旗| 天峻县| 滨海县| 蒲城县| 托克逊县| 南康市| 淳安县| 沁阳市| 竹山县| 县级市|