基于Arduino的智能泡茶机(2)——代码与解析

前言

注意注意注意,<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源码实在太多了,我就直接放资源了。部分代码
有问题的话,可以评论一下,看到的话我会尽量帮忙解决。

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值