目錄
- 前言
- 舵機控制原理
- PWM原理
- 舵機相關知識
- 實作程序
- PWM模塊配置
- 初步效果
- 轉速、方向控制
- 注意事項
- 總結
前言
前兩天用F28335控制四位共陽數碼管玩了一下(鏈接在這),這兩天換一個,用F28335來控制舵機,
舵機控制原理
PWM原理
PWM(Pulse Width Modulation),指脈沖寬度調制,是一種模擬控制方式,它的思想很簡單,就是一種等效的思想:一個5V的信號作用0.5秒可以等效成一個2.5V的信號作用1秒,所以通過控制信號的通斷時間,就可以在恒壓信號的基礎上輸出不同大小的信號,
舵機相關知識
舵機由外殼、電機、控制電路以及減速器組成,因為常用于舵面(飛行器操縱面)的控制,所以叫舵機,根據轉動范圍,舵機可以分為90°、180°和360°舵機等,我手頭上的這個是360°舵機,所以它可以做整圈轉動,360°舵機和其他舵機不一樣的是,其他舵機可以控制其轉動角度,而360°舵機只能控制其轉動速度和轉動方向,
(圖片來自網路,侵刪)
舵機一般有三根線,分別是電源線、地線以及信號線,舵機的控制是通過在信號線上施加不同占空比的PWM信號而實作的,
實作程序
PWM模塊配置
PWM信號的配置主要是周期以及占空比,和控制開關器件不一樣,由于這里PWM是作為舵機的控制信號,不需要避免開關器件同時接通的問題,因此不需要對死區做出配置,
首先進行相關的宏定義,以便理解和后期修改,包括時鐘頻率、PWM頻率和周期,代碼如下:
#if (CPU_FRQ_150MHZ)
#define CPU_CLK 150e6 // SYSCLK = 150MHz
#endif
#if (CPU_FRQ_100MHZ)
#define CPU_CLK 100e6 // SYSCLK = 100MHz
#endif
#define TBCTLVAL 0x200E // Up-down cnt, timebase = SYSCLKOUT 控制暫存器的值
#define SERVO_CLK 50 // SERVOCLK = 50Hz
#define SERVO_SP CPU_CLK/(2*SERVO_CLK*8*12) // 周期暫存器的值,由于采用增減計數,所以周期暫存器的值為系統時鐘頻率除PWM頻率再除2
然后需要對PWM的輸出管腳進行配置,用的是 InitEPwm1Gpio 函式,這個函式是自帶的例程函式,位于 DSP2833x_EPwm.c 檔案中,代碼如下:
void InitEPwm1Gpio(void)
{
EALLOW;
/* Enable internal pull-up for the selected pins */
// Pull-ups can be enabled or disabled by the user.
// This will enable the pullups for the specified pins.
// Comment out other unwanted lines.
GpioCtrlRegs.GPAPUD.bit.GPIO0 = 0; // Enable pull-up on GPIO0 (EPWM1A)
GpioCtrlRegs.GPAPUD.bit.GPIO1 = 0; // Enable pull-up on GPIO1 (EPWM1B)
/* Configure ePWM-1 pins using GPIO regs*/
// This specifies which of the possible GPIO pins will be ePWM1 functional pins.
// Comment out other unwanted lines.
GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1; // Configure GPIO0 as EPWM1A
GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 1; // Configure GPIO1 as EPWM1B
EDIS;
}
最后,需要對PWM的各個模塊進行配置,包括時基模塊、比較計數模塊、動作模塊、死區模塊、錯誤聯防模塊、事件觸發模塊以及斬波模塊,不過由于我們這個是基礎應用,因此死區模塊、錯誤聯防模塊、事件觸發模塊和斬波模塊我們實際上并沒有涉及,配置代碼如下:
void ePWM1Setup()
{
// clear time-base submodule
EPwm1Regs.TBSTS.all = 0; // clear TBSTS
EPwm1Regs.TBPHS.half.TBPHS = 0; // set TBPHS to 0
EPwm1Regs.TBCTR = 0; // clear TB counter
// configure counter-compare submodule
EPwm1Regs.CMPCTL.all = 0x50; // SHDWAMODE = 1, SHDWBMODE = 1, disable shadow mode
EPwm1Regs.CMPCTL.bit.SHDWAMODE = 0;
EPwm1Regs.CMPCTL.bit.SHDWBMODE = 0; // enable shadow mode
EPwm1Regs.CMPA.half.CMPA = SERVO_SP * (1 - 0.05); // dutycycle of ePWMxA
EPwm1Regs.CMPB = SERVO_SP / 8; // dutycycle 0f ePWMxB
// configure action-qualifier submodule
EPwm1Regs.AQCTLA.all = 0x0060; // CAD = 01: EPwm1A = 0 when CTR = CMPA and the counter is decrementing;
// CAU = 10: EPwm1A = 1 when CTR = CMPA and the counter is incrementing;
EPwm1Regs.AQCTLB.all = 0x0900; // CBD = 10: EPwm1B = 1 when CTR = CMPB and the counter is decrementing;
// CAU = 01: EPwm1A = 0 when CTR = CMPB and the counter is incrementing;
EPwm1Regs.AQSFRC.all = 0; // no effect under immediate mode
EPwm1Regs.AQCSFRC.all = 0; // continuous force disabled
// configure dead-band submodule
EPwm1Regs.DBCTL.all = 0x03; // POSEL = 00: Neither EPWMxA nor EPWMxB is inverted (default);
// OUT_MODE = 11: Dead-band is fully enabled for both rising-edge delay on output EPWMxA and falling-edge
// delay on output EPWMxB;
// IN_MODE = 00: EPWMxA In is the source for both falling-edge and rising-edge delay.
EPwm1Regs.DBRED = 0;
EPwm1Regs.DBFED = 0; // delay for rise-edge and fall-edge respectively
// configure trip-zone submodule
EPwm1Regs.TZSEL.all = 0; // clear all TZ registers because we don't use it
EPwm1Regs.TZCTL.all = 0;
EPwm1Regs.TZEINT.all = 0;
EPwm1Regs.TZFLG.all = 0;
EPwm1Regs.TZCLR.all = 0;
EPwm1Regs.TZFRC.all = 0;
// configure event-trigger submodule
EPwm1Regs.ETSEL.all = 0x000A; // SOCBEN = 0 SOCAEN = 0: EPWMxSOCB EPWMxSOCA disabled;
// INTEN = 1: interrupt enabled;
// INTSEL = 010: interrupt when TBCTR = TBPRD
EPwm1Regs.ETFLG.all = 0;
EPwm1Regs.ETCLR.all = 0;
EPwm1Regs.ETFRC.all = 0;
EPwm1Regs.ETPS.bit.INTPRD = 11;
// configure PWM-chopper submodule
EPwm1Regs.PCCTL.all = 0; // clear PCCTL register because we don't use it
// configure time-base submodule
EPwm1Regs.TBCTL.all = 0x2D8E; // FREE,SOFT = 00: Stop after the next time-base counter increment or decrement;
// PHSDIR = 1: Count up after the synchronization event
// CLKDIV = 011 HSPCLKDIV = 011: TBCLK = SYSCLKOUT/8/6
// SWFSYNC = 0: no effect
// SYNCOSEL = 00: the source of the EPWMxSYNCO signal is set to EPWMxSYNCI
// PRDLD = 1: shadow registers disabled
// PHSEN = 1: Load the time-base counter with the phase register
// CTRMODE = 10: Up-down-count mode
EPwm1Regs.TBCTL.bit.CLKDIV = 100;
EPwm1Regs.TBCTL.bit.HSPCLKDIV = 110;
EPwm1Regs.TBPRD = SERVO_SP;
}
初步效果
360度舵機轉動效果
轉速、方向控制
在前面我們只是使舵機轉起來了,但是我們還需要去控制它的轉速以及方向,這要求我們清楚不同占空比所對應的舵機轉速以及方向,所以在上面的基礎上增添如下內容,每隔一定時間改變PWM信號的占空比,觀察舵機的表現,代碼如下:
cnt_PWM++;
if (duty_cycle_2 >= 0.1)
duty_cycle_2 = 0;
if (cnt_PWM % 4 == 0)
duty_cycle_2 += 0.01;
EPwm1Regs.CMPA.half.CMPA = SERVO_SP * (1 - duty_cycle_2);
實驗程序如下面視頻所示:
不同占空比下的舵機表現
根據實驗程序,可以整理得下表:
| 占空比/% | 舵機表現 |
|---|---|
| 0 | 不轉 |
| 1 | 順時針較快轉動 |
| 2 | 同上 |
| 3 | 順時針較慢轉動 |
| 4 | 逆時針更慢轉動 |
| 5 | 逆時針較快轉動 |
| 6 | 同上 |
| 7 | 不轉 |
| 8 | 同上 |
| 9 | 同上 |
| 10 | 同上 |
由上表可以清楚看到,作用不同占空比的PWM信號,舵機表現出不同的轉速以及方向,不過這個只是作為參考的目測結果,具體的轉速多少需要后期結合其他模塊進一步測量,
注意事項
- 由于開發板能力有限,無法直接給舵機供電,所以我們這里采用開關電源給舵機供電,這個時候要注意將開關電源的COM端與開發板的地端相連,不然舵機無法正常運行,這應該是因為不相連的話就沒有共地,會導致PWM信號與舵機內部的基準信號的比較出現問題,當時除錯了很久都沒反應,還以為是舵機壞了或者是PWM模塊配置有問題,
- 另外,由于舵機控制所需的PWM信號頻率較低,因此如果直接用系統時鐘作為時鐘源的話,周期值會超過周期暫存器的上限,因此需要設定時基控制暫存器TBCTL的CLKDIV位和HSPCLKDIV位來對系統時鐘進行分頻,
總結
至此,我們就成功利用F28335的PWM模塊來產生控制信號,驅動舵機的旋轉,同時,依然,由于本人水平有限,這個實驗各個方面肯定都還有可以改進的地方;另外,文中的知識闡述可能也會有錯誤的地方,歡迎大家批評指正,還有的話,從視頻可以看到,舵機運行程序中有抖動,沒看出來是什么原因,希望大佬們可以提出寶貴意見orz
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/258527.html
標籤:其他
下一篇:四、解讀VisualDSP++案例之21489 AD1939 C Block-Based Talkthru 48 or 96 kHz
