前言
注意注意注意,<Adafruit_PWMServoDriver.h>是第三方库,来自厂家!要编译前请添加第三方库!
以下代码仅为简单分享一些经验,
Arduino Mega板上的代码
Mega板上的头文件
#ifndef PUBLIC_H
#define PUBLIC_H
#include <SPI.h> //the communication interface with the modem
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
/***********************************************************
舵机驱动板驱动定义
***********************************************************/
#define SERVOMIN 140 // 这是“最小”脉冲长度计数(4096)
#define SERVOMAX 650 // 这是“最大”脉冲长度计数(4096)
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0X40);
/***********************************************************
舵机结构体
***********************************************************/
typedef struct Motor_Data
{
int Motor_ID;
int Motor_type;
int Motor_Degree; //记录当前角度
int Motor_Target; //将要执行的目标角度
}Motor_Data_t;
/***********************************************************
舵机数据枚举定义区
***********************************************************/
//舵机类型枚举
enum MOTORTYPE
{
Motortpye_Middle = 1,
Motortpye_Right,
Motortpye_Left,
Motortpye_WaterPump,
Motortpye_TeaKettle
};
//舵机速度枚举
enum MOTORVELOCITY
{
MotorVelocity_Fast = 8,
MotorVelocity_Moderate = 10,
MotorVelocity_Sluggish = 15,
MotorVelocity_Sluggish2 = 20,
};
/***********************************************************
洗杯子指令
***********************************************************/
//舵机整套动作命令枚举
enum CLEAN
{
//左边杯
claen_Left = 1,
//右边杯
claen_Right,
//中间杯
claen_Middle,
//全结束
claen_End,
claen_Middle2,
};
//舵机整套动作命令枚举
enum MAKETEA
{
//洗茶——茶壶移动指定地点,水泵加水
MakeTea_CleanTea = 100,
MakeTea_CleanTea_ret,
MakeTea_CleanTea_PutOut,
MakeTea_CleanTea_PutOut_ret,
MakeTea_AddWater,
MakeTea_AddWater_ret,
MakeTea_AddWater_End,
MakeTea_Refills,
MakeTea_Refills_ret,
MakeTea_CleanTea_PutOut2,
MakeTea_Rest=110,
MakeTea_Rest_ret=111,
};
//舵机整套动作命令枚举
enum ORDER
{
//全自动
order_Full_Automatic = 1,
//泡茶
order_Making_Tea,
//清洗杯子
order_Clean,
//续杯
order_Refills,
//洗茶
order_CleanTea,
//复位
order_Rest,
};
/***********************************************************
系统初始化
* 数据初始化 Init_Data()
* 左手位置初始化 Init_Left()
* 右手位置初始化 Init_Right()
* 中手位置初始化 Init_Middle()
* 水泵机械手初始化 Init_WaterPump()
* 茶壶机械手臂初始化 Init_TeaKettle()
***********************************************************/
void Init_Data(); //数据初始化
void Init_Left();
void Init_Right();
void Init_Middle();
/***********************************************************
舵机底层函数
* 执行指定舵机 Base_MotorRun(int MotorNum,int MotorVelocity = MotorVelocity_Moderate)
* 修改舵机数据 Base_setMotorData(int MotorNum,int MotorDegree)
***********************************************************/
void Base_MotorRun(int MotorNum,int MotorVelocity = MotorVelocity_Moderate);
void Base_setMotorData(int MotorNum,int MotorDegree,int MotorTarget=-1);
/***********************************************************
系统通信解码
* 运行蓝牙 Run_Bluetooth()
* 运行解码 Run_Decode(int code)
***********************************************************/
void Run_Bluetooth(); //运行蓝牙
void Run_Decode(int code); //解码
int Listen(int Object); //返回Object发来的信息,Object为1是水泵,2为茶壶
/***********************************************************
小茶杯运动
***********************************************************/
//手臂收回
void Left_TakeBack(int Velocity = MotorVelocity_Sluggish);
void Right_TakeBack(int Velocity = MotorVelocity_Sluggish);
void Middle_TakeBack(int Velocity = MotorVelocity_Sluggish);
//手臂送出
void Left_SendTo(int Velocity = MotorVelocity_Sluggish2);
void Middle_SendTo(int Velocity = MotorVelocity_Sluggish2);
void Right_SendTo(int Velocity = MotorVelocity_Sluggish2);
//手臂杯口朝上
void Left_Positive(int Velocity = MotorVelocity_Moderate);
void Middle_Positive(int Velocity = MotorVelocity_Moderate);
void Right_Positive(int Velocity = MotorVelocity_Moderate);
//手臂杯口朝下
void Left_Negative(int Velocity = MotorVelocity_Moderate);
void Middle_Negative(int Velocity = MotorVelocity_Moderate);
void Right_Negative(int Velocity = MotorVelocity_Moderate);
//手臂盖子盖上
void Left_Close(int Velocity = MotorVelocity_Moderate);
void Middle_Close(int Velocity = MotorVelocity_Moderate);
void Right_Close(int Velocity = MotorVelocity_Moderate);
//手臂盖子打开
void Left_Open(int Velocity = MotorVelocity_Moderate);
void Middle_Open(int Velocity = MotorVelocity_Moderate);
void Right_Open(int Velocity = MotorVelocity_Moderate);
/***********************************************************
小茶杯分解动作
***********************************************************/
//洗杯子
void Wash_Left_Cup(int flag);
void Wash_Right_Cup(int flag);
void Wash_Middle_Cup(int flag);
//放杯子
void Place_Left_Cup();
void Place_Right_Cup();
void Place_Middle_Cup();
void Place_Cup();
//收回杯子
void TakeBack_Left_Cup();
void TakeBack_Right_Cup();
void TakeBack_Middle_Cup();
//检测IO口
int Test_Left();
int Test_Right();
int Test_Middle();
//洗杯子
void Clean();
//洗茶
void CleanTea(int flag=1);
//泡茶——加水后,复位
void MakeTea();
//续杯
void Refills();
//判断有没有杯子
void judge();
//复位
void rest();
#endif
Mega板上源文件
#include "public1.h"
/******************************************
* 舵机数据区
* ****************************************/
Motor_Data_t MyMotors[9]; //创建9个舵机结构体
int Motor_Velocity; //舵机运行速度
int Making_Tea_Flag=1; //记录第几次泡茶
/******************************************
* 公共变量据区
* ****************************************/
volatile int myData = 0; //蓝牙发来数据保存于此
volatile int WaterPumpData = 0; //水泵执行数据保存于此
volatile int TeaKettleData = 0; //茶壶执行数据保存于此
volatile int LeftFlag = -1; //检查左手是否有茶杯标志位
volatile int MiddleFlag = -1; //检查中手是否有茶杯标志位
volatile int RightFlag = -1; //检查右手是否有茶杯标志位
/******************************************
* arduino基层函数区
* ****************************************/
void setup(){
Serial.begin(9600);
Serial1.begin(9600); //水泵
Serial2.begin(9600); //茶壶
Serial.println("3个串口化完成!");
Init_Data();
Serial.println("数据初始化完成!");
pwm.begin();
pwm.setPWMFreq(60); //模拟伺服系统以60赫兹的频率更新
Serial.println("舵机驱动初始化完成!");
Init_Left();
Init_Right();
Init_Middle();
Serial.println("三只手臂初始化完成!");
//监视IO口初始化
pinMode(11, INPUT);
pinMode(12, INPUT);
pinMode(13, INPUT);
Serial.println("检测模块初始化完成");
}
void loop(){
Run_Bluetooth();
}
/***********************************************************
系统初始化
* 数据初始化 Init_Data()
* 左手位置初始化 Init_Left()
* 右手位置初始化 Init_Right()
* 中手位置初始化 Init_Middle()
* 水泵机械手初始化 Init_WaterPump()
* 茶壶机械手臂初始化 Init_TeaKettle()
***********************************************************/
//数据初始化
void Init_Data(){
//舵机组数据初始化
for(int i = 0;i < 9;i++){
MyMotors[i].Motor_ID=i+1;
MyMotors[i].Motor_Degree = 0;
if( i>=0 || i<=2){
MyMotors[i].Motor_type = Motortpye_Left;
}
else if(i>=3 || i<=5){
MyMotors[i].Motor_type = Motortpye_Right;
}
else if(i>=6 || i<=8){
MyMotors[i].Motor_type = Motortpye_Middle;
}
}
}
//左手位置初始化
void Init_Left(){
Left_TakeBack();
Left_Positive();
Left_Close();
}
//右手位置初始化
void Init_Right(){
Right_TakeBack();
Right_Positive();
Right_Close();
}
//中手位置初始化
void Init_Middle(){
Middle_TakeBack();
Middle_Positive();
Middle_Close();
}
/***********************************************************
舵机底层函数
* 执行指定舵机 Base_MotorRun(int MotorNum,int MotorVelocity = MotorVelocity_Moderate)
* 修改舵机数据 Base_setMotorData(int MotorNum,int MotorDegree)
***********************************************************/
//执行指定舵机
void Base_MotorRun(int MotorNum,int MotorVelocity){
int Variable = 0;
int flag = 0;
int Decode_Motor_Degree;
//做差值,求两角度的差值
if(MyMotors[MotorNum-1].Motor_Target>=0){
Variable = MyMotors[MotorNum-1].Motor_Target - MyMotors[MotorNum-1].Motor_Degree;
}
//判断角度差是正值还是负值,并且设立标志位
if(Variable>=0){
flag = 1;
}
else{
flag = -1;
}
//控制舵机运动
for (int i = 1; i <= Variable*flag; i++) {
Decode_Motor_Degree = map((MyMotors[MotorNum-1].Motor_Degree+i*flag),0,180,140,600);
pwm.setPWM(MotorNum-1, 0, Decode_Motor_Degree);
delay(MotorVelocity);
}
Base_setMotorData(MotorNum,MyMotors[MotorNum-1].Motor_Target);
}
//修改舵机数据
void Base_setMotorData(int MotorNum,int MotorDegree,int MotorTarget=-1){
MyMotors[MotorNum-1].Motor_Degree = MotorDegree;
MyMotors[MotorNum-1].Motor_Target = MotorTarget;
}
//运行解码
void Run_Decode(int code){
int Order_Number = 0;
int Order_Degree = 0;
int i=0;
//信息提示
Serial.println("执行了函数Decode");
Serial.print("蓝牙发来的数据为:");
Serial.println(code);
//解析指令序号、指定度数
Order_Number = code/1000;
Order_Degree = code%1000;
//20为动作指令
if(Order_Number==20){
switch (Order_Degree) {
case order_Full_Automatic: //1
Serial.println("全自动");
CleanTea(2);
MakeTea();
Clean();
Refills();
while(i<4){
judge();
Place_Cup();
MakeTea();
delay(10000*i);
Refills();
i++;
}
break;
case order_Making_Tea: //2
Serial.println("泡茶");
MakeTea();
i++;
break;
case order_Clean: //3
Serial.println("清洗杯子");
Clean();
break;
case order_Refills: //4
Serial.println("倒茶");
Refills();
break;
case order_CleanTea: //5
Serial.println("洗茶");
CleanTea();
break;
case order_Rest: //复位 6
Serial.println("复位");
rest();
break;
default:
break;
}
}
else if(Order_Number>=10&&Order_Number<=13){
Serial1.println(code); //水泵舵机
}
else if(Order_Number>=14&&Order_Number<=17){
Serial2.println(code); //茶壶舵机
}
else{
Base_setMotorData(Order_Number,MyMotors[Order_Number-1].Motor_Degree,Order_Degree);
Base_MotorRun(Order_Number);
}
}
//监听Uno板函数
int Listen(int Object){
int ObjectData=-1;
if(Object==1){
while (1) {
while (Serial1.available() > 0) {
//字符转整数
ObjectData = String(Serial1.readString()).toInt();
return ObjectData;
}
}
}
else if(Object==2){
while (1) {
while (Serial2.available() > 0) {
//字符转整数
ObjectData = String(Serial2.readString()).toInt();
return ObjectData;
}
}
}
else{
Serial.println("监听对象有错");
return 0;
}
}
/***********************************************************
小茶杯运动
***********************************************************/
//手臂收回
void Left_TakeBack(int Velocity){
Base_setMotorData(1,MyMotors[0].Motor_Degree,10);
Base_MotorRun(1,6);
}
void Right_TakeBack(int Velocity){
Base_setMotorData(4,MyMotors[3].Motor_Degree,179);
Base_MotorRun(4,6);
}
void Middle_TakeBack(int Velocity){
Base_setMotorData(7,MyMotors[6].Motor_Degree,165);
Base_MotorRun(7,6);
}
//手臂送出
void Left_SendTo(int Velocity){
Base_setMotorData(1,MyMotors[0].Motor_Degree,179);
Base_MotorRun(1,Velocity);
}
void Right_SendTo(int Velocity){
Base_setMotorData(4,MyMotors[3].Motor_Degree,0);
Base_MotorRun(4,Velocity);
}
void Middle_SendTo(int Velocity){
Base_setMotorData(7,MyMotors[6].Motor_Degree,1);
Base_MotorRun(7,Velocity);
}
//手臂杯口朝上
void Left_Positive(int Velocity){
Base_setMotorData(2,MyMotors[1].Motor_Degree,5);
Base_MotorRun(2,Velocity);
}
void Right_Positive(int Velocity){
Base_setMotorData(5,MyMotors[4].Motor_Degree,10);
Base_MotorRun(5,Velocity);
}
void Middle_Positive(int Velocity){
Base_setMotorData(8,MyMotors[7].Motor_Degree,10);
Base_MotorRun(8,Velocity);
}
//手臂杯口朝下
void Left_Negative(int Velocity){
Base_setMotorData(2,MyMotors[1].Motor_Degree,179);
Base_MotorRun(2,Velocity);
}
void Right_Negative(int Velocity){
Base_setMotorData(5,MyMotors[4].Motor_Degree,179);
Base_MotorRun(5,Velocity);
}
void Middle_Negative(int Velocity){
Base_setMotorData(8,MyMotors[7].Motor_Degree,179);
Base_MotorRun(8,Velocity);
}
//手臂盖子盖上
void Left_Close(int Velocity){
Base_setMotorData(3,MyMotors[2].Motor_Degree,3);
Base_MotorRun(3,Velocity);
}
void Right_Close(int Velocity){
Base_setMotorData(6,MyMotors[5].Motor_Degree,10);
Base_MotorRun(6,Velocity);
}
void Middle_Close(int Velocity){
Base_setMotorData(9,MyMotors[8].Motor_Degree,5);
Base_MotorRun(9,Velocity);
}
//手臂盖子打开
void Left_Open(int Velocity){
Base_setMotorData(3,MyMotors[2].Motor_Degree,107);
Base_MotorRun(3,Velocity);
}
void Right_Open(int Velocity){
Base_setMotorData(6,MyMotors[5].Motor_Degree,127);
Base_MotorRun(6,Velocity);
}
void Middle_Open(int Velocity){
Base_setMotorData(9,MyMotors[8].Motor_Degree,125);
Base_MotorRun(9,Velocity);
}
/***********************************************************
小茶杯分解动作
***********************************************************/
//洗杯子——输入1、2、3,其中1、3是杯口朝上,2是朝下
void Wash_Left_Cup(int flag){
switch (flag) {
case 1:
Left_Positive();
break;
case 2:
Left_Negative();
break;
default:
Left_Positive();
break;
}
}
emmmm源码实在太多了,我就直接放资源了。部分代码
有问题的话,可以评论一下,看到的话我会尽量帮忙解决。