1. 功能描述
R323样机是一款拥有6自由度的串联机械臂。本文提供的示例所实现的功能为:在6自由度串联机械臂样机上安装电磁铁,底座上安装近红外传感器,当检测到有物品时,实现机械臂电磁铁搬运物品的功能。
2. 电子硬件
在这个示例中,我们采用了以下硬件,请大家参考:
主控板 | Basra(兼容Arduino Uno) |
扩展板 | Bigfish2.1 |
舵机 | 270°伺服电机、标准舵机 |
传感器 | 近红外传感器 |
电池 | 7.4V锂电池 |
其它 | 电磁铁、USB线 |
电路连接说明:
注:
① 270°伺服电机分别连接在Bigfish扩展板D4、D7、D11、D3、D8、D12接口上
② 2个近红外传感器分别连接在A0及A4接口上
③ 电磁铁连接在Bigfish扩展板D9,D10接口上
3. 功能实现
上位机:Controller 1.0
下位机编程环境:Arduino 1.8.19
3.1初始位置的设定
① 将Controller下位机程序servo_bigfish.ino直接下载到主控板。这段代码供Controller上位机与主控板通信,并允许调试舵机。代码如下:
/*------------------------------------------------------------------------------------版权说明:Copyright 2023 Robottime(Beijing) Technology Co., Ltd. All Rights Reserved.Distributed under MIT license.See file LICENSE for detail or copy athttps://opensource.org/licenses/MITby 机器谱 2023-01-31 https://www.robotway.com/------------------------------/** 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 12Servo 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;}
下载完成后,保持主控板和电脑的USB连接,以便利用上位机进行调试。
② 双击打开Controller 1.0b.exe:
③ 界面左上角选择:设置-面板设置,弹出需要显示的调试块,可通过勾选隐藏不需要调试的舵机块:联机-选择主控板对应端口号以及波特率。
④ 拖动进度条,可以观察相应的舵机角度转动。写好对应的舵机调试角度,勾选左下角添加-转化,获得舵机调试的数组:
⑤ 将该数组直接复制到相应的arduino软件的程序中进行使用。
3.2调试好角度后将电磁铁搬运例程(jixieshoubi.ino)下载到主控板:
/*------------------------------------------------------------------------------------版权说明:Copyright 2023 Robottime(Beijing) Technology Co., Ltd. All Rights Reserved.Distributed under MIT license.See file LICENSE for detail or copy athttps://opensource.org/licenses/MITby 机器谱 2023-02-07 https://www.robotway.com/------------------------------*///#define EYEINIT 174#define HEADINIT 90#define NECKINIT 124#define UPBODYINIT 72#define DOWNBODYINIT 100#define FOOTINIT 88#define EYE0 130#define HEAD0 90#define NECK0 170#define UPBODY0 160#define DOWNBODY0 79#define FOOT0 36#define EYE1 130#define HEAD1 90#define NECK1 170#define UPBODY1 160#define DOWNBODY1 80#define FOOT1 130#include<Wire.h>#include <Servo.h> #define PIN_SERVO_EYE 4 //定义各个舵机所对应的端口;#define PIN_SERVO_HEAD 7#define PIN_SERVO_NECK 11#define PIN_SERVO_UPBODY 3#define PIN_SERVO_DOWNBODY 8#define PIN_SERVO_FOOT 12#define OPERATE_TIME 3000#define SERVO_EYE 0 //定义各个舵机所对应的端口;#define SERVO_HEAD 1#define SERVO_NECK 2#define SERVO_UPBODY 3#define SERVO_DOWNBODY 4#define SERVO_FOOT 5int servoPin[6] = {PIN_SERVO_EYE, PIN_SERVO_HEAD, PIN_SERVO_NECK, PIN_SERVO_UPBODY,PIN_SERVO_DOWNBODY,PIN_SERVO_FOOT};Servo myServo[6];void setup() {// put your setup code here, to run once:delay(1000);Serial.begin(9600);resetArm();}void loop() {// put your main code here, to run repeatedly:resetArm(); //机械臂复位getCube(); //机械臂开始抓取货物putCube(); //机械臂开始释放货物delay(2000);//等待2秒}void resetArm(){ //舵机复位函数;for(int i = 0; i < 6; i++)myServo[i].attach(servoPin[i]);myServo[SERVO_EYE].write(EYEINIT);myServo[SERVO_HEAD].write(HEADINIT);myServo[SERVO_NECK].write(NECKINIT);myServo[SERVO_UPBODY].write(UPBODYINIT);myServo[SERVO_DOWNBODY].write(DOWNBODYINIT);myServo[SERVO_FOOT].write(FOOTINIT);delay(1500);}void getCube(){ //抓取物料动作序列函数;ServoMove(SERVO_FOOT, FOOTINIT, FOOT0, OPERATE_TIME);ServoMove(SERVO_UPBODY, UPBODYINIT,UPBODY0, OPERATE_TIME);ServoMove(SERVO_HEAD, HEADINIT, HEAD0, OPERATE_TIME);ServoMove(SERVO_NECK, NECKINIT, NECK0, OPERATE_TIME);ServoMove(SERVO_EYE, EYEINIT, EYE0, OPERATE_TIME);ServoMove(SERVO_DOWNBODY, DOWNBODYINIT, DOWNBODY0, OPERATE_TIME);ServoMove(SERVO_HEAD, HEAD0, HEADINIT, OPERATE_TIME);ServoMove(SERVO_UPBODY, UPBODY0, UPBODYINIT, OPERATE_TIME);ServoMove(SERVO_EYE, EYE0, EYEINIT, OPERATE_TIME);ServoMove(SERVO_NECK, NECK0, NECKINIT, OPERATE_TIME);ServoMove(SERVO_DOWNBODY, DOWNBODY0, DOWNBODYINIT, OPERATE_TIME);}void putCube() //机械臂开始释放货物{ServoMove(SERVO_FOOT, FOOT0, FOOT1 , OPERATE_TIME);ServoMove(SERVO_HEAD, HEADINIT, HEAD1, OPERATE_TIME);ServoMove(SERVO_NECK, NECKINIT, NECK1, OPERATE_TIME);ServoMove(SERVO_UPBODY, UPBODYINIT,UPBODY1, OPERATE_TIME);ServoMove(SERVO_EYE, EYEINIT, EYE1, OPERATE_TIME);ServoMove(SERVO_DOWNBODY, DOWNBODYINIT, DOWNBODY1, OPERATE_TIME); ServoMove(SERVO_HEAD, HEAD1, HEADINIT, OPERATE_TIME);ServoMove(SERVO_UPBODY, UPBODY1, UPBODYINIT, OPERATE_TIME);ServoMove(SERVO_EYE, EYE1, EYEINIT, OPERATE_TIME);ServoMove(SERVO_NECK, NECK1, NECKINIT, OPERATE_TIME);ServoMove(SERVO_DOWNBODY, DOWNBODY1, DOWNBODYINIT, OPERATE_TIME);ServoMove(SERVO_FOOT, FOOT1, FOOTINIT , OPERATE_TIME); }void ServoMove(int which, int _start, int _finish, long t) //舵机动作函数:它有四个参数,舵机号,初始角度,目标角度,动作时间;{static int direct;static int diff;static long deltaTime;if(_start <= _finish)direct = 1;elsedirect = -1;diff = abs(_finish - _start);deltaTime = (long) (t / 180);for(int i = 0; i < diff; i++){myServo[which].write(_start + i * direct);Serial.println(_start + i * direct);delay(deltaTime);}}
4. 资料内容
①电磁铁搬运-程序源代码
②电磁铁搬运-样机3D文件
③Controller1.0b资料包
资料内容详见 6自由度串联机械臂-电磁铁搬运