ARDUINO机械臂实验报告111
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
NANCHANG UNIVERSITY
综合设计报告
题目基于Arduino的简易机械臂
学院:信息工程学院系电子系
专业班级:电子信息类xxx班
学生姓名:xxx 学号:xxx
指导教师:xxx xxx
起讫日期:2017.6.26--2017.9.1
基于Arduino 的简易机械臂
摘要
Arduino是一款便捷灵活、方便上手的开源电子原型平台。
Arduino IDE基于processing IDE开发。
对于初学者来说,极易掌握,同时有着足够的灵活性。
Arduino语言基于wiring语言开发,是对 avr-gcc库的二次封装,不需要太多的单片机基础、编程基础。
Arduino不仅仅是全球最流行的开源硬件,也是一个优秀的硬件开发平台,更是硬件开发的趋势。
Arduino简单的开发方式使得开发者更关注创意与实现,更快的完成自己的项目开发,大大节约了学习的成本,缩短了开发的周期。
越来越多的专业硬件开发者已经或开始使用Arduino来开发他们的项目、产品;越来越多的软件开发者使用Arduino进入硬件、物联网等开发领域;大学里,自动化、软件,甚至艺术专业,也纷纷开展了Arduino相关课程。
安卓手机与Arduino之间采用蓝牙串口通讯,是很多智能装置和互动装置常用的控制方法,简单而有效,无需网络环境,很实用的技术。
通过Arduino 与机械臂上的舵机结合,使其可以和电脑通信,再通过手机蓝牙控制Arduino 进而控制机械臂。
用实现简单的抓取动作。
关键词:Arduino UNO;机械臂;简单
目录
第一章 (2)
1.1实验目的 ............................................................................................ 错误!未定义书签。
1.2实验器材 ............................................................................................ 错误!未定义书签。
1.3实验原理 (2)
第二章 (5)
2.1实验程序设计 (5)
2.2功能实现........................................................................................ 错误!未定义书签。
2.3实物图 (6)
第三章 ............................................................................................................... 错误!未定义书签。
3.1结论与展望 ........................................................................................ 错误!未定义书签。
附录 .. (8)
源代码 (8)
1
第一章
1.1 实验目的
掌握Arduino进行串口通信的原理,熟练使用Arduino UNO开发板。
了解HC-06蓝牙模块工作原理。
掌握机械臂工作原理。
1.2 实验器材
制作机械臂的亚克力板套件 x 1
Arduino UNO开发板 x 1
HC-06蓝牙模块 x 1
电源模块 x 1
面包板 x 1
安卓手机 x 1
面包板跳线若干
杜邦线(公对公) x 20
9g舵机 x 4
USB线(公对公) x 1
充电宝或其它可为面包板供电的设备 x 1
1k 欧姆电阻 X 1 (HC-06模块需要)
20k 欧姆电阻 X 1(HC-06模块需要)
1.3 实验原理
人为编写程序烧录Arduino,Arduino通过控制四个舵机的转动进而控制整个机械臂的运行。
蓝牙技术是一种近距离地保证可靠接受和信息安全的无线通信技术。
蓝牙的工作频段为2.402~2.480GHz,为免费的工业、科学、医学频段,调频速率为1600次/s,同时连接的最大设备数为7个,有效的最大传输距离为10米。
2
Arduino UNO是基于ATmega328P 的单片机开发板。
该开发板由14路数字输入/输出引脚(其中6路可以用作PWM输出)、 6路模拟输入、1个16MHz的石英晶体振荡器、一个USB接口、1个电源接头、1个ICSP数据头以及1个复位按钮组成。
Uno 包含了单片机运行所需的所有要素,只需用USB连接线将其连接到计算机,或利用AC-DC 适配器或电池供电后即可启动。
Uno 的特色在于将Atmega16U2 编程为一个 USB-to-serial 转换器,以便能简单、轻松和自由地安装驱动程序。
Arduino开发使用java开发的编程环境,使用类c语言编程,并提供丰富的库函数。
Aeduino是免费开源的,所有资源都可以免费下载,只需要一根USB线即可完成编程和烧写。
其工作电压为5V,出入电压在7~12V为最佳,最大范围为6~20V。
板上主要资源
技术规格
3
舵机的伺服系统由可变宽度的脉冲来进行控制,控制线是用来传送脉冲的。
脉冲的参数有最小值,最大值,和频率。
一般而言,舵机的基准信号都是周期为20ms,宽度为1.5ms。
这个基准信号定义的位置为中间位置。
舵机有最大转动角度,中间位置的定义就是从这个位置到最大角度与最小角度的量完全一样。
最重要的一点是,不同舵机的最大转动角度可能不相同,但是其中间位置的脉冲宽度是一定的,那就是1.5ms。
角度是由来自控制线的持续的脉冲所产生。
这种控制方法叫做脉冲调制。
脉冲的长短决定舵机转动多大角度。
例如:1.5毫秒脉冲会到转动到中间位置(对于180°舵机来说,就是90°位置)。
当控制系统发出指令,让舵机移动到某一位置,并让他保持这个角度,这时外力的影响不会让他角度产生变化,但是这个是由上限的,上限就是他的最大扭力。
除非控制系统不停的发出脉冲稳定舵机的角度,舵机的角度不会一直不变。
当舵机接收到一个小于1.5ms 的脉冲,输出轴会以中间位置为标准,逆时针旋转一定角度。
接收到的脉冲大于1.5ms情况相反。
不同品牌,甚至同一品牌的不同舵机,都会有不同的最大值和最小值。
一般而言,最小脉冲为1ms,最大脉冲为2ms。
4
第二章
2.1 实验程序设计
按要求将亚克力板和舵机组装好。
Arduino Uno与各个舵机连接好。
接法如下:
UNO板接口接向电脑USB端口用于传输程序,电源模块可用充电宝给其供电。
从网络上寻找合适的蓝牙连接软件,我选择的是Arduino Bluetooth controller。
参考网络上控制舵机的程序编写代码
5
2.2 功能实现
将舵机的运动分解为水平方向和竖直方向运动,用四个舵机实现机械臂再空间范围内的上下前后左右运动;来达到将细微物体夹取并移动。
2.3 实物图
6
3.1 结论与展望
在制作Arduino机械臂的过程中,由于配件过多,组装机械臂花费了我大量时间,在程序的编写过程中我也遇到了很多困难,最后通过参考网上的教程终于完成了代码的编写。
通过本次Arduino项目的制作我对于Arduino开发板有了更深刻的认识,也初步的了解了伺服舵机的工作原理,对串口通信有了一定的了解。
7
实验源代码
/*
1 使用串口获得电机数据,设置机械臂动作
将串口指令解读改写为函数,加入状态汇报函数reportStatus
2 加入servoCmd函数控制电机速度
3 加入判断人类指令是否超出舵机限值
4 MeArm执行一系列动作(执行程序) armIniPos - 1 (一维数组)
5 MeArm执行一系列动作(执行程序) armIniPos - 2 (二维数组)
6 加入手柄控制模式
加入机器判断:人类输入信息错误检查
*/
#include <Servo.h> //使用servo库
Servo base, fArm, rArm, claw ; //创建4个servo对象
//存储电机极限值(const指定该数值为常量,常量数值在程序运行中不能改变) const int baseMin = 0;
const int baseMax = 180;
const int rArmMin = 45;
const int rArmMax = 180;
const int fArmMin = 35;
const int fArmMax = 120;
const int clawMin = 25;
const int clawMax = 100;
8
int DSD = 15; //Default Servo Delay (默认电机运动延迟时间)
//此变量用于控制电机运行速度.增大此变量数值将
//降低电机运行速度从而控制机械臂动作速度。
bool mode; //mode = 1: 指令模式, mode = 0: 手柄模式
int moveStep = 3; // 每一次按下手柄按键,舵机移动量(仅适用于手柄模式)
void setup(){
base.attach(11); // base 伺服舵机连接引脚11 舵机代号'b'
delay(200); // 稳定性等待
rArm.attach(10); // rArm 伺服舵机连接引脚10 舵机代号'r'
delay(200); // 稳定性等待
fArm.attach(9); // fArm 伺服舵机连接引脚9 舵机代号'f'
delay(200); // 稳定性等待
claw.attach(6); // claw 伺服舵机连接引脚6 舵机代号'c'
delay(200); // 稳定性等待
base.write(81);
delay(10);
fArm.write(100);
delay(10);
rArm.write(90);
delay(10);
claw.write(95);
delay(10);
Serial.begin(9600);
Serial.println("Welcome to Taichi-Maker Robot Arm Tutorial");
}
9
void loop(){
if (Serial.available()>0) {
char serialCmd = Serial.read();
if( mode == 1 ){
armDataCmd(serialCmd); //指令模式
} else {
armJoyCmd(serialCmd); //手柄模式
}
}
}
void armDataCmd(char serialCmd){ //Arduino根据串行指令执行相应操作
//指令示例:b45 底盘转到45度角度位置
// o 输出机械臂舵机状态信息
//判断人类是否因搞错模式而输入错误的指令信息(指令模式下输入手柄按键信息)
if ( serialCmd == 'w' || serialCmd == 's' || serialCmd == 'a' || serialCmd == 'd'
|| serialCmd == '5' || serialCmd == '4' || serialCmd == '6' || serialCmd == '8' ){
Serial.println("+Warning: Robot in Instruction Mode...");
delay(100);
while(Serial.available()>0) char wrongCommand = Serial.read(); //清除串口缓存的错误指令
return;
}
10
if (serialCmd == 'b' || serialCmd == 'c' || serialCmd == 'f' || serialCmd == 'r'){
int servoData = Serial.parseInt();
servoCmd(serialCmd, servoData, DSD); // 机械臂舵机运行函数(参数:舵机名,目标角度,延迟/速度)
} else {
switch(serialCmd){
case 'm' : //切换至手柄模式
mode = 0;
Serial.println("Command: Switch to Joy-Stick Mode.");
break;
case 'o': // 输出舵机状态信息
reportStatus();
break;
case 'i':
armIniPos();
break;
default: //未知指令反馈
Serial.println("Unknown Command.");
}
}
}
11
void armJoyCmd(char serialCmd){ //Arduino根据手柄按键执行相应操作
//判断人类是否因搞错模式而输入错误的指令信息(手柄模式下输入舵机指
令)
if (serialCmd == 'b' || serialCmd == 'c' || serialCmd == 'f' || serialCmd == 'r'){
Serial.println("+Warning: Robot in Joy-Stick Mode...");
delay(100);
while(Serial.available()>0) char wrongCommand = Serial.read();
//清除串口缓存的错误指令
return;
}
int baseJoyPos;
int rArmJoyPos;
int fArmJoyPos;
int clawJoyPos;
switch(serialCmd){
case 'a': // Base向左
Serial.println("Received Command: Base Turn Left");
baseJoyPos = base.read() - moveStep;
servoCmd('b', baseJoyPos, DSD);
break;
case 'd': // Base向右
Serial.println("Received Command: Base Turn Right");
baseJoyPos = base.read() + moveStep;
12
servoCmd('b', baseJoyPos, DSD);
break;
case 's': // rArm向下
Serial.println("Received Command: Rear Arm Down"); rArmJoyPos = rArm.read() + moveStep;
servoCmd('r', rArmJoyPos, DSD);
break;
case 'w': // rArm向上
Serial.println("Received Command: Rear Arm Up");
rArmJoyPos = rArm.read() - moveStep;
servoCmd('r', rArmJoyPos, DSD);
break;
case '8': // fArm向上
Serial.println("Received Command: Front Arm Up");
fArmJoyPos = fArm.read() + moveStep;
servoCmd('f', fArmJoyPos, DSD);
break;
case '5': // fArm向下
Serial.println("Received Command: Front Arm Down");
fArmJoyPos = fArm.read() - moveStep;
servoCmd('f', fArmJoyPos, DSD);
break;
13
case '4': // Claw关闭
Serial.println("Received Command: Claw Close Down"); clawJoyPos = claw.read() + moveStep;
servoCmd('c', clawJoyPos, DSD);
break;
case '6': // Claw打开
Serial.println("Received Command: Claw Open Up");
clawJoyPos = claw.read() - moveStep;
servoCmd('c', clawJoyPos, DSD);
break;
case 'm' : //切换至指令模式
mode = 1;
Serial.println("Command: Switch to Instruction Mode.");
break;
case 'o':
reportStatus();
break;
case 'i':
armIniPos();
break;
default:
Serial.println("Unknown Command.");
14
return;
}
}
void servoCmd(char servoName, int toPos, int servoDelay){
Servo servo2go; //创建servo对象
//串口监视器输出接收指令信息
Serial.println("");
Serial.print("+Command: Servo ");
Serial.print(servoName);
Serial.print(" to ");
Serial.print(toPos);
Serial.print(" at servoDelay value ");
Serial.print(servoDelay);
Serial.println(".");
Serial.println("");
int fromPos; //建立变量,存储电机起始运动角度值
switch(servoName){
case 'b':
if(toPos >= baseMin && toPos <= baseMax){
servo2go = base;
fromPos = base.read(); // 获取当前电机角度值用于“电机运动起始角度值”
break;
} else {
15
Serial.println("+Warning: Base Servo Value Out Of Limit!");
return;
}
case 'c':
if(toPos >= clawMin && toPos <= clawMax){
servo2go = claw;
fromPos = claw.read(); // 获取当前电机角度值用于“电机运动起始角度值”
break;
} else {
Serial.println("+Warning: Claw Servo Value Out Of Limit!");
return;
}
case 'f':
if(toPos >= fArmMin && toPos <= fArmMax){
servo2go = fArm;
fromPos = fArm.read(); // 获取当前电机角度值用于“电机运动起始角度值”
break;
} else {
Serial.println("+Warning: fArm Servo Value Out Of Limit!");
return;
}
case 'r':
if(toPos >= rArmMin && toPos <= rArmMax){
16
servo2go = rArm;
fromPos = rArm.read(); // 获取当前电机角度值用于“电机运动起始角度值”
break;
} else {
Serial.println("+Warning: rArm Servo Value Out Of Limit!");
return;
}
}
//指挥电机运行
if (fromPos <= toPos){ //如果“起始角度值”小于“目标角度值”
for (int i=fromPos; i<=toPos; i++){
servo2go.write(i);
delay (servoDelay);
}
} else { //否则“起始角度值”大于“目标角度值”
for (int i=fromPos; i>=toPos; i--){
servo2go.write(i);
delay (servoDelay);
}
}
}
void reportStatus(){ //舵机状态信息
Serial.println("");
Serial.println("");
Serial.println("+ Robot-Arm Status Report +");
17
Serial.print("Claw Position: "); Serial.println(claw.read());
Serial.print("Base Position: "); Serial.println(base.read());
Serial.print("Rear Arm Position:"); Serial.println(rArm.read());
Serial.print("Front Arm Position:"); Serial.println(fArm.read());
Serial.println("++++++++++++++++++++++++++");
Serial.println("");
}
void armIniPos(){
Serial.println("+Command: Restore Initial Position.");
int robotIniPosArray[4][3] = {
{'b', 90, DSD},
{'r', 90, DSD},
{'f', 90, DSD},
{'c', 90, DSD}
};
for (int i = 0; i < 4; i++){
servoCmd(robotIniPosArray[i][0], robotIniPosArray[i][1], robotIniPosArray[i][2]);
}
}
}
18。