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