文獻標識碼: B
文章編號: 0258-7998(2012)08-0033-04
隨著數(shù)字信息技術(shù)的不斷發(fā)展,,人們對伺服控制系統(tǒng)的實時性,、穩(wěn)定性和復雜性的要求越來越高,單靠順序結(jié)構(gòu)的軟件設(shè)計已經(jīng)不容易滿足上述要求,。目前很多伺服控制系統(tǒng)的控制器采用PC/104結(jié)構(gòu)或依賴上位計算機,,根據(jù)實際的控制系統(tǒng)需要擴展相應的控制電路,使得系統(tǒng)體積大,、成本高,、可靠性不易保證,,且用戶交互性不好。嵌入式Linux操作系統(tǒng)由于具有代碼開源,、可移植性,、軟硬件可裁剪性、資源豐富及支持多種硬件平臺和接口等特點,,并且從2.6版本以后的Linux實時性有了很大的提高,,正被越來越多地應用于伺服控制系統(tǒng)中。通過嵌入式Linux操作系統(tǒng)對控制系統(tǒng)的軟硬件資源進行分配,、調(diào)度,、控制和協(xié)調(diào),能夠充分發(fā)揮控制系統(tǒng)的性能,。ARM處理器以其體積小,、低功耗、低成本,、高性能,、文檔豐富及嵌入式軟件多等優(yōu)點而得到廣泛的應用。因此,,本文以ARM9和CPLD為硬件平臺,,在嵌入式Linux操作系統(tǒng)下設(shè)計了直流伺服控制系統(tǒng)。
1 硬件平臺
系統(tǒng)原理框圖[1]如圖1所示,。系統(tǒng)以ARM作為主控芯片,,主要負責運行操作系統(tǒng)并實現(xiàn)控制算法、人機交互和多機通信等,。CPLD EPM570T144主要負責從ARM接收數(shù)據(jù),,產(chǎn)生相應的PWM波;接收編碼器輸出信號,,并對其進行處理,,得到編碼器的值,將其送給ARM,,從而實現(xiàn)電機的閉環(huán)控制,。CPLD和ARM之間通過地址總線(13根)、數(shù)據(jù)總線(16根),、控制總線(片選,、讀寫使能信號等)與GPIO口(作為外部中斷使用)連接,即CPLD類似于ARM的一個外部存儲器(CPLD掛接在ARM的bank1存儲空間上,,地址空間為0x08000000~0x10000000),,ARM和CPLD的數(shù)據(jù)交換類似于對存儲器的讀寫操作。這種總線方式擴展,,使得系統(tǒng)數(shù)據(jù)交換快速,、操作簡單,。控制板通過JTAG,、UART,、USB和網(wǎng)口與上位機連接,在目標板和上位機之間建立交叉開發(fā)環(huán)境,,可在控制板和上位機之間實現(xiàn)程序下載調(diào)試,、文件傳輸和通信等,便于系統(tǒng)軟件開發(fā)和調(diào)試,。
2 CPLD程序設(shè)計
CPLD程序分為電機辨向,、四倍頻、編碼器脈沖計數(shù),、PWM波生成和總線數(shù)據(jù)讀寫5個模塊,,如圖2所示。采用VHDL語言,,依據(jù)自底向上設(shè)計的方法,,以便于程序開發(fā)和移植。
采用增量式編碼器,,需對編碼器輸出的ABZ碼進行處理[2],,經(jīng)過辨向、倍頻,、計數(shù)后得到編碼器值,。ARM與CPLD之間通過雙向總線交換數(shù)據(jù),CPLD讀取ARM寫入數(shù)據(jù)總線的數(shù)據(jù),,產(chǎn)生對應的PWM波,。當CPLD中的編碼器值可讀后,CPLD采用中斷方式通知ARM,,然后將編碼器值寫到數(shù)據(jù)總線上供ARM讀取。由于CPLD與ARM的其他外設(shè)共用數(shù)據(jù)總線,,所以在CPLD對總線進行操作時要特別注意,,除了CPLD往總線上寫數(shù)據(jù)外,其他時刻都應該將總線置為高阻態(tài),,以讓出總線的使用權(quán),,否則其他外設(shè)(如網(wǎng)口、ADC接口等)會因CPLD一直占用總線而不能正常工作,。
CPLD應用計數(shù)法產(chǎn)生PWM波[3],,CPLD時鐘頻率為100 MHz,設(shè)置PWM總計數(shù)值為8 000,。CPLD根據(jù)ARM給定的0~8 000的計數(shù)值對時鐘計數(shù),,產(chǎn)生兩路反相的PWM波,。為防止功率放大器的H橋同一側(cè)上下同時導通,一般設(shè)置有3~5 μs的死區(qū),,本設(shè)計中設(shè)置為5 μs的死區(qū),。
3 設(shè)備驅(qū)動設(shè)計
3.1 設(shè)備驅(qū)動簡介
設(shè)備驅(qū)動是連接應用程序與硬件設(shè)備的橋梁,驅(qū)動程序為應用程序提供了接口函數(shù),,用戶在應用程序中調(diào)用相應的接口函數(shù)便可實現(xiàn)對硬件設(shè)備的操作,,因此,驅(qū)動程序的開發(fā)是嵌入式系統(tǒng)開發(fā)的關(guān)鍵環(huán)節(jié),。Linux設(shè)備驅(qū)動分為字符設(shè)備驅(qū)動,、塊設(shè)備驅(qū)動和網(wǎng)絡(luò)設(shè)備驅(qū)動[4]。本文中控制板上移植了Linux2.6操作系統(tǒng),,該操作系統(tǒng)下需設(shè)計ARM讀寫CPLD的數(shù)據(jù)及對CPLD產(chǎn)生的中斷信號響應的驅(qū)動,,這一要求采用字符設(shè)備驅(qū)動來實現(xiàn)。應用程序通過系統(tǒng)調(diào)用對設(shè)備文件進行諸如read,、write等操作時,,系統(tǒng)調(diào)用通過設(shè)備文件的主設(shè)備號找到相應的設(shè)備驅(qū)動程序,然后讀取設(shè)備驅(qū)動程序中初始化的file_operations結(jié)構(gòu)體,,獲取相應操作(read/write等)對應的函數(shù)指針,,接著把控制權(quán)交給該函數(shù)。因此,,編寫設(shè)備驅(qū)動程序的主要工作就是編寫這些文件操作的接口函數(shù),,并填充file_operations的各個域。
3.2 設(shè)備驅(qū)動程序設(shè)計
為便于開發(fā)和調(diào)試,,設(shè)備驅(qū)動使用模塊的方式動態(tài)加載到內(nèi)核中去,。加載模塊的方式與以往的應用程序開發(fā)有很大的不同。以往在開發(fā)應用程序時都有一個main()函數(shù)作為程序的入口點,,而在驅(qū)動開發(fā)時卻沒有main()函數(shù),,模塊在調(diào)用insmod命令時被加載,此時的入口點為module_init()函數(shù),,在該函數(shù)中完成設(shè)備的注冊,、設(shè)備文件的創(chuàng)建和相關(guān)內(nèi)存及寄存器的地址映射。同樣,,模塊在調(diào)用rmmod命令時被卸載,,此時的入口點為module_exit()函數(shù),在該函數(shù)中將不用的資源返還給操作系統(tǒng),,把注冊的設(shè)備,、創(chuàng)建的設(shè)備文件及IO內(nèi)存映射等注銷掉。在設(shè)備完成注冊和加載之后,用戶的應用程序就可以對該設(shè)備進行一定的操作,,如read,、write等。而驅(qū)動就是用于實現(xiàn)這些操作,,在用戶應用程序調(diào)用相應入口函數(shù)時執(zhí)行相關(guān)的操作,,module_init()入口點函數(shù)則不需要完成其他如read、wirte之類的功能,。驅(qū)動程序需要定義和實現(xiàn)open,、read、write等函數(shù),,并填充到file_operations結(jié)構(gòu)中,,file_operations結(jié)構(gòu)把應用程序中的系統(tǒng)調(diào)用與驅(qū)動中對應的函數(shù)聯(lián)系在一起。file_operations結(jié)構(gòu)體如下所示:
static struct file_operations cpld_drv_fops = {
.owner = THIS_MODULE,
.write = cpld_drv_write,
.read = cpld_drv_read,
.open = cpld_drv_open,
.release = cpld_drv_close,
.fasync = cpld_drv_fasync,
};
其中,,write()函數(shù)實現(xiàn)向CPLD中寫入數(shù)據(jù),,read()函數(shù)實現(xiàn)ARM從CPLD讀取數(shù)據(jù)。設(shè)備驅(qū)動運行在內(nèi)核空間,,而應用程序運行在用戶空間,,設(shè)備驅(qū)動程序不能直接訪問用戶空間的地址,在read()和write()函數(shù)中分別調(diào)用內(nèi)核函數(shù)copy_to_user()和copy_from_user()實現(xiàn)數(shù)據(jù)的轉(zhuǎn)移,。read函數(shù)實現(xiàn)讀取CPLD中的編碼器值,,write函數(shù)實現(xiàn)將產(chǎn)生PWM波的計數(shù)值寫入CPLD中,這兩個函數(shù)實現(xiàn)了內(nèi)核空間與用戶空間的數(shù)據(jù)交換,。從驅(qū)動程序結(jié)構(gòu)看,,驅(qū)動程序由三部分組成:結(jié)構(gòu)體struct file_operations及其成員函數(shù)的實現(xiàn)、設(shè)備初始化module_init()和設(shè)備注銷module_exit(),。
讀寫CPLD需要對內(nèi)存進行讀寫操作[5],。CPLD產(chǎn)生的讀中斷信號連接到ARM的GPF1口,CPLD的使能信號由ARM的GPF0產(chǎn)生,,因此需要配置相應的寄存器,。驅(qū)動程序中需要對內(nèi)存和寄存器進行操作,本操作系統(tǒng)下不能直接對內(nèi)存和寄存器的物理地址進行操作,,需先將相應的內(nèi)存和寄存器的物理地址映射到內(nèi)核的虛擬地址空間,,通過對映射后的虛擬地址進行操作實現(xiàn)對寄存器和內(nèi)存的操作。
ARM對CPLD的讀操作采用異步通知和內(nèi)核中斷方式[5]實現(xiàn),,這樣可減少系統(tǒng)開支,。首先在驅(qū)動的open()函數(shù)中調(diào)用request_irq()函數(shù)注冊內(nèi)核中斷,,并在內(nèi)核中實現(xiàn)中斷處理函數(shù),,在內(nèi)核中斷處理函數(shù)中調(diào)用kill_fasyn()函數(shù)給指定的應用程序發(fā)送信號,通知應用程序CPLD中的編碼器值可讀。當CPLD無可讀中斷產(chǎn)生時,,將read()函數(shù)放入等待隊列,,主程序一直處于睡眠狀態(tài),而不是應用程序主動去調(diào)用read()函數(shù)來等待中斷的產(chǎn)生,,即采用異步通知方式,,調(diào)用內(nèi)核中的fasync_helper()函數(shù)來實現(xiàn)。當CPLD有可讀中斷產(chǎn)生時,,在中斷處理函數(shù)中通過kill_fasync()函數(shù),,向進程發(fā)送信號SIGIO,觸發(fā)應用程序中signal聲明的異步觸發(fā)函數(shù),,使用POLL_IN表明有數(shù)值可以讀取,。另外,要注意,,在進入中斷服務程序后,,首先通過中斷自旋鎖spin_lock_irq()關(guān)閉所有中斷,以防止其他中斷源中斷kill_fasync的工作,,在中斷服務程序結(jié)束時,,再通過spin_unlock_irq()打開中斷。中斷處理函數(shù)部分代碼如下:
spinlock_t lock;
static irqreturn_t eint1_irq(int irq, void *dev_id)
//中斷服務程序
{
spin_lock_irq(&lock),;//關(guān)閉中斷
kill_fasync (&eint1_async, SIGIO, POLL_IN);
//產(chǎn)生中斷后,,驅(qū)動向應用程序發(fā)送數(shù)據(jù)可讀信號
spin_unlock_irq(&lock);//開中斷
return IRQ_RETVAL(IRQ_HANDLED);
}
4 應用程序設(shè)計
在應用程序[6]中,,通過函數(shù)signal()注冊信號處理函數(shù),,以接收內(nèi)核發(fā)來的數(shù)據(jù)可讀信號。為了打開設(shè)備文件的異步觸發(fā)機制,,用戶程序需指定當前進程為內(nèi)核發(fā)送信號的接收進程,,可以通過fcntl系統(tǒng)調(diào)用的F_SETOWN命令來設(shè)置該值。用戶程序還必須通過另一個fcntl命令設(shè)置設(shè)備的FASYNC標志,,打開異步觸發(fā)機制,。只要內(nèi)核中有CPLD可讀中斷產(chǎn)生,輸入文件就會產(chǎn)生一個SIGIO信號,,信號發(fā)送給應用程序,,應用程序調(diào)用信號處理函數(shù)。在信號處理函數(shù)中讀取編碼器的值,,通過控制算法得到控制數(shù)據(jù)(即PWM波計數(shù)值),,然后將PWM波的計數(shù)值寫入到CPLD中。主程序流程圖如圖3所示,,部分代碼如下:
int main(int argc, char **argv)
{
int Oflags;
signal(SIGIO, signal_fun);//注冊信號處理函數(shù)
Init(argc,argv); //打開設(shè)備,,控制參數(shù)初始化
…
fcntl(fd_cpld, F_SETOWN, getpid());
//指定當前進程為接收信號進程
Oflags=fcntl(fd_cpld, F_GETFL);//返回當前的信號標志
fcntl(fd_cpld, F_SETFL, Oflags | FASYNC);
//打開異步觸發(fā)機制
while(1)
{
sleep(1000);//進程睡眠,等待內(nèi)核發(fā)送中斷信號
}
……
return 0;
}
由于Linux是多任務系統(tǒng),各個進程間采用一定的調(diào)度算法調(diào)度,,進程間會不時地切換,,因此編寫程序時要特別考慮系統(tǒng)進程調(diào)度的問題??刂瞥绦?qū)崟r性有一定的要求,,因此,要將控制程序進程設(shè)置為實時進程且要具有較高的進程調(diào)度優(yōu)先級,,同時控制程序中要盡量少地使用系統(tǒng)調(diào)用,,以保證控制系統(tǒng)的實時性。
5 實驗結(jié)果
控制板通過串口,、網(wǎng)口與計算機(裝有Linux系統(tǒng))建立交叉編譯環(huán)境,,程序在計算機上編譯調(diào)試。利用網(wǎng)線通過nfs(網(wǎng)絡(luò)文件系統(tǒng))服務,,在計算機和控制板之間實現(xiàn)網(wǎng)絡(luò)文件共享,,可直接在控制板上訪問計算機上的共享文件、執(zhí)行計算機上編譯好的程序,,無需將計算機上編譯好的程序下載到板子上,。這種交叉開發(fā)的方式將程序和實驗數(shù)據(jù)直接存儲在計算機上,可節(jié)省控制板上的存儲空間,,便于程序開發(fā)和進行實驗數(shù)據(jù)分析,。
實驗過程中,首先要對電機參數(shù)進行辨識,。電機參數(shù)辨識的方法[7-8]很多,,本實驗采用階躍響應法測得電機的模型參數(shù),近似為一階慣性環(huán)節(jié),。編碼器為增量式編碼器,,電機轉(zhuǎn)一圈產(chǎn)生20 000個碼,即一個碼值對應0.018°,,編碼器值采樣周期為2 ms,。將電機一個采樣周期內(nèi)轉(zhuǎn)過的角度值除以采樣周期作為速度反饋值,將電機轉(zhuǎn)過的角度進行累加得到位置反饋值,,電機最高轉(zhuǎn)速為900°/s,,最低轉(zhuǎn)速為9°/s,采用PI控制[9-10],。圖4為系統(tǒng)速度階躍響應曲線,,速度響應誤差為每1個采樣周期1個碼值。圖5為系統(tǒng)位置階躍曲線,,設(shè)定速度環(huán)最大速度為180°/s,。位置環(huán)采用抗積分飽和算法,,以消除因積分飽和引起的過大的超調(diào),位置階躍穩(wěn)態(tài)誤差為0,。圖6是系統(tǒng)的速度正弦跟蹤曲線,正弦引導函數(shù)為:v=180°sin(0.8πt),,跟蹤誤差在正反轉(zhuǎn)速度換向處跟蹤誤差較大,。
實驗結(jié)果表明,基于ARM9和CPLD硬件平臺,,在嵌入式Linux操作系統(tǒng)下,,系統(tǒng)能夠?qū)崿F(xiàn)等速跟蹤、位置定點和正弦跟蹤等功能,,滿足控制實時性要求,,可實現(xiàn)伺服控制。系統(tǒng)體積小,、成本低,、功耗小、接口豐富,、便于開發(fā),,且Linux系統(tǒng)具有很好的文件管理功能,有助于實驗數(shù)據(jù)的存儲和導出,,便于實驗結(jié)果分析,。系統(tǒng)進一步完善后可將控制程序設(shè)計成圖形界面,利用觸摸屏輸入和顯示伺服控制結(jié)果,,則可實現(xiàn)控制結(jié)果實時顯示,,可視化效果好,整個系統(tǒng)可脫離計算機工作,,具有廣泛的應用價值,。
參考文獻
[1] 李金洪,楊小軍.基于DSP和FPGA的經(jīng)緯儀控制系統(tǒng)設(shè)計[J].電子技術(shù)應用,,2010,,36(7):48-51.
[2] 鈔靖,王小椿,,姜虹.基于FPGA的光電編碼器四倍頻電路設(shè)計[J].儀表技術(shù),,2007(6):17-21.
[3] 耿偉松,于海東.基于CPLD的PWM發(fā)生器設(shè)計[J].制造業(yè)自動化,,2010,,32(6):151-153.
[4] 韋東山.嵌入式Linux應用開發(fā)完全手冊[M].北京:人民郵電出版社,2008.
[5] 宋寶華.Linux設(shè)備驅(qū)動詳解[M].北京:人民郵電出版社,,2008.
[6] 孫程建.基于Linux的嵌入式數(shù)控系統(tǒng)底層軟件設(shè)計[D].武漢:武漢科技大學,,2007.
[7] 王帥,,陳濤,李洪文,,等.光電跟蹤伺服系統(tǒng)的頻率特性測試與模型辨識[J].光學精密工程,,2009,17(1):78-83.
[8] 王偉國,,陳濤,,沈湘衡.直流伺服系統(tǒng)機械時間常熟測試方法的研究[J].儀器儀表學報,2005,,26(8):66-70.
[9] 李洪文.基于內(nèi)模PID控制的大型望遠鏡伺服系統(tǒng)[J].光學精密工程,,2009(2):327-332.
[10] 劉金錕.先進PID控制及其MATLAB仿真[M].北京:電子工業(yè)出版社,2003.