机械臂是令人着迷的工程创造之一,看着这些东西倾斜和平移以像人类手臂一样完成复杂的事情总是令人着迷。这些机械臂常见于装配线上进行焊接、钻孔、喷漆等高强度机械工作的行业中,最近还开发了高精度的先进机械臂来执行复杂的外科手术。因此,在本教程中,让我们使用 arm7-lpc2148 微控制器构建一个简单的机械臂,通过手动控制几个电位器来拾取和放置物体。
所需组件
3d 打印机机械臂
arm7-lpc2148
sg-90 伺服电机 (4)
10k 电位器 (4)
按钮 (4)
发光二极管 (4)
5v (1a) 直流电源适配器
电阻器(10k (4)、2.2k(4))
面包板
连接电线
准备好 3d 打印机械臂
本教程中使用的 3d 打印机械臂是按照thingiverse中提供的eezybotarm给出的设计制作的。制作 3d 打印机械臂的完整程序和带有视频的组装细节都在上面分享的 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。为此,请参阅我们之前关于将伺服电机与 lpc2148连接以及如何在 lpc2148 中使用 adc 的项目。
使用 lpc2148 进行 adc 转换
因为我们需要提供 adc 值来设置占空比值,以生成用于控制伺服电机位置的 pwm 输出。我们需要找到电位器的 adc 值。由于我们有四个电位器来控制四个伺服电机,因此我们需要 lpc2148 的 4 个adc 通道。在本教程中,我们使用 lpc2148 中分别存在的 4、1、2、3 adc 通道的 adc 引脚(p0.25、p0.28、p0.29、p0.30)。
使用 lpc2148 为伺服电机生成 pwm 信号
因为我们需要生成 pwm 信号来控制伺服电机的位置。我们需要设置 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 编写代码并创建一个 hex 文件,然后使用flash magic将 hex 文件闪存到 arm7 棒。要了解有关安装 keil uvision 和 flash magic 以及如何使用它们的更多信息,请点击链接 getting started with arm7 lpc2148 microcontroller and program it using keil uvision。
编码说明
该机械臂项目的完整程序在教程的最后给出。现在让我们详细看看编程。
配置 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 函数#define ad01 (1<<24) //为 p0.28 选择 ad0.1 函数#define ad02 (1<<26) / /为 p0.29 选择 ad0.2 函数#define ad03 (1<<28) //为 p0.30 选择 ad0.3 函数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 转换设置
接下来使用 ad0cr_setup 寄存器设置 adc 转换模式和 adc 时钟。
无符号长 ad0cr_setup = (clkdiv<<8) | burst_mode_off | 充电; //设置adc模式
而 clckdiv、burst mode 和 powerup 被定义为
#define clkdiv (15-1) #define burst_mode_off (0<<16) // 1 表示开启,0 表示关闭#define powerup (1<>switchpinnumber1) & 0x01 ;
因此,根据哪个开关值是高电平,会发生 adc 转换,然后在成功转换 adc(0 到 1023)值后,将其映射为(0 到 2045),然后将占空比值写入(pwmmrx) pwm 引脚连接到伺服电机。而且,led 会变高以指示按下了哪个开关。以下是第一个按钮的示例
if(switchstatus1 == 1) { iopin1 = (16) & 0x3ff; //获取adc值 result1 = map(convert1,0,1023,0,2450); //将 adc 值转换为 pwm 的 占空比 pwmmr5 = result1; //设置占空比值为 pwm5 pwmler = 0x20; //启用 pwm5 delay_ms(2); } } 其他 { iopin1 = (0<
取放机械臂的工作
将代码上传到 lpc2148 后,按下任意开关并改变相应的电位器来改变机械臂的位置。
每个开关和电位器控制每个伺服电机的运动,即底座向左或向右运动,向上或向下运动,向前或向后运动,然后夹具保持和释放运动。
//使用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 表示关闭
#define 上电 (1<<21)
#define start_now ((0<<26)|(0<<25)|(1<<24)) //001 立即开始转换
#define adc_done (1ul<<31)
#define vref 3.3 //vref 引脚的参考电压
易失性int结果1 = 0;
易失性int结果2 = 0;
易失性int结果3 = 0;
易失性int结果4 = 0;
易失性 int 转换 1=0;
易失性int转换2 = 0;
易失性 int 转换 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) // 映射函数来转换范围
{
返回 (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
void delay_ms(uint16_t j) /* 循环产生 1 毫秒延迟,cclk = 60mhz */
{
uint16_t x,i;
for(i=0;i {
对于(x=0;x<6000;x++);
}
}
主函数()
{
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管脚为输出,开关管脚为输入
无符号长 ad0cr_setup = (clkdivswitchpinnumber1) & 0x01 ; // 读取开关状态
switchstatus2 = (iopin1>>switchpinnumber2) & 0x01; // 读取开关状态
switchstatus3 = (iopin1>>switchpinnumber3) & 0x01 ; // 读取开关状态
switchstatus4 = (iopin1>>switchpinnumber4) & 0x01; // 读取开关状态
if(switchstatus1 == 1) //根据开关状态打开/关闭 led 并开始 adc 转换
{
iopin1 = (16) & 0x3ff; //获取adc值
结果 1 = 地图(转换 1,0,1023,0,2450);//根据占空比为 pwm 转换 adc 值
pwmmr5 = 结果1;//将占空比值设置为pwm5
pwmler = 0x20;//启用pwm5
延迟毫秒(2);
}
}
别的
{
iopin1 = (0< }
if(switchstatus2 == 1) //根据开关状态打开/关闭 led 并开始 adc 转换
{
iopin1 = (16) & 0x3ff; //获取adc值
结果 2 = 地图(转换 2,0,1023,0,2450);//根据占空比为 pwm 转换 adc 值
pwmmr4 = 结果2;//将占空比值设置为pwm4
pwmler = 0x10;//启用pwm4
延迟毫秒(2);
}
} 别的
{
iopin1 = (0< }
if(switchstatus3 == 1) //根据开关状态打开/关闭 led 并开始 adc 转换
{
iopin1 = (16) & 0x3ff; //获取adc值
结果 3 = 地图(转换 3,0,1023,0,2450);//根据占空比为 pwm 转换 adc 值
pwmmr3 = 结果3;//将占空比值设置为pwm3
pwmler = 0x08;//启用pwm3
延迟毫秒(2);
}
} 别的
{
iopin1 = (0< }
if(switchstatus4 == 1) //根据开关状态打开/关闭 led 并开始 adc 转换
{
iopin1 = (16) & 0x3ff; //获取adc值
结果4 =地图(转换4,0,1023,0,2450);//根据占空比为 pwm 转换 adc 值
pwmmr2 = 结果4;//将占空比值设置为 pwm pwmler = 0x04; //启用pwm2
延迟毫秒(2);
}
} 别的
{
iopin1 = (0< }
}
}
海康威视对于中兴事件的看法
微软Win7 技术为什么支持停止 Win10?
【开源获奖案例】四轴机械臂控制系统
网线千兆百兆的区别
赛灵思与业界领先的电源管理公司合作提供产品电源要求指南
使用ARM7 LPC2148微控制器构建一个简单的机械臂
智能网联汽车与智慧城市协同发展成果推广活动举行
直播预告|WINSOK(微硕)专场&quot;功率器件在无刷电机上的应用&quot;
人工智能的未来能在多大程度上代替人类
利用机器视觉的摄像机标定方法研究
电阻器的参数特性与应用分析
小米预热众筹新品 让小户型也能拥有4K激光巨幕影院
业内快讯:比亚迪海外市场订单井喷、宁德时代总营收93亿元
指夹式血氧仪的测量原理是什么
为什么区块链的panacea在网络安全中如此迫切需要
「RVBoards-哪吒」首个体验贴?(全志D1,RISC-V 64bit)
多串流MIMO驱动 11ac射频前端迈向28nm
西门子PLC入门—正反转电路图解
有线网,有线网的结构是什么?
iphone8什么时候上市?iphone8最新消息:iphone8竟然长这样,冷艳高贵!发布时间在6月?