面包板电源模块为机器臂单独供电,机器臂本身有四个小电机驱动作用,如果单独靠arduino来为这四个小电机供电,机器臂可能不会稳定工作,将会抖动。
机械臂的四个动作主要靠四个电机来控制,这四个电机主要连接在我们的arduino控制器上,通过audino的编程,可以对这四个电机发送相应的指令,然后电机就会驱动机械臂做出相应的动作。
伺服电机
这四个电机学名叫做直流伺服电机(舵机)(下图为其结构)。
输出轴上往往会加上一个摇臂,摇臂就会驱动我们想用电机驱动的那些外界的装置了,输出轴下面连接了一个电位器,输出轴在转动的时候,底下电位器也会跟着旋转,电位器旋转的过程中,电压信号就会随之改变,电压信号发送到控制电路上面,控制电路根据接受的信号判断我们的输出是否跟arduino上控制的信号相同,从而调整电机。
#include <Servo.h>
Servo myservo; // create servo object to control a servo
// twelve servo objects can be created on most boards
int pos = 0; // variable to store the servo position
void setup() {
myservo.attach(9); // attaches the servo on pin 9 to the servo object
}
void loop() {
for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees
// in steps of 1 degree
myservo.write(pos); // tell servo to go to position in variable 'pos'
//Serial.print(pos);
delay(15); // waits 15 ms for the servo to reach the position
}
for (pos = 180; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15 ms for the servo to reach the position
}
}
串口通讯
上面返回值是一个数字(代表有几个字节),下面返回值是一个字符型数值。
**读取的完整过程: **
如果串口接收的是多个字节:逐个进行读取,读取一个清除一个
控制伺服电机
控制一个电机
#include<Servo.h>
Servo myServo; //创建Servo对象myServo
int dataIndex = 0; //存储输入数据序列号
void setup(){
myServo.attach(6);
Serial.begin(9600); //启动串口通讯
Serial.println(" Please input serial data.");
}
void loop(){ //检查串口缓存是否有数据等待传输
if(Serial.available()>0){
daaIndex++; //处理数据序列号并通过串口监视器显示
Serial.print("dataIndex: ");
Serial.print(dataIndex);
Serial.print(",");
int pos = Serial.parseInt(); //解析串口数据中的整数信息并赋值给变量pos
Serial.print("Set servo postion:");
Serial.println(pos); //通过串口监视器显示
myServo.write(pos); //使用pos变量数值设置伺服电机
delay(15);
}
}
结果图:
控制四个电机
#include<Servo.h>
Servo base,fArm,rArm,claw; //创建4个电机对象
int dataIndex = 0; //存储输入数据序列号
void setup(){
base.attach(11); //base 伺服电机链接引脚11 b
rArm.attach(10); //rArm 伺服电机连接引脚10 r
fArm.attach(9); //fArm 伺服电机连接引脚9 f
claw.attach(6); //claw 伺服电机链接引脚6 c
Serial.begin(9600); //启动串口通讯
Serial.println(" Please input serial data.");
}
void loop(){ //检查串口缓存是否有数据等待传输
if(Serial.available()>0){
char servoName = Serial.read();//获取电机指令中电机编号信息
Serial.print("servoName: ");
Serial.print(servoName);
Serial.print(",");
int data = Serial.parseInt(); //获取电机指令中电机角度信息
switch(servoName){ //根据电机指令中电机信息决定对哪一个电机进行角度设置
case 'b': //电机指令b,设置base电机角度
base.write(data);
Serial.print("Set base servo value: ");
Serial.pritnln(data);
break;
case 'r': //电机指令r,设置rArm电机角度
rArm.write(data);
Serial.print("Set rArm servo value: ");
Serial.pritnln(data);
break;
case 'f': //电机指令f,设置rArm电机角度
rArm.write(data);
Serial.print("Set rArm servo value: ");
Serial.pritnln(data);
break;
case 'c': //电机指令b,设置claw电机角度
claw.write(data);
Serial.print("Set claw servo value: ");
Serial.pritnln(data);
break;
}
Serial.print("Set servo postion:");
Serial.println(pos); //通过串口监视器显示
myServo.write(pos); //使用pos变量数值设置伺服电机
delay(15);
}
}
meArm机械臂组装
调试meArm机械臂
#include <Servo.h> //使用servo库
Servo base, fArm, rArm, claw ; //创建4个servo对象
// 建立4个int型变量存储当前电机角度值
// 初始角度值为设备启动后初始状态所需要的电机角度数值
int basePos = 90;
int rArmPos = 90;
int fArmPos = 90;
int clawPos = 90;
//存储电机极限值(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;
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); // 稳定性等待
Serial.begin(9600);
Serial.println("Welcome to Taichi-Maker Robot Arm Tutorial.");
}
void loop(){
if (Serial.available()>0) { //使用串口监视器输入电机指令控制机械臂电机
char serialCmd = Serial.read();//指令举例: b45,将底盘舵机调整到45度位置
armDataCmd(serialCmd);
}
base.write(basePos);
delay(10);
fArm.write(fArmPos);
delay(10);
rArm.write(rArmPos);
delay(10);
claw.write(clawPos);
delay(10);
}
void armDataCmd(char serialCmd){
Serial.print("serialCmd = ");
Serial.print(serialCmd);
int servoData = Serial.parseInt();
switch(serialCmd){
case 'b':
basePos = servoData;
Serial.print(" Set base servo value: ");
Serial.println(servoData);
break;
case 'c':
clawPos = servoData;
Serial.print(" Set claw servo value: ");
Serial.println(servoData);
break;
case 'f':
fArmPos = servoData;
Serial.print(" Set fArm servo value: ");
Serial.println(servoData);
break;
case 'r':
rArmPos = servoData;
Serial.print(" Set rArm servo value: ");
Serial.println(servoData);
break;
case 'o':
reportStatus();
break;
default:
Serial.println(" Unknown Command.");
}
}
void reportStatus(){
Serial.println("");
Serial.println("");
Serial.println("++++++ Robot-Arm Status Report +++++");
Serial.print("Claw Position: clawPos = "); Serial.println(claw.read());
Serial.print("Base Position: basePos = "); Serial.println(base.read());
Serial.print("Rear Arm Position: rArmPos = "); Serial.println(rArm.read());
Serial.print("Front Arm Position: fArmPos = "); Serial.println(fArm.read());
Serial.println("++++++++++++++++++++++++++++++++++++");
Serial.println("");
}
控制机械臂运行速度(顺畅完成指令)
就是要进行舵机转动速度控制
#include <Servo.h> //使用servo库
Servo base, fArm, rArm, claw ; //创建4个servo对象
// 建立4个int型变量存储当前电机角度值
// 初始角度值为设备启动后初始状态所需要的电机角度数值
int basePos = 90;
int rArmPos = 90;
int fArmPos = 90;
int clawPos = 90;
//存储电机极限值(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;
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); // 稳定性等待
Serial.begin(9600);
Serial.println("Welcome to Taichi-Maker Robot Arm Tutorial");
}
void loop(){
if (Serial.available()>0) { //使用串口监视器输入电机指令控制机械臂电机
char serialCmd = Serial.read();//指令举例: b45,将底盘舵机(舵机代号'b')调整到45度位置
armDataCmd(serialCmd);
}
base.write(basePos);
delay(10);
fArm.write(fArmPos);
delay(10);
rArm.write(rArmPos);
delay(10);
claw.write(clawPos);
delay(10);
}
void armDataCmd(char serialCmd){
Serial.print("serialCmd = ");
Serial.print(serialCmd);
int fromPos; //起始位置
int toPos; //目标位置
int servoData = Serial.parseInt();
switch(serialCmd){
case 'b':
fromPos = base.read();//把舵机底盘当前的位置信息读出来
toPos = servoData;
//流畅过度到目标位置
// for(int i =fromPos;i<=toPos;i++){ //b135->b90,这个便不执行
// base.write(i);
// delay(15);
// }
if(fromPos<=toPos){
for(int i =fromPos;i<=toPos;i++){ //b135->b90,这个便不执行
base.write(i);
delay(15);
}
}
else{
for(int i =fromPos;i>=toPos;i--){ //b135->b90,这个便不执行
base.write(i);
delay(15);
}
}
basePos = servoData;
Serial.print(" Set base servo value: ");
Serial.println(servoData);
break;
case 'c':
clawPos = servoData;
Serial.print(" Set claw servo value: ");
Serial.println(servoData);
break;
case 'f':
fArmPos = servoData;
Serial.print(" Set fArm servo value: ");
Serial.println(servoData);
break;
case 'r':
rArmPos = servoData;
Serial.print(" Set rArm servo value: ");
Serial.println(servoData);
break;
case 'o':
reportStatus();
break;
default:
Serial.println(" Unknown Command.");
}
}
void reportStatus(){
Serial.println("");
Serial.println("");
Serial.println("++++++ Robot-Arm Status Report +++++");
Serial.print("Claw Position: clawPos = "); Serial.println(claw.read());
Serial.print("Base Position: basePos = "); Serial.println(base.read());
Serial.print("Rear Arm Position: rArmPos = "); Serial.println(rArm.read());
Serial.print("Front Arm Position: fArmPos = "); Serial.println(fArm.read());
Serial.println("++++++++++++++++++++++++++++++++++++");
Serial.println("");
}
开发机械臂程序
控制机械臂速度函数封装优化:
#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;
int DSD = 15; //Default Servo Delay (默认电机运动延迟时间)
//此变量用于控制电机运行速度.增大此变量数值将
//降低电机运行速度从而控制机械臂动作速度。
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(90);
delay(10);
fArm.write(90);
delay(10);
rArm.write(90);
delay(10);
claw.write(90);
delay(10);
Serial.begin(9600);
Serial.println("Welcome to Taichi-Maker Robot Arm Tutorial");
}
void loop(){
if (Serial.available()>0) {
char serialCmd = Serial.read();
armDataCmd(serialCmd);
}
}
void armDataCmd(char serialCmd){ //Arduino根据串行指令执行相应操作
//指令示例:b45 底盘转到45度角度位置
// o 输出机械臂舵机状态信息
if (serialCmd == 'b' || serialCmd == 'c' || serialCmd == 'f' || serialCmd == 'r'){
int servoData = Serial.parseInt();
servoCmd(serialCmd, servoData, DSD); // 机械臂舵机运行函数(参数:舵机名,目标角度,延迟/速度)
} else {
switch(serialCmd){
case 'o': // 输出舵机状态信息
reportStatus();
break;
default: //未知指令反馈
Serial.println("Unknown Command.");
}
}
}
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 {
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){
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 +");
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("");
}
键盘控制机械臂程序初版
#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;
int DSD = 15; //Default Servo Delay (默认电机运动延迟时间)
//此变量用于控制电机运行速度.增大此变量数值将
//降低电机运行速度从而控制机械臂动作速度。
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(90);
delay(10);
fArm.write(90);
delay(10);
rArm.write(90);
delay(10);
claw.write(90);
delay(10);
Serial.begin(9600);
Serial.println("Welcome to Taichi-Maker Robot Arm Tutorial");
}
void loop(){
if (Serial.available()>0) {
char serialCmd = Serial.read();
armDataCmd(serialCmd);
}
}
void armDataCmd(char serialCmd){ //Arduino根据串行指令执行相应操作
//指令示例:b45 底盘转到45度角度位置
// o 输出机械臂舵机状态信息
if (serialCmd == 'b' || serialCmd == 'c' || serialCmd == 'f' || serialCmd == 'r'){
int servoData = Serial.parseInt();
servoCmd(serialCmd, servoData, DSD); // 机械臂舵机运行函数(参数:舵机名,目标角度,延迟/速度)
} else {
switch(serialCmd){
case 'o': // 输出舵机状态信息
reportStatus();
break;
case 'i':
armIniPos();
break;
case 'p':
playDice();
break;
default: //未知指令反馈
Serial.println("Unknown Command.");
}
}
}
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 {
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){
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 +");
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]);
}
}
void playDice(){
Serial.println("+Command: Let's play some dice!");
armIniPos();
int diceMove1[21][3] = {
{'c', 30, DSD},
{'b', 90, DSD},
{'f', 43, DSD},
{'r', 126, DSD},
{'c', 90, DSD},
{'r', 90, DSD},
{'b', 60, DSD},
{'f', 36, DSD},
{'r', 135, DSD},
{'c', 30, DSD},
{'r', 90, DSD},
{'b', 90, DSD},
{'f', 36, DSD},
{'r', 135, DSD},
{'c', 90, DSD},
{'r', 90, DSD},
{'b', 60, DSD},
{'f', 48, DSD},
{'r', 123, DSD},
{'c', 30, DSD},
{'r', 90, DSD},
};
for (int i = 0; i < 21; i++){
servoCmd(diceMove1[i][0], diceMove1[i][1], diceMove1[i][2]);
delay(200);
}
armIniPos();
int diceMove2[21][3]{
{'c', 30, DSD},
{'b', 58, DSD},
{'f', 48, DSD},
{'r', 120, DSD},
{'c', 90, DSD},
{'r', 90, DSD},
{'b', 90, DSD},
{'f', 36, DSD},
{'r', 135, DSD},
{'c', 30, DSD},
{'r', 90, DSD},
{'b', 60, DSD},
{'f', 36, DSD},
{'r', 135, DSD},
{'c', 95, DSD},
{'r', 90, DSD},
{'b', 90, DSD},
{'f', 43, DSD},
{'r', 125, DSD},
{'c', 30, DSD},
{'r', 90, DSD},
};
for (int i = 0; i < 21; i++){
servoCmd(diceMove2[i][0], diceMove2[i][1], diceMove2[i][2]);
delay(200);
}
armIniPos();
}
键盘控制机械臂程序终版(灵活版,不固定位置)
#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;
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(90);
delay(10);
fArm.write(90);
delay(10);
rArm.write(90);
delay(10);
claw.write(90);
delay(10);
Serial.begin(9600);
Serial.println("Welcome to Taichi-Maker Robot Arm Tutorial");
}
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;
}
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.");
}
}
}
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; //read获取角度
ser voCmd('b', baseJoyPos, DSD);
break;
case 'd': // Base向右
Serial.println("Received Command: Base Turn Right");
baseJoyPos = base.read() + moveStep;
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;
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.");
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 {
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){
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 +");
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]);
}
}
HC06蓝牙模块——仅作为一个传输工具,无另外的程序编写
/*
---- 电路连接 ----
HC-06 Arduino Uno R3 引脚
TX 0 (RX)
RX 1 (TX)
VCC +5v
GND GND
LED Arduino Uno R3 引脚
+ 11 (RX)
- GND (通过220欧姆限流电阻)
注意:
1. 须使用分压电路,确保HC-06 RX信号电压为3.3伏特。
2. 须先将此程序上传至ARDUINO后,再将HC-06连接在ARDUINO开发板的串口引脚上。
否则程序将无法正常上传。
*/
int brightness; //LED亮度变量
int serialData; //串口数据变量
void setup() {
Serial.begin(9600);
pinMode(LED_BUILTIN, OUTPUT);
pinMode(11, OUTPUT);
}
void loop(){
if( Serial.available()>0 ){ //如果串口缓存有数据
serialData = Serial.parseInt(); //将串口缓存数值存储到serialData变量
Serial.print("serialData = "); Serial.println(serialData);
if (serialData >=0 && serialData <= 255) {
if (serialData >= brightness){ //逐渐调节LED亮度
for (brightness; brightness <= serialData; brightness++){
analogWrite(11, brightness);
Serial.print("brightness = "); Serial.println(brightness);
delay(5);
}
} else {
for (brightness; brightness >= serialData; brightness--){
analogWrite(11, brightness);
Serial.print("brightness = "); Serial.println(brightness);
delay(5);
}
}
}
}
}
版权归原作者 努力的小羽儿 所有, 如有侵权,请联系我们删除。