機械臂是令人著迷的工程創(chuàng)造之一,看著這些東西傾斜和平移以像人類手臂一樣完成復(fù)雜的事情總是令人著迷。這些機械臂常見于裝配線上進行焊接、鉆孔、噴漆等高強度機械工作的行業(yè)中,最近還開發(fā)了高精度的先進機械臂來執(zhí)行復(fù)雜的外科手術(shù)。因此,在本教程中,讓我們使用 ARM7-LPC2148 微控制器構(gòu)建一個簡單的機械臂,通過手動控制幾個電位器來拾取和放置物體。
所需組件
3D 打印機機械臂
ARM7-LPC2148
SG-90 伺服電機 (4)
10k 電位器 (4)
按鈕 (4)
發(fā)光二極管 (4)
5V (1A) 直流電源適配器
電阻器(10k (4)、2.2k(4))
面包板
連接電線
準備好 3D 打印機械臂
本教程中使用的 3D 打印機械臂是按照Thingiverse中提供的EEZYbotARM給出的設(shè)計制作的。制作 3D 打印機械臂的完整程序和帶有視頻的組裝細節(jié)都在上面分享的 thingiverse 鏈接中。
這是我的 3D 打印機械臂與 4 個伺服電機組裝后的圖像。
電路原理圖
下圖顯示了基于 ARM 的機械臂的電路連接。
該項目的電路連接很簡單。確保使用單獨的 5V DC 電源適配器為伺服電機供電。對于電位器和按鈕,我們可以使用LPC2148 微控制器提供的 3.3V 電壓。
這里我們使用 LPC2148 的 4 個 ADC 引腳和 4 個電位器。LPC2148 的 4 個 PWM 引腳與伺服電機的 PWM 引腳相連。我們還連接了 4 個按鈕來選擇要操作的電機。因此,按下按鈕后,電位器會變化以改變伺服電機的位置。
與LPC2148的GPIO連接的按鈕一端通過10k的電阻下拉,另一端連接3.3V。還連接了 4 個 LED 以指示選擇哪個伺服電機來改變位置。
為機械臂編程 LPC2148 所涉及的步驟
在為這個機械臂編程之前,我們需要了解如何在 LPC2148 中生成 PWM 以及在 ARM7-LPC2148 中使用 ADC。為此,請參閱我們之前關(guān)于將伺服電機與 LPC2148連接以及如何在 LPC2148 中使用 ADC 的項目。
使用 LPC2148 進行 ADC 轉(zhuǎn)換
因為我們需要提供 ADC 值來設(shè)置占空比值,以生成用于控制伺服電機位置的 PWM 輸出。我們需要找到電位器的 ADC 值。由于我們有四個電位器來控制四個伺服電機,因此我們需要 LPC2148 的 4 個ADC 通道。在本教程中,我們使用 LPC2148 中分別存在的 4、1、2、3 ADC 通道的 ADC 引腳(P0.25、P0.28、P0.29、P0.30)。
使用 LPC2148 為伺服電機生成 PWM 信號
因為我們需要生成 PWM 信號來控制伺服電機的位置。我們需要設(shè)置 PWM 的占空比。我們有四個伺服電機連接到機械臂,所以我們需要 LPC2148 的 4 個 PWM 通道。在本教程中,我們使用LPC2148 中分別存在的 3、2、4、5 PWM 通道的 PWM 引腳(P0.1、P0.7、P0.8、P0.21)。
將十六進制文件編程和閃存到 LPC2148
要對 ARM7-LPC2148 進行編程,我們需要keil uVision 并將HEX 代碼閃存到 LPC2148 需要 Flash Magic 工具。此處使用 USB 電纜通過微型 USB 端口對ARM7 Stick進行編程。我們使用 Keil 編寫代碼并創(chuàng)建一個 hex 文件,然后使用Flash Magic將 HEX 文件閃存到 ARM7 棒。要了解有關(guān)安裝 keil uVision 和 Flash Magic 以及如何使用它們的更多信息,請點擊鏈接 Getting Started With ARM7 LPC2148 Microcontroller and Program it using Keil uVision。
編碼說明
?該機械臂項目的完整程序在教程的最后給出。現(xiàn)在讓我們詳細看看編程。
配置 LPC2148 的 PORT 以使用 GPIO、PWM 和 ADC:
使用 PINSEL1 寄存器為引腳 P0.25、P0.28、P0.29、P0.30 啟用 ADC 通道 - ADC0.4、ADC0.1、ADC0.2、ADC0.3。此外,對于引腳 P0.21 (1<<10) 的 PWM5。
?
#define AD04 (1<<18) //為 P0.25 選擇 AD0.4 函數(shù) #define AD01 (1<<24) //為 P0.28 選擇 AD0.1 函數(shù) #define AD02 (1<<26) / /為 P0.29 選擇 AD0.2 函數(shù) #define AD03 (1<<28) //為 P0.30 選擇 AD0.3 函數(shù) PINSEL1 |= AD04 | AD01 | AD02 | AD03 | (1<<10);
?
使用 PINSEL0 寄存器來使能 LPC2148 的引腳 P0.1、P0.7、P0.8 的 PWM 通道 PWM3、PWM2、PWM4。
?
PINSEL0 = 0x000A800A;
?
使用 PINSEL2 寄存器啟用 PORT1 中所有用于連接 LED 和按鈕的引腳的 GPIO 引腳功能。
?
PINSEL2 = 0x00000000;
?
為了使 LED 引腳作為輸出和按鈕引腳作為輸入,使用 IODIR1 寄存器。(輸入為 0,輸出為 1)
?
IODIR1 = ((0<<17)|(0<<18)|(0<<19)|(0<<20)|(1<<28)|(1<<29)|(1<<30 )|(1<<31));
?
雖然引腳號定義為
?
#define SwitchPinNumber1 17 //(與P1.17相連) #define SwitchPinNumber2 18 //(與P1.18相連) #define SwitchPinNumber3 19 //(與P1.19相連) #define SwitchPinNumber4 20 //(與P1相連。 20) #define LedPinNumber1 28 //(與P1.28相連) #define LedPinNumber2 29 //(與P1.29相連) #define LedPinNumber3 30 //(與P1.30相連) #define LedPinNumber4 31 //(與P1相連。 31)
?
配置 ADC 轉(zhuǎn)換設(shè)置
接下來使用 AD0CR_setup 寄存器設(shè)置 ADC 轉(zhuǎn)換模式和 ADC 時鐘。
?
無符號長 AD0CR_setup = (CLKDIV<<8) | BURST_MODE_OFF | 充電; //設(shè)置ADC模式
?
而 CLCKDIV、Burst Mode 和 PowerUP 被定義為
?
#define CLKDIV (15-1) #define BURST_MODE_OFF (0<<16) // 1 表示開啟,0 表示關(guān)閉 #define PowerUP (1<<21)
?
設(shè)置 ADC 轉(zhuǎn)換的時鐘 (CLKDIV)
這用于為 ADC 生成時鐘。4Mhz ADC 時鐘 (ADC_CLOCK=PCLK/CLKDIV) 實際使用“CLKDIV-1”,在我們的例子中 PCLK=60mhz?
Burst Mode (Bit-16):該位用于 BURST 轉(zhuǎn)換。如果該位置位,ADC 模塊將對在 SEL 位中選擇 (SET) 的所有通道進行轉(zhuǎn)換。將此位設(shè)置為 0 將禁用 BURST 轉(zhuǎn)換。
斷電模式(Bit-21):用于打開或關(guān)閉 ADC。該位設(shè)置 (1) 使 ADC 退出掉電模式并使其運行。清零該位將關(guān)閉 ADC。
配置 PWM 轉(zhuǎn)換設(shè)置
首先使用 PWMTCR 寄存器復(fù)位和禁用 PWM 計數(shù)器,并使用預(yù)分頻器值設(shè)置 PWM 定時器預(yù)分頻寄存器。
?
PWMTCR = 0x02; PWMPR = 0x1D;
?
接下來設(shè)置一個循環(huán)中的最大計數(shù)數(shù)。這是在匹配寄存器 0 (?PWMMR0?) 中完成的。因為我們有 20000,因為它是 20 毫秒的 PWM 波
?
PWMMR0 = 20000;
?
在匹配寄存器中設(shè)置占空比值之后,我們使用 PWMMR4、PWMMR2、PWMMR3、PWMMR5。這里我們將初始值設(shè)置為 0 毫秒 (Toff)
?
PWMMR4 = 0; PWMMR2 = 0; PWMMR3 = 0; PWMMR5 = 0;
?
之后,設(shè)置 PWM 匹配控制寄存器以在匹配寄存器發(fā)生時導(dǎo)致計數(shù)器復(fù)位。
?
PWMMCR = 0x00000002;// 在 MR0 匹配時重置
?
之后,PWM 鎖存器使能寄存器使能使用匹配值(PWMLER)
?
PWMLER = 0x7C;// PWM2、PWM4、PWM4 和 PWM5 的鎖存使能
?
使用 PWM 定時器控制寄存器 ( PWMTCR?)中的一個位來復(fù)位定時器計數(shù)器,并啟用 PWM。
?
PWMTCR = 0x09;// 啟用 PWM 和計數(shù)器
?
接下來啟用 PWM 輸出并在 PWM 控制寄存器 (?PWMPCR?) 中將 PWM 設(shè)置為單邊沿控制模式。
?
PWMPCR = 0x7C00;// 使能 PWM2、PWM4、PWM4 和 PWM5,單邊沿控制 PWM
?
使用按鈕選擇要旋轉(zhuǎn)的伺服電機???????????????????????????????????????????????????????????????????????????????????????????????????????????????????
我們有四個按鈕,用于旋轉(zhuǎn)四個不同的伺服電機。通過選擇一個按鈕并改變相應(yīng)的電位器,ADC值設(shè)置占空比,相應(yīng)的伺服電機改變其位置。獲取按鈕開關(guān)的狀態(tài)??????????? ??????????????
?
switchStatus1 = (IOPIN1>>SwitchPinNumber1) & 0x01 ;
?
因此,根據(jù)哪個開關(guān)值是高電平,會發(fā)生 ADC 轉(zhuǎn)換,然后在成功轉(zhuǎn)換 ADC(0 到 1023)值后,將其映射為(0 到 2045),然后將占空比值寫入(PWMMRx) PWM 引腳連接到伺服電機。而且,LED 會變高以指示按下了哪個開關(guān)。以下是第一個按鈕的示例
?
if(switchStatus1 == 1) { IOPIN1 = (1<>6) & 0x3ff; //獲取ADC值 result1 = map(convert1,0,1023,0,2450); //將 ADC 值轉(zhuǎn)換為 PWM 的 占空比 PWMMR5 = result1; //設(shè)置占空比值為 PWM5 PWMLER = 0x20; //啟用 PWM5 delay_ms(2); } } 其他 { IOPIN1 = (0< ?
取放機械臂的工作
將代碼上傳到 LPC2148 后,按下任意開關(guān)并改變相應(yīng)的電位器來改變機械臂的位置。
每個開關(guān)和電位器控制每個伺服電機的運動,即底座向左或向右運動,向上或向下運動,向前或向后運動,然后夾具保持和釋放運動。
//使用LPC2148的機器人ARM
#include
?? #include
#define SwitchPinNumber1 17?
#define SwitchPinNumber2 18
#define SwitchPinNumber3 19
#define SwitchPinNumber4 20
#define LedPinNumber1 28
#define LedPinNumber2 29
#define LedPinNumber3 30
#define LedPinNumber4 31
#define AD04 (1<<18) //為 P0.25 選擇 AD0.4 功能
#define AD01 (1<<24) //為 P0.28 選擇 AD0.1 功能
#define AD02 (1<<26) //為 P0.29 選擇 AD0.2 功能
#define AD03 (1<<28) //為 P0.30 選擇 AD0.3 功能
#define SEL_AD04 (1<<4) //選擇ADC通道4
#define SEL_AD01 (1<<1) //選擇ADC通道1
#define SEL_AD02 (1<<2) //選擇ADC通道2
#define SEL_AD03 (1<<3) //選擇ADC通道3
#define CLKDIV (15-1) // 4Mhz ADC 時鐘 (ADC_CLOCK=PCLK/CLKDIV) 實際使用“CLKDIV-1”,在我們的例子中 PCLK=60mhz?
#define BURST_MODE_OFF (0<<16) // 1 表示開啟,0 表示關(guān)閉
#define 上電 (1<<21)
#define START_NOW ((0<<26)|(0<<25)|(1<<24)) //001 立即開始轉(zhuǎn)換
#define ADC_DONE (1UL<<31)
#define VREF 3.3 //VREF 引腳的參考電壓
易失性int結(jié)果1 = 0;
易失性int結(jié)果2 = 0;
易失性int結(jié)果3 = 0;
易失性int結(jié)果4 = 0;
易失性 int 轉(zhuǎn)換 1=0;
易失性int轉(zhuǎn)換2 = 0;
易失性 int 轉(zhuǎn)換 3=0;
易失性 int convert4=0;
volatile unsigned int switchStatus1;
volatile unsigned int switchStatus2;
volatile unsigned int switchStatus3;
volatile unsigned int switchStatus4;
long map(long x, long in_min, long in_max, long out_min, long out_max) // 映射函數(shù)來轉(zhuǎn)換范圍
{
? 返回 (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
void delay_ms(uint16_t j) /* 循環(huán)產(chǎn)生 1 毫秒延遲,Cclk = 60MHz */
{
? ? uint16_t x,i;
? ? ? ? ? ? ? ? for(i=0;i
? ? ? ? ? ? ? ? {
? ? 對于(x=0;x<6000;x++);? ?
? ? ? ? ? ? ? ? }
}
主函數(shù)()
{
? ? PINSEL0 = 0x000A800A;// 將 P0.1,P0.7,P0.8 配置為 PWM3,PWM2,PWM4 引腳
? ? PINSEL2 = 0x00000000;//將PORT1引腳配置為GPIO;
? ?PINSEL1 |= AD04 | AD01 | AD02 | AD03 | (1<<10); // 配置 P0.25,P0.28,P0.29,P0.30 為 ADC0.4, ADC0.1, ADC0.2, ADC0.3 引腳 & P0.21 為 PWM5
? ?IODIR1 = ((0<<17)|(0<<18)|(0<<19)|(0<<20)|(1<<28)|(1<<29)|(1<<30 )|(1<<31)); //配置LED管腳為輸出,開關(guān)管腳為輸入
? ? 無符號長 AD0CR_setup = (CLKDIV<<8) | BURST_MODE_OFF | 充電; //設(shè)置ADC模式
? ? ?PWMTCR = 0x02;// 重置和禁用 PWM 計數(shù)器
? ? ?PWMPR = 0x1D;// 預(yù)分頻寄存器值
? ? ?PWMMR0 = 20000;// PWM波的時間周期,20msec
? ? ?PWMMR4 = 0;// PWM 波的初始值 0 ms
? ? ?PWMMR2 = 0;
? ? ?PWMMR3 = 0;
? ? ?PWMMR5 = 0;
? ? ?PWMMCR = 0x00000002;// 在 MR0 匹配時重置
? ? ?PWMLER = 0x7C;// PWM2、PWM4、PWM4 和 PWM5 的鎖存使能
? ? ?PWMPCR = 0x7C00;// 使能 PWM2、PWM4、PWM4 和 PWM5,單邊沿控制 PWM
? ? ?PWMTCR = 0x09;// 啟用 PWM 和計數(shù)器? ? ? ? ? ? ??
而(1)
? ? {
? ? ? ?switchStatus1 = (IOPIN1>>SwitchPinNumber1) & 0x01 ; // 讀取開關(guān)狀態(tài)
? ? ? ?switchStatus2 = (IOPIN1>>SwitchPinNumber2) & 0x01; // 讀取開關(guān)狀態(tài)
? ? ? ?switchStatus3 = (IOPIN1>>SwitchPinNumber3) & 0x01 ; // 讀取開關(guān)狀態(tài)
? ? ? ?switchStatus4 = (IOPIN1>>SwitchPinNumber4) & 0x01; // 讀取開關(guān)狀態(tài)
if(switchStatus1 == 1) //根據(jù)開關(guān)狀態(tài)打開/關(guān)閉 LED 并開始 ADC 轉(zhuǎn)換
? ? ? ? {?
? ? ? ? ? ? ? ? ? ? ? ?IOPIN1 = (1<
? ? ? ? ? ? ? ? ? ? ? ?AD0CR = AD0CR_setup | SEL_AD01; //為通道1設(shè)置ADC
? ? ? ? ? ? ? ? ? ? ? ?AD0CR |= START_NOW; //在ADC1開始新的轉(zhuǎn)換
? ? ? ? ? ? ? ? ? ? ? ?while( (AD0DR1 & ADC_DONE) == 0 ) //檢查 ADC 轉(zhuǎn)換
? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?轉(zhuǎn)換1 = (AD0DR1>>6) & 0x3ff; //獲取ADC值
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 結(jié)果 1 = 地圖(轉(zhuǎn)換 1,0,1023,0,2450);//根據(jù)占空比為 PWM 轉(zhuǎn)換 ADC 值
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? PWMMR5 = 結(jié)果1;//將占空比值設(shè)置為PWM5
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? PWMLER = 0x20;//啟用PWM5
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?延遲毫秒(2);
? ? ? ? ? ? ? ? ?}
? ? ? ? }
? ? ? 別的
? ? ? ? ?{
? ? ? ? ?IOPIN1 = (0<
? ? ? ? ?}? ? ?
if(switchStatus2 == 1) //根據(jù)開關(guān)狀態(tài)打開/關(guān)閉 LED 并開始 ADC 轉(zhuǎn)換
? ? ? ?{?
? ? ? ? ? ? ? ? ?IOPIN1 = (1<
? ? ? ? ? ? ? ? ?AD0CR = AD0CR_setup | SEL_AD02; //設(shè)置通道2的ADC
? ? ? ? ? ? ? ? ?AD0CR |= START_NOW; //在ADC2開始新的轉(zhuǎn)換
while( (AD0DR2 & ADC_DONE) == 0 ) //檢查 ADC 轉(zhuǎn)換
? ? ? ? {
? ? ? ? ? ? ? ? ? ? ?轉(zhuǎn)換2 = (AD0DR2>>6) & 0x3ff; //獲取ADC值
? ? ? ? ? ? ? ? ? ? ? 結(jié)果 2 = 地圖(轉(zhuǎn)換 2,0,1023,0,2450);//根據(jù)占空比為 PWM 轉(zhuǎn)換 ADC 值
? ? ? ? ? ? ? ? ? ? ? PWMMR4 = 結(jié)果2;//將占空比值設(shè)置為PWM4
? ? ? ? ? ? ? ? ? ? ? PWMLER = 0x10;//啟用PWM4
? ? ? ? ? ? ? ? ? ? ? 延遲毫秒(2);
? ? ? ? ?}
? ?} 別的
? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? IOPIN1 = (0<
? ? ? ? ? ? }? ? ?
if(switchStatus3 == 1) //根據(jù)開關(guān)狀態(tài)打開/關(guān)閉 LED 并開始 ADC 轉(zhuǎn)換
? ? ? ? {?
? ? ? ? ? ? ? ? ? ? ?IOPIN1 = (1<
? ? ? ? ? ? ? ? ? ? ?AD0CR |= START_NOW; //在ADC3開始新的轉(zhuǎn)換
? ? ? ? ? ? ? ? ? ? ?while( (AD0DR3 & ADC_DONE) == 0 ) //檢查 ADC 轉(zhuǎn)換
? ? ? ? ? ? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ? ? ? ?轉(zhuǎn)換3 = (AD0DR3>>6) & 0x3ff; //獲取ADC值
? ? ? ? ? ? ? ? ? ? ? ? ? ?結(jié)果 3 = 地圖(轉(zhuǎn)換 3,0,1023,0,2450);//根據(jù)占空比為 PWM 轉(zhuǎn)換 ADC 值
? ? ? ? ? ? ? ? ? ? ? ? ? ?PWMMR3 = 結(jié)果3;//將占空比值設(shè)置為PWM3
? ? ? ? ? ? ? ? ? ? ? ? ? ?PWMLER = 0x08;//啟用PWM3
? ? ? ? ? ? ? ? ? ? ? ? ? ? 延遲毫秒(2);
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ?} 別的
? ? ? ?{
? ? ? ? ?IOPIN1 = (0<
? ? ? ?}? ? ?
?if(switchStatus4 == 1) //根據(jù)開關(guān)狀態(tài)打開/關(guān)閉 LED 并開始 ADC 轉(zhuǎn)換
? ? ? ?{?
? ? ? ? ? ? ? ? ? ? ? ? ? ?IOPIN1 = (1<
? ? ? ? ? ? ? ? ? ? ? ? ? ?AD0CR = AD0CR_setup | SEL_AD04; //設(shè)置通道4的ADC
? ? ? ? ? ? ? ? ? ? ? ? ? ?AD0CR |= START_NOW; //在ADC4開始新的轉(zhuǎn)換
? ? ? ? ? ? ? ? ? ? ? ? ? while( (AD0DR4 & ADC_DONE) == 0 ) //檢查 ADC 轉(zhuǎn)換
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ? ? ? ? 轉(zhuǎn)換4 = (AD0DR4>>6) & 0x3ff; //獲取ADC值
? ? ? ? ? ? ? ? ? ? ? ? ? ? 結(jié)果4 =地圖(轉(zhuǎn)換4,0,1023,0,2450);//根據(jù)占空比為 PWM 轉(zhuǎn)換 ADC 值
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?PWMMR2 = 結(jié)果4;//將占空比值設(shè)置為 PWM PWMLER = 0x04; //啟用PWM2
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?延遲毫秒(2);
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? } 別的
? ? ? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? IOPIN1 = (0<
? ? ? ? ? ? ? ? ? ? ? ? }? ? ?
? ? ? ? ?}
? ? ? }
評論
查看更多