FPGA 非常適合精密電機控制,在這個項目中,我們將創(chuàng)建一個簡單的電機控制程序,在此基礎(chǔ)上可以構(gòu)建更復(fù)雜的應(yīng)用。
介紹
我們可以用一個簡單的 8 位微控制器來控制電機,輸出一個簡單的脈寬調(diào)制波形。然而,當(dāng)想要進行精密或高級電機控制時,沒有什么比 FPGA 的確定性和實時響應(yīng)更好的了。接口的靈活性還使得可以通過單個設(shè)備控制多個電機,從而提供更加集成的解決方案。
首先,我們將學(xué)習(xí)一些有關(guān)電機控制理論的知識,并創(chuàng)建一個簡單的示例。我們都知道,我們可以通過PWM信號來驅(qū)動直流電機并控制其速度。然而,高效、精確地驅(qū)動它需要對電機控制理論有更多的了解。
電機
不管你信不信,我在大學(xué)最喜歡的課程之一是控制理論。在該模塊中,我們研究了交流電機和直流電機,了解理論和實際用例。有多種類型的交流電機由交流電源供電,可分為同步電機和感應(yīng)電機。例如,交流電機通常用于泵和壓縮機。
直流電機分為有刷電機和無刷電機兩種。在兩種類型中,有刷是最容易驅(qū)動的,因為它們只需要一個電源。在有刷直流電機中,電刷向連接有轉(zhuǎn)子和線圈的換向器提供電流。電流在線圈中感應(yīng)出電場,該電場被外部磁體(定子)排斥。為了確保旋轉(zhuǎn),換向器的設(shè)計使得電流反向流動以確保連續(xù)旋轉(zhuǎn)。
第二種類型的直流電機是無刷電機,它們的驅(qū)動稍微復(fù)雜一些,因為它們沒有換向器。相反,磁體安裝在轉(zhuǎn)子上,線圈纏繞在定子周圍,這樣線圈的電流就可以從外部控制和排序。
兩者中最容易控制的是有刷直流電機,所以我們就以這類電機為例。
脈寬調(diào)制驅(qū)動
使用 PWM 驅(qū)動電機的理論是,可以控制電機得到的平均電壓,從而控制其速度。在 PWM 信號占空比為 100% 時,電機處于滿電壓并全速運行。如果提供 10% 的占空比,電機就會以其全速的 10% 運行。
然而,為了有效地運行電機,我們需要正確確定 PWM 周期。直流電機具有串聯(lián)電感和串聯(lián)電阻,這意味著電機將充當(dāng)?shù)屯?a href="http://hljzzgx.com/tags/濾波器/" target="_blank">濾波器。頻率削減為
其中時間常數(shù)由 L/R 給出 - 我們可以從電機數(shù)據(jù)表中獲得這些值。
因此,為了確保穩(wěn)定的速度,我們需要選擇高于電機頻率截止的 PWM 頻率,以確保觀察到直流分量。
因此,我們要選擇一個至少是截止頻率 5 倍的頻率。
FPGA
為了開始這個項目,我們首先要創(chuàng)建一個針對 FPGA 板的硬件設(shè)計。
開始創(chuàng)建一個新項目
為項目命名
選擇 RTL 項目但不指定來源
創(chuàng)建項目后,創(chuàng)建一個新的框圖
從“板”選項卡將系統(tǒng)時鐘拉到框圖上
從 IP 庫添加 MicroBlaze 處理器
運行塊自動化連接,選擇本地內(nèi)存大小為32KB并取消選中中斷控制器
添加 AXI 定時器
運行連接自動化
打開時鐘向?qū)Р⑷∠x擇復(fù)位輸入
添加 GPIO
重新定制GPIO為1位寬,僅輸出
選擇 GPIO 輸出和 AXI 定時器 PWM 并將其設(shè)引出
完成后應(yīng)如下所示。
綜合完成后,我們可以打開綜合視圖并將 IO 分配給 GPIO 和定時器輸出 - 對于 GPIO,引腳是 J1,對于 PWM,引腳是 L2
構(gòu)建比特流并導(dǎo)出平臺
vitis設(shè)計
打開Vitis創(chuàng)建一個新的應(yīng)用程序項目并選擇剛剛導(dǎo)出的XSA。
輸入項目名稱
選擇獨立
創(chuàng)建一個新的 hello world 應(yīng)用程序
應(yīng)用軟件非常簡單,我們將根據(jù)所需的 PWM 周期以及所需的占空比配置 AXI 定時器。
?
#include?#include?"platform.h" #include?"xil_printf.h" #include?"xtmrctr.h" #define?TMRCTR_DEVICE_ID????????XPAR_TMRCTR_0_DEVICE_ID #define?PWM_PERIOD??????????????1000000????/*?PWM?period?in?(500?ms)?*/ #define?TMRCTR_0????????????????0????????????/*?Timer?0?ID?*/ #define?TMRCTR_1????????????????1????????????/*?Timer?1?ID?*/ #define?CYCLE_PER_DUTYCYCLE?????10???????????/*?Clock?cycles?per?duty?cycle?*/ #define?MAX_DUTYCYCLE???????????100??????????/*?Max?duty?cycle?*/ #define?DUTYCYCLE_DIVISOR???????2????????????/*?Duty?cycle?Divisor?*/ XTmrCtr?TimerCounterInst; void?display_menu() { //Clear?the?screen xil_printf("?33[2J"); //Display?the?main?menu xil_printf("******************************************* "); xil_printf("****??????www.adiuvoengineering.com????**** "); xil_printf("****??????Motor?Control?Example????????**** "); xil_printf("******************************************* "); xil_printf(" "); xil_printf("???MM10?Motor?Control??? "); xil_printf("------------------------------------------ "); xil_printf(" "); xil_printf("Select?a?Speed: "); xil_printf("??(1)???-?Stop "); xil_printf("??(2)???-?25?%? "); xil_printf("??(3)???-?33?%? "); xil_printf("??(4)???-?50?%? "); xil_printf("??(5)???-?66?%? "); xil_printf("??(6)???-?75?%? "); xil_printf("??(7)???-?100?%? "); xil_printf(" "); } void?set_pwm(u32?cycle) { ?u32?HighTime; ?XTmrCtr_PwmDisable(&TimerCounterInst); ?HighTime?=?PWM_PERIOD?*?((?float)?cycle?/?100.0?); ?XTmrCtr_PwmConfigure(&TimerCounterInst,?PWM_PERIOD,?HighTime); ?XTmrCtr_PwmEnable(&TimerCounterInst); } int?main() { ?u8??Div; ?u32?Period; ?u32?HighTime; ?char?key_input; ?u8?DutyCycle; ????init_platform(); ????print("Hello?World "); ????print("Successfully?ran?Hello?World?application"); ????XTmrCtr_Initialize(&TimerCounterInst,?TMRCTR_DEVICE_ID); ????Div?=?DUTYCYCLE_DIVISOR; ????XTmrCtr_PwmDisable(&TimerCounterInst); ?Period?=?PWM_PERIOD; ?HighTime?=?PWM_PERIOD?/?Div--; ?XTmrCtr_PwmConfigure(&TimerCounterInst,?Period,?HighTime); ?XTmrCtr_PwmEnable(&TimerCounterInst); ?while(1){ ??display_menu(); ??read(1,?(char*)&key_input,?1); ??xil_printf("Echo?%c ",key_input); ??switch?(key_input)?{ ??case?'1':?//stop ??XTmrCtr_PwmDisable(&TimerCounterInst); ??break; ??case?'2':?//25% ???xil_printf("25% "); ??DutyCycle?=?25; ??set_pwm(DutyCycle); ??break; ??case?'3':?//33% ??DutyCycle?=?33; ??set_pwm(DutyCycle); ??break; ??case?'4':?//50% ??DutyCycle?=?50; ??set_pwm(DutyCycle); ??break; ??case?'5':?//66% ??DutyCycle?=?66; ??set_pwm(DutyCycle); ??break; ??case?'6':?//75% ??DutyCycle?=?75; ??set_pwm(DutyCycle); ??break; ??case?'7':?//100% ??DutyCycle?=?100; ??set_pwm(DutyCycle); ??break; ??} ?} ????cleanup_platform(); ????return?0; }
?
當(dāng)然,我選擇的電機包含兩個霍爾效應(yīng)傳感器.旋轉(zhuǎn)方向可以通過一個霍爾效應(yīng)傳感器位于另一個霍爾效應(yīng)傳感器前面的輸出來確定。
順時針旋轉(zhuǎn)
逆時針旋轉(zhuǎn)
我們可以使用脈沖頻率來確定電機的速度,我們將在后面項目中更詳細(xì)地研究這一點。
審核編輯:劉清
評論
查看更多