在本教程中,我們將使用 ARM7-LPC2148 控制伺服電機。伺服電機比步進電機具有低功耗的優勢。當到達所需位置時,伺服電機停止其功耗,但步進電機繼續消耗功率以將軸鎖定在所需位置。伺服電機主要用于 機器人項目 ,因為它們的準確性和易于操作性。
伺服電機
伺服電機 是直流電機、位置控制系統和齒輪的組合。 伺服電機的旋轉是通過向其施加PWM信號來控制的,PWM信號的寬度決定了電機的旋轉角度和方向。在這里,我們將在本教程中使用 SG90 伺服電機 ,它是最受歡迎和最便宜的電機之一。SG90 是 180 度伺服。所以有了這個伺服,我們可以將軸定位在 0-180 度之間:
工作電壓:+5V
齒輪類型:塑料
旋轉角度:0 至 180 度
重量:9克
扭矩:2.5kg/cm
在我們開始為伺服電機編程之前,我們應該知道要發送什么類型的信號來控制伺服電機。我們應該對 MCU 進行編程以將 PWM 信號發送到伺服電機的信號線。伺服電機內部有一個控制電路,它讀取 PWM 信號的占空比并將伺服電機軸定位在相應的位置,如下圖所示
伺服電機每 20 毫秒檢查一次脈沖。因此,調整信號的脈沖寬度以旋轉電機的軸。
1 毫秒(1 毫秒)脈沖寬度,用于伺服旋轉到0 度
1.5ms 脈沖寬度旋轉到90 度(中性位置)
2 ms 脈沖寬度用于伺服旋轉到180 度。
在 將伺服連接到 ARM7-LPC2148之前,您可以借助此 伺服電機測試儀電路測試您的伺服。
使用 LPC2148 PWM 和 ADC 控制伺服電機
LPC2148 可以使用 PWM 控制伺服電機。通過以 20ms 的周期和 50Hz 的頻率向 SERVO 的 PWM 引腳提供 PWM 信號,我們可以將伺服電機的軸定位在 180 度左右(-90 到 +90)。
電位器用于改變PWM信號的占空比并旋轉伺服電機的軸,這種方法是通過使用LPC2148中的ADC模塊來實現的。因此,我們需要在本教程中實現 PWM 和 ADC 概念。所以請參考我們之前的教程來學習 ARM7-LPC2148 中的 PWM 和 ADC。
ARM7-LPC2148 中的 PWM 和 ADC 引腳
下圖顯示了 LPC2148 中的 PWM 和 ADC 引腳。黃色框表示 (6) 個 PWM 引腳,黑框表示 (14) 個 ADC 引腳。
所需組件
ARM7-LPC2148
LCD (16x2) 顯示模塊
伺服馬達 (SG-90)
3.3V穩壓器
10k電位器(2個)
面包板
連接電線
軟件
凱爾uVision5
閃光魔法工具
電路圖和連接
下表顯示了伺服電機與 ARM7-LPC2148 之間的連接:
引腳 P0.1 是 LPC2148 的 PWM 輸出。
下表顯示了LCD 和 ARM7-LPC2148 之間的電路連接。
下表顯示了ARM7 LPC2148 和帶 3.3V 穩壓器的電位器之間的連接。
注意事項
1. 這里使用一個 3.3V 的穩壓器為 LPC2148 的 ADC 引腳(P0.28)提供模擬輸入值。由于我們使用的是 5V 電源,我們需要使用 3.3V 的穩壓器來調節電壓。
2. 電位器用于在(0V 至 3.3V)之間改變電壓,以向 LPC2148 引腳 P0.28 提供模擬輸入(ADC)
3、LPC2148的P0.1引腳為伺服電機提供PWM輸出,控制電機的位置。
4. 根據模擬輸入 (ADC) 值,伺服電機的位置通過 LPC2148 的 P0.1 處的 PWM 輸出引腳從(0 到 180 度)變化。
為 PWM 和 ADC 配置 LPC2148 以控制伺服電機的步驟
第 1 步:-包括編碼 LPC2148 所需的頭文件
#include
#include
#include
#include
第 2 步:-下一步是配置 PLL以生成時鐘,因為它根據程序員的需要設置 LPC2148 的系統時鐘和外設時鐘。LPC2148 的最大時鐘頻率為 60Mhz。以下行用于配置 PLL 時鐘生成。
void initilizePLL (void) //使用 PLL 產生時鐘的函數
{
PLL0CON = 0x01;
PLL0CFG = 0x24;
PLL0FEED = 0xAA;
PLL0FEED = 0x55;
而(!(PLL0STAT&0x00000400));
PLL0CON = 0x03;
PLL0FEED = 0xAA;
PLL0FEED = 0x55;
VPBDIV = 0x01;
}
第 3 步:-接下來要做的是使用 PINSEL 寄存器選擇 LPC2148 的 PWM 引腳和 PWM 功能。我們使用 PINSEL0,因為我們使用 P0.1 作為 LPC2148 的 PWM 輸出。
PINSEL0 |= 0x00000008; // 將 LPC2148 的 P0.1 引腳設置為 PWM3
第 4 步:-接下來,我們需要使用 PWMTCR(定時器控制寄存器)重置定時器。
PWMTCR = 0x02;// 重置和禁用 PWM 計數器
然后設置決定 PWM 分辨率的預分頻值。
PWMPR = 0x1D;// 預分頻寄存器值
第 5 步:-接下來,設置 PWMMCR(PWM 匹配控制寄存器),因為它設置復位、PWMMR0 和 PWMMR3 的中斷等操作。
PWMMCR = 0x00000203;// MR0 匹配時復位并中斷,MR3 匹配時中斷
第 6 步:- PWM 通道的最大周期使用 PWMMR0 設置,PWM 占空比的 Ton 初始設置為 0.65msec
PWMMR0 = 20000;// PWM波的時間周期,
20msec PWMMR3 = 650; // 噸 PWM 波 0.65 毫秒
第 7 步:-接下來,我們需要使用 PWMLER 將 Latch Enable 設置為相應的匹配寄存器
PWMLER = 0x09;// PWM3 和 PWM0 的鎖存使能
(我們使用 PWMMR0 和 PWMMR3)所以通過在 PWMLER 中設置 1 來啟用相應的位
第 8 步:-要使 PWM 輸出到引腳,我們需要使用 PWMTCR 來啟用 PWM 定時器計數器和 PWM 模式。
PWMPCR = 0x0800;// 使能 PWM3 和 PWM 0,單邊沿控制 PWM
PWMTCR = 0x09; // 啟用 PWM 和計數器
第 9 步:-現在我們需要從 ADC 引腳 P0.28 獲取用于設置 PWM 占空比的電位器值。因此,我們使用 LPC2148 中的 ADC 模塊將電位器模擬輸入(0 至 3.3V)轉換為 ADC 值(0 至 1023)。
第 10 步:-為了 選擇 LPC2148 中的 ADC 引腳 P0.28, 我們使用
PINSEL1 = 0x01000000;//設置P0.28為ADC INPUT
AD0CR = (((14)<<8) | (1<<21)); //為A/D轉換設置時鐘和PDN
以下行 捕獲模擬輸入(0 到 3.3V) 并將其轉換為數字值(0 到 1023)。然后將這個數字值除以 4 以將它們轉換為 (0 到 255) ,最后作為 PWM 輸出饋送到 LPC2148 的 P0.1 引腳 。在這里,我們 通過將其除以 4 將值從 0-1023 轉換為 0-255,因為 LPC2148 的 PWM 具有 8 位分辨率 (28)。
AD0CR |= (1<<1);
//在ADC寄存器delaytime(10)
中選擇AD0.1通道;AD0CR |= (1<<24); //開始A/D轉換
while( (AD0DR1 & (1<<31)) == 0 ); //檢查ADC數據寄存器中的DONE位
adcvalue = (AD0DR1>>6) & 0x3ff; //從 ADC 數據寄存器中獲取 RESULT
dutycycle = adcvalue/4; //從 (0 到 255) 獲取占空比值的公式
PWMMR1 = dutycycle; //設置占空比值到 PWM 匹配寄存器
PWMLER |= (1<<1); //使用占空比值啟用 PWM 輸出
第 11 步:-接下來,我們在 LCD (16X2) 顯示模塊中顯示這些值。所以我們添加以下行來初始化 LCD 顯示模塊
void LCD_INITILIZE(void) //準備 LCD 的函數
{
IO0DIR = 0x0000FFF0; //設置引腳P0.12,P0.13,P0.14,P0.15,P0.4,P0.6為OUTPUT
delaytime(20);
LCD_SEND(0x02); // 以 4 位操作模式初始化 lcd
LCD_SEND(0x28); // 2 行 (16X2)
LCD_SEND(0x0C); // 光標關閉時顯示
LCD_SEND(0x06); // 自動遞增光標
LCD_SEND(0x01); // 顯示清除
LCD_SEND(0x80); // 第一行第一個位置
}
當我們將 4 位模式的 LCD 與 LPC2148連接時, 我們需要發送值以逐個半字節(上半字節和下半字節)顯示。所以使用以下幾行。
void LCD_DISPLAY (char* msg) //函數將發送的字符一一打印
{
uint8_t i=0;
while(msg[i]!=0)
{
IO0PIN = ( (IO0PIN & 0xFFFF00FF) | ((msg[i] & 0xF0)<<8) ); //發送高半字節
IO0SET = 0x00000050; //RS HIGH & ENABLE HIGH 打印數據
IO0CLR = 0x00000020; //RW LOW 寫模式
延遲時間(2);
IO0CLR = 0x00000040;// EN = 0,RS 和 RW 不變(即 RS = 1,RW = 0)
delaytime(5);
IO0PIN = ( (IO0PIN & 0xFFFF00FF) | ((msg[i] & 0x0F)<<12) ); //發送低半字節
IO0SET = 0x00000050; //RS & EN HIGH
IO0CLR = 0x00000020;
延遲時間(2);
IO0CLR = 0x00000040;
延遲時間(5);
我++;
}
}
為了顯示這些 ADC 和 PWM 值,我們在int main() 函數中使用以下行 。
LCD_SEND(0x80);
sprintf(displayadc,“adcvalue=%f”,占空比);
LCD_DISPLAY(displayadc); //顯示ADC值(0到1023)
angle = (adcvalue/5.7); //公式將ADC值轉換為角度(o到180度)
LCD_SEND(0xC0);
sprintf(角度值,“角度=%.2f 度”,角度);
LCD_DISPLAY(角度值);
//連接伺服電機與ARM7-LPC2148
//由 Pramoth.T 編寫的代碼
#include
#include
#include
#include
無效初始化PLL(無效);
void initilizePLL (void) //使用PLL產生時鐘的函數
{
PLL0CON = 0x01;
PLL0CFG = 0x24;
PLL0FEED = 0xAA;
PLL0FEED = 0x55;
而(!(PLL0STAT&0x00000400));
PLL0CON = 0x03;
PLL0FEED = 0xAA;
PLL0FEED = 0x55;
VPBDIV = 0x01;
}
void delay_ms(uint16_t z) // 使用 Cclk (60MHz) 產生 1 毫秒延遲的函數
{
uint16_t x,i;
for(i=0;i
{
對于(x=0;x<6000;x++);
}
}
__irq 無效 PWM_ISR (無效)
{
如果(PWMIR & 0x0001)
{
PWMIR = 0x0001;
}
如果(PWMIR & 0x0008)
{
PWMIR = 0x0008;
}
VICVectAddr = 0x00000000;
}
void LCD_SEND(char command) //發送十六進制命令的函數
{
IO0PIN = ( (IO0PIN & 0xFFFF00FF) | ((命令 & 0xF0)<<8) ); //發送命令的上半字節
IO0SET = 0x00000040;//使啟用高
IO0CLR = 0x00000030;//使 RS & RW 低
延遲毫秒(5);
IO0CLR = 0x00000040;//使啟用低
延遲毫秒(5);
IO0PIN = ( (IO0PIN & 0xFFFF00FF) | ((命令 & 0x0F)<<12) ); //發送命令的低半字節
IO0SET = 0x00000040;//啟用高
IO0CLR = 0x00000030;//RS & RW 低
延遲毫秒(5);
IO0CLR = 0x00000040;//啟用低
延遲毫秒(5);
}
void LCD_INITILIZE(void) //準備LCD的函數
{
IO0DIR = 0x0000FFF0;//設置引腳P0.12,P0.13,P0.14,P0.15,P0.4,P0.6為OUTPUT
延遲毫秒(20);
LCD_SEND(0x02); // 以 4 位操作模式初始化 lcd
LCD_SEND(0x28); // 2 行 (16X2)
LCD_SEND(0x0C); // 光標關閉時顯示
LCD_SEND(0x06); // 自動遞增光標
LCD_SEND(0x01); // 顯示清晰
LCD_SEND(0x80); // 第一行第一個位置
}
void LCD_DISPLAY (char* msg) //函數將發送的字符一一打印
{
uint8_t i=0;
而(味精[i]!=0)
{
IO0PIN = ( (IO0PIN & 0xFFFF00FF) | ((msg[i] & 0xF0)<<8) ); //發送上半字節
IO0SET = 0x00000050;//RS HIGH & ENABLE HIGH 打印數據
IO0CLR = 0x00000020;//RW LOW 寫模式
延遲毫秒(2);
IO0CLR = 0x00000040;// EN = 0,RS 和 RW 不變(即 RS = 1,RW = 0)
延遲毫秒(5);
IO0PIN = ( (IO0PIN & 0xFFFF00FF) | ((msg[i] & 0x0F)<<12) ); //發送低半字節
IO0SET = 0x00000050;//RS & EN 高
IO0CLR = 0x00000020;
延遲毫秒(2);
IO0CLR = 0x00000040;
延遲毫秒(5);
我++;
}
}
主函數()
{
LCD_INITILIZE(); //調用函數準備LCD顯示
字符顯示ADC[18];
浮動ADC;
浮動角度;
字符角度值[18];
LCD_DISPLAY("電路摘要");
延遲毫秒(900);
LCD_SEND(0xC0);
LCD_DISPLAY("伺服 LPC2148");
延遲毫秒(900);
PINSEL0 |= 0x00000008; // 將 LPC2148 的 P0.1 引腳設置為 PWM3
VICVectAddr0 =(無符號)PWM_ISR;// PWM ISR 地址
VICVectCntl0 = (0x00000020 | 8); // 啟用 PWM IRQ 插槽
VICIntEnable = VICIntEnable | 0x00000100; // 啟用 PWM 中斷
VICIntSelect = VICIntSelect | 0x00000000; // PWM 配置為 IRQ
PWMTCR = 0x02;// 重置和禁用 PWM 計數器
PWMPR = 0x1D;// 預分頻寄存器值
PWMMR0 = 20000;// PWM波的時間周期,20msec
PWMMR3 = 650;// 噸 PWM 波 0.65 毫秒
PWMMCR = 0x00000203;// MR0 匹配時復位并中斷,MR3 匹配時中斷
PWMLER = 0x09;// PWM3 和 PWM0 的鎖存使能
PWMPCR = 0x0800;// 啟用 PWM3 和 PWM 0,單邊沿控制 PWM
PWMTCR = 0x09;// 啟用 PWM 和計數器
浮動占空比;
unsigned short int adcvalue;
PINSEL1 = 0x01000000;//設置P0.28為ADC INPUT(來自電位器)
AD0CR = (((14)<<8) | (1<<21)); //為A/D轉換設置時鐘和PDN
PWMPCR |= (1<<9); //在LPC2148的P0.1引腳啟用PWM3輸出用于伺服(橙色線)
而(1)
{
AD0CR |= (1<<1); //選擇ADC寄存器中的AD0.1通道
AD0CR |= (1<<24); //開始A/D轉換
而( (AD0DR1 & (1<<31)) == 0 ); //檢查ADC數據寄存器中的DONE位
adcvalue = (AD0DR1>>6) & 0x3ff; //從ADC數據寄存器中獲取RESULT
占空比 = (adcvalue/4); //從 (0 到 255) 獲取占空比值的公式
PWMMR3 = 占空比;//設置占空比值到PWM匹配寄存器
PWMLER = 0x08;//使用占空比值啟用 PWM 輸出
延遲毫秒(50);
LCD_SEND(0x80);
sprintf(displayadc,“adcvalue=%f”,占空比);
LCD_DISPLAY(displayadc); //顯示ADC值(0到1023)
角度 = (adcvalue/5.7); //將ADC值轉換為角度的公式(o到180度)
LCD_SEND(0xC0);
sprintf(角度值,“角度=%.2f 度”,角度);
LCD_DISPLAY(角度值); //顯示角度值
}
}
評論
查看更多