六轴串联机械臂工训纪实
1 工程训练纪实前言
这是南京理工大学暑期工程训练(金工实习)机器人项目第一天的记录博客,记录了六轴串联机械臂的全过程细节,第一天的项目比较简单,内容不深。在此先向这一个月中的各位老师表达感谢,尤其感谢张小兵教授的教导。先叠个甲,以后的学弟学妹请勿完全照抄本文本人方案,仅为我个人记录,吾技术浅薄,仅供参考。
2 组装过程
2.1 结构说明
六轴协作机械臂是一种具有六个自由度的机械臂,六轴协作机械臂之所以称为六轴,是因为它包含六个关节,每个关节都能够独立运动,它可以在六个方向上进行运动。这六个方向分别是:上下运动(沿着Z轴)、前后运动(沿着Y轴)、左右运动(沿着X轴)、绕X轴旋转、绕Y轴旋转和绕Z轴旋转。这种设计使得机械臂能够在六个自由度上进行灵活的运动,可以在三维空间内进行复杂的运动和操作,从而达到更加精确和高效的操作。这些关节通常由电机和传动装置控制,能够以精确的速度和力度进行移动和操作。
2.2 具体步骤
2.2.1 注意事项
①注意请在伺服电机初始化调试后进行组装。
②注意舵机垫片螺纹是否清晰
③尽量改进爪口结构,使之易于抓夹
2.2.2 机械臂组装
2.2.3 夹持机构组装
3 调整电控
3.1 伺服电机初始化
在上课之前,老师会提前发一个压缩包,里面有各种各样的工具软件还有半成品代码,这里就要用到arduino和controller。
先将以下命名为servo_bigfish.ino的代码通过arduino烧录进开发板中。
/*
* Bigfish扩展板舵机口; 4, 7, 11, 3, 8, 12, 14, 15, 16, 17, 18, 19
* 使用软件调节舵机时请拖拽对应序号的控制块
*/
#include <Servo.h>
#define ANGLE_VALUE_MIN 0
#define ANGLE_VALUE_MAX 180
#define PWM_VALUE_MIN 500
#define PWM_VALUE_MAX 2500
#define SERVO_NUM 12
Servo myServo[SERVO_NUM];
int data_array[2] = {0,0}; //servo_pin: data_array[0], servo_value: data_array[1];
int servo_port[SERVO_NUM] = {4, 7, 11, 3, 8, 12, 14, 15, 16, 17, 18, 19};
int servo_value[SERVO_NUM] = {};
String data = "";
boolean dataComplete = false;
void setup() {
Serial.begin(9600);
}
void loop() {
while(Serial.available())
{
int B_flag, P_flag, T_flag;
data = Serial.readStringUntil('\n');
data.trim();
for(int i=0;i<data.length();i++)
{
//Serial.println(data[i]);
switch(data[i])
{
case '#':
B_flag = i;
break;
case 'P':
{
String pin = "";
P_flag = i;
for(int i=B_flag+1;i<P_flag;i++)
{
pin+=data[i];
}
data_array[0] = pin.toInt();
}
break;
case 'T':
{
String angle = "";
T_flag = i;
for(int i=P_flag+1;i<T_flag;i++)
{
angle += data[i];
}
data_array[1] = angle.toInt();
servo_value[pin2index(data_array[0])] = data_array[1];
}
break;
default: break;
}
}
/*
Serial.println(B_flag);
Serial.println(P_flag);
Serial.println(T_flag);
for(int i=0;i<2;i++)
{
Serial.println(data_array[i]);
}
*/
dataComplete = true;
}
if(dataComplete)
{
for(int i=0;i<SERVO_NUM;i++)
{
ServoGo(i, servo_value[i]);
/*********************************串口查看输出***********************************/
// Serial.print(servo_value[i]);
// Serial.print(" ");
}
// Serial.println();
/*********************************++++++++++++***********************************/
dataComplete = false;
}
}
void ServoStart(int which){
if(!myServo[which].attached() && (servo_value[which] != 0))myServo[which].attach(servo_port[which]);
else return;
pinMode(servo_port[which], OUTPUT);
}
void ServoStop(int which){
myServo[which].detach();
digitalWrite(servo_port[which],LOW);
}
void ServoGo(int which , int where){
ServoStart(which);
if(where >= ANGLE_VALUE_MIN && where <= ANGLE_VALUE_MAX)
{
myServo[which].write( where);
}
else if(where >= PWM_VALUE_MIN && where <= PWM_VALUE_MAX)
{
myServo[which].writeMicroseconds(where);
}
}
int pin2index(int _pin){
int index;
switch(_pin)
{
case 4: index = 0; break;
case 7: index = 1; break;
case 11: index = 2; break;
case 3: index = 3; break;
case 8: index = 4; break;
case 12: index = 5; break;
case 14: index = 6; break;
case 15: index = 7; break;
case 16: index = 8; break;
case 17: index = 9; break;
case 18: index = 10; break;
case 19: index = 11; break;
}
return index;
}
代码烧录后,进入controller选择端口号及波特率(9600)进行连接,在对应模块中拖动控制条,使电机转动,最终置于90°的位置,伺服电机初始化调整成功。
单独连接舵机调试,分别在controller中拖动进度条,可以观察相应的舵机角度转动,做好相应的记录,写好对应的舵机调试角度。
3.2 电路搭建
伺服电机接线次序为,由上至下4、7、11、3、8、12。
3.3 机械臂自动化控制设计
在arduino中打开老师提供的jixieshoubi.ino进行编程,如下所示。
#include <Servo.h>
#define OPERATE_TIME 3000
int nInitialDeg[6]={72,35,118,58,80,60};//六个舵机初始角度
int nGetDeg[6]={82,65,155,66,80,15};//六个舵机运动到抓取目标物的角度
int nPutDeg[6]={20,65,155,66,80,60};//六个舵机运动到释放目标物的角度
int nServoPin[6]={3,4,7,8,11,12};//六个舵机对象对应的引脚
Servo myServo[6];
void setup() //初始化函数,上电后只执行一次
{
pinMode(9,INPUT);
resetArm();//对机械臂进行初始化,包括绑定舵机引脚,运行至初始化状态
}
void loop() //循环函数,反复执行
{
int nState=digitalRead(9);
if(nState==0)
{
getCube(); //到目标点抓取物体
delay(1000);
putCube(); //到目标点释放物体
delay(2000);//延时等待2秒
}
}
void resetArm()//机械臂初始形态,此时建议夹爪张开
{
for(int i = 0; i < 6; i++)
{
myServo[i].attach(nServoPin[i]);//舵机对象绑定引脚
myServo[i].write(nInitialDeg[i]);//相应舵机运行至指定初始化位置
delay(1000);
}
}
void getCube()//抓取目标物体
{
for(int i=0;i<6;i++)
{
ServoMove(i, nInitialDeg[i], nGetDeg[i], OPERATE_TIME);//控制各个舵机由初始化位置运行至目标物位置,并执行夹爪闭合动作,以抓取目标物体
}
for(int i=4;i>=0;i--)
{
ServoMove(i, nGetDeg[i], nInitialDeg[i], OPERATE_TIME);//保持夹爪状态不变,其他舵机逆序由目标物位置返回初始化位置
}
}
void putCube() //释放目标物体
{
for(int i=0;i<5;i++)
{
ServoMove(i, nInitialDeg[i], nPutDeg[i], OPERATE_TIME);//控制除夹爪以外各个舵机由初始化位置运行至释放位置
}
ServoMove(5, nGetDeg[5], nPutDeg[5], OPERATE_TIME);//控制夹爪舵机角度,由夹爪闭合状态转为张开状态,以释放目标物体
for(int i=4;i>=0;i--)
{
ServoMove(i, nPutDeg[i], nInitialDeg[i], OPERATE_TIME);//除夹爪舵机外所有舵机逆序由释放位置返回初始化位置
}
}
void ServoMove(int which, int _start, int _finish, long t) //控制指定舵机(which)在指定时间(t)由初始位置(_start)运动到目标位置(_finish)
{
static int direct;
static int diff;
static long deltaTime;
if(_start <= _finish)
direct = 1;
else
direct = -1;
diff = abs(_finish - _start);
deltaTime = (long) (t / 180);
for(int i = 0; i < diff; i++)
{
myServo[which].write(_start + i * direct);
delay(deltaTime);
}
}
在以下代码中,填写之前记录的数据。
int nInitialDeg[6]={72,35,118,58,80,60};//六个舵机初始角度
int nGetDeg[6]={82,65,155,66,80,15};//六个舵机运动到抓取目标物的角度
int nPutDeg[6]={20,65,155,66,80,60};//六个舵机运动到释放目标物的角度
int nServoPin[6]={3,4,7,8,11,12};//六个舵机对象对应的引脚
填写完成后,编译程序,连接开发板,选择正确的端口并上传。