机器人制作开源方案 | 校园餐具回收分类机器人

作者:梁桥、吴振宇、凌福海、李清轩、姜晓敏

单位:华北科技学院

指导老师:韩红利、张伟杰

1. 场景调研

1.1 项目实施目的

      受新冠病毒引起的影响,人们生产生活发生了巨大的改变。现处于疫情防控常态化阶段,为应对点状爆发,减少人员接触。目前在学校大型食堂都有专门的餐盘回收处,并有专门的负责人将人们用过的餐盘进行回收,工作人员需将不同餐具中的剩饭剩菜倒入泔水桶,还要把用过的餐盘餐具送至洗碗间进行统一清洗,这一过程费时费人费力,在学生用餐高峰期人工回收餐盘效率低下,并且随着人口减少,相关工作人员难以招聘,出现用工缺口。实地调研情况,如下图所示:

机器人制作开源方案 | 校园餐具回收分类机器人_第1张图片 实地调研

      目前市面上所能见到的餐具回收机器人如下图所示,都是以半自动化半人工的运作方式为主,简单来说就是需要客户将待回收的餐具放入到机器人指定的回收箱内,机器人主要起到一个运输的功能。而我们所设计的产品完全自动化,从夹取餐具到倾倒残余再到后续的分拣都是完全自动化,减轻人工劳动强度。针对上述存在的问题,本发明提供了一种基于人工智能的餐具回收机器人系统,提高回收餐盘效率。

机器人制作开源方案 | 校园餐具回收分类机器人_第2张图片 现有餐具回收机器人

1.2 项目实施意义

我国是人口大国,餐具回收机的开发和生产起步较晚,直至90年代初才逐渐发展起来,目前共有20余家厂家生产此类产品。餐厅自动回收车的出现,缓解了人们在工作时因时间少而产生的就餐问题。因此餐厅自动回收车在我国也有着飞速的发展,但国内的普及率尚不高,尚属超前消费产品,具有非常广泛的应用前景。过去几年的市场调研数据显示,用户比较顾虑洗碗机的效率、分类能力、回收能力、耗电量及操作是否方便等。因此开发出具有高效率、节电、操作方便餐具自动回收车是有巨大市场的。

2. 机器人本体设计

2.1 总体结构

      该餐具回收分类机器人由两部分组成,第一部分由小车携带的机械臂为主体的餐具回收分类,第二部分为固定夹取装置,装卸车上的回收箱进行二次回收分类,双机协同完成复杂工作。车身本体搭载两块arduino开发板,装卸机械臂有一块开发板控制。工作系统还配备拓展板、电源等控制舵机电机的转向以及电机转向的时间,引用专用传感器,使用软件建立三维模型,优化设计尺寸和形状,针对不同功能,采用不同传感器及系统对信号进行检测,从原始信号中提取参数,实现反馈信号的定量预测。通过灰度传感器和避障模块进行移动和工作,如下图所示:

机器人制作开源方案 | 校园餐具回收分类机器人_第3张图片 整体结构

2.2 机械结构

(1)底盘采用四轮驱动,通过杆件和板块进行底盘制作。运动灵活敏捷,在校园餐厅内可进行基本的运动。平稳整齐的底盘可装载箱体或者发放结构,拆卸方便,利于维护修理,方便后期进行二次改造,如下图所示:

机器人制作开源方案 | 校园餐具回收分类机器人_第4张图片 底盘结构

2)机械手夹爪:机械夹爪的加减速可控,对工件的冲击可以减至最小,并且可以实现力的闭环控制,夹持力的精度可以到0.01N、测量精度可以到0.005mm,可以精确控制夹取餐具,如下图所示:

机器人制作开源方案 | 校园餐具回收分类机器人_第5张图片 机械爪结构

3)装卸机械臂:四轴机械手臂可以在几何平面内进行自由移动,具有较强的刚性,拥有四个轴,关节全部由电机来进行驱动,这四个关节是三个轴线相互平行的旋转关节和一个移动关节,允许机械手臂在平面内进行定位和定向以及未端执行器完成垂直于平面的直线运动,如下图所示:

机器人制作开源方案 | 校园餐具回收分类机器人_第6张图片 装卸机械臂结构

2.3 电路控制与设备调试

      该机器人有两部分协同作业,由餐具回收运输系统与回收箱装卸系统组成,通过传感器的信号识别与Basra主控板的数据处理进行单机器与双机系统的协同作业。

(1)餐具回收运输系统

      餐具回收运输部分由两块Basra主控板控制,第一块Basra主控板控制其四轮运输底盘的运动、循迹与识别系统、指示灯系统;第二块Basra主控板控制回收分类机械臂进行回收作业与显示屏上的工作状态提示词。

第一块Basra主控板通过对四个灰度传感器与识别系统集合的方式配合,对线路的识别和运动状态进行精准把控,配合显示屏与指示灯实现自主避障、到达目标位置精准启停与循迹与提示功能。当感知到周围没障碍物也没有停车指令时,指示灯绿色、小车循迹;当餐具回收运输车上的近红外与白标传感器被触发时停止前进、指示灯红色、显示屏提示工作状态、回收分类机械臂的传感器触发进行回收作业,停止指令全过程中共触发两次(餐具回收点、回收箱装卸点)。

(2)回收箱装卸系统

 回收箱装卸部分由一块Basra主控板控制,其包含感应模块、装卸机械臂、指示灯。其电路控制流程为:当Basra主控板通过距离传感器感应到餐具回收运输车到达停车点时触发装卸命令,指示灯红色提示请勿靠近、装卸机械臂开始装卸回收箱,完成共工作后回到初始位置、指示灯绿色。如下图所示:

机器人制作开源方案 | 校园餐具回收分类机器人_第7张图片 回收站 

3. 作品创新点

      本作品与市面上已有的大多数同类型餐具回收分类机器人机器人相比,本产品的生产消耗和运营成本相对较低,单次运输的容量相对较大,单次使用价格相对低廉,可满足公司、学校和工厂等大型餐厅的需求以及预算。

3.1 双机协同作业

      回收运输机器人到达装卸机器人前方时停止,同时触发装卸机器人的装卸工作指令,两机配合分别实现餐具回收运输与回收箱的装卸。双机协同简化了小车机械臂工作的复杂程度;装卸机械臂使整体形成了一个闭环系统,并且使回收过程的灵活性最大化,可高质量的完成可重复流程;编程方便,对于普通操作者和非技术背景人员都可对其进行调试,将人与机器人的各自优势发挥到极致,让机器人更好的工作,能够适应更广泛的工作场景。双机的三维模型如下图所示:

机器人制作开源方案 | 校园餐具回收分类机器人_第8张图片 双机三维模型

3.2 多种传感器联合应用

      由于近红外传感器的只能对距离情况做简单的判别,局限性较大,并且传感器高度位置的差异可能会对其检测造成干扰等问题。为了提高识别的准确度降低环境因素的干扰,我们采取了多传感器联合识别的方法规避环境影响,如下图所示,只有当相关传感器同时被触发时才能激活机器人的相应运动指令,例如在距离和白标传感器被激活时小车停止前进。

机器人制作开源方案 | 校园餐具回收分类机器人_第9张图片 传感器

3.3 抓取结构的改进

      由于初始抓取结构无法进行碗盘抓取,我们通过后续增加限位的方式使得餐具与机械爪贴合更加良好、稳固,可以在倾倒剩菜过程中确保碗盘不会掉落。在此设计灵感的基础上衍生出了我们装卸机械臂上的抓取机构,通过爪子长度的延伸和卡扣结构实现了牢固抓取。抓取结构演变过程如下图所示:

机器人制作开源方案 | 校园餐具回收分类机器人_第10张图片 抓取结构演变过程

3.4 回收箱结构可变

      一体多箱(一个箱子分隔成多个存放区域)或多体多箱(多个小箱体相互分离)的可变结构,可根据不同的餐具的分类及残渣回收的需求和应用场景进行结构的调整,可适应性较强,同时避免了回收时人与餐具的非必要接触,便于后续的回收。

注:演示视频中展示的为一体双箱结构,分为餐具箱和残渣箱。

3.5 PWM调速

      PWM调速系统主电路线路简单,需用的功率器件少,电流容易连续,谐波少,电机损耗及发热都较小。若与快速响应的电动机配合,则系统频带宽,动态响应快,动态抗扰能力强;功率开关器件工作在开关状态,导通损耗小,当开关频率适当的时候,开关损耗也不大,因而装置效率较高;直流电源采用不控整流时,电网功率因数比相控整流器高。

4. 难点及解决方案

4.1精准启停问题

      餐具回收分类机器人如果无法准确的识别和运行到指定的位置,会难以将回收箱精确放置于指定地点。

      现阶段我们通过控制代码优化、机械结构改进、传感器种类和位置来实现较高精准度的启停,将延迟尽可能降低。由于所用开发板以及开发套件的限制等一些不可抗拒的外部因素导致,一些设计思路无法落实,设计团队后期也在寻找更为合适精确的方案。

4.2 抓取与装卸问题

      由于回收箱箱体过长导致普通机械爪难以牢固的抓取,我们采用了加长机械爪与卡扣结构,通过机械结构的改进,使嗯机械爪可以与回收箱密切贴合、牢固抓取;

      由于所抓取的物品形状特殊且表面光滑,普通机械爪难以稳固抓取,我们为其加装了上下限位,使得可以牢固的碗盘,可以在倾倒饭菜的过程中不会是碗盘脱落从而造成损失。为了抓取铁质餐具我们还为其加装电磁铁,从而实现碗盘和铁质餐具的分类,由于受疫情影响,团队没有机会开发出更多的抓取结构实现更加丰富的分类。

4.3 双机协同的准确运行

      双机协同的设计开发难度较大,但是可以在具体的工作环境中发挥其优势,双机协同大大提高了运行效率、极大的降低了人工劳动强度,而且双击协同。后期的使用难度较低,更加方便工作人员的使用。对于双机协同我们只用了多主控板控制减少了每块儿主控板上所需处理的数据数量,提高了其运行的效率,确保了其运行的准确性。

4.4 餐具的精确分类

      在分类方面,我们实现了碗、盘、勺子的分类为了实现准确的分类我们根据不行不同的舵机返回数值判断餐具的种类,放入回收箱不同的位置。但尚未解决的是如何实现非金属筷子的回收,团队将致力于通过机械结构的改进来实现。

5. 前景展望

      由于现有开发板的功能受限,暂时无法实现视觉识别餐具位置,后续我们将对机器的开发板进行优化,增加机器人视觉识别功能,使机器人更加智能化。我们还将为机器人添加语言提示和远程监测功能,突发情况也可以及时解决。

      除了应用在校园内外,还可以通过小车的二次开发应用在公司,餐厅等公共区域。通过小车的二次开发,能够使小车在公共区域的运动更加智能高效。

6. 示例程序

① 车载机械臂代码

/*车载机械臂代码*/

#include    //显示屏库函数

#include     //舵机库

U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, SCL, SDA);

Servo servo_3;   /*3号舵机*/

Servo servo_4;   /*4号舵机*/

Servo servo_7;   /*7号舵机*/

Servo servo_8;   /*8号舵机*/

Servo servo_11;   /*11号舵机*/

Servo servo_12;   /*12号舵机*/

void panduan();

void red();               /*指示灯红灯*/

void green();             /*指示灯绿灯*/

void red_green();         /*指示灯闪烁*/

void off();               /*指示灯熄灭*/

void panduanzhonglei();   /*根据舵机读取的参数判断夹取餐具的种类(盘、碗)并放置到指定位置*/

void xunzhao();           /*吸附轻质铁质勺子 放入指定位*/

void zhuaqu();            /*机械臂抓取过程*/

void stop();              /*舵机初始位置*/

void face();              /*显示屏显示函数*/

void letter(int a);

int a;

void setup() {

  Serial.begin(9600);

  u8g2.begin();        //启动u8g2驱动程序

  u8g2.clearBuffer();   //清空显示屏缓存

  servo_3.attach(3);

  servo_4.attach(4);

  servo_7.attach(7);

  servo_8.attach(8);

  servo_11.attach(11);

  servo_12.attach(12);

  servo_3.write(160);

  servo_4.write(10);

  servo_7.write(20);

  servo_8.write(30);

  servo_11.write(5);

  servo_12.write(70);

  pinMode(A0, OUTPUT);

  pinMode(A1, OUTPUT);

  pinMode(A2, INPUT);

  pinMode(A3, OUTPUT);

  pinMode(A4, OUTPUT);

}

    /*主程序*/

void loop() {

  Serial.println(digitalRead(A2));

  /*定义串口*/

  servo_3.write(160);

  delay(15);

  servo_4.write(10);

  delay(15);

  servo_7.write(20);

  delay(15);

  servo_8.write(10);

  delay(15);

  servo_11.write(5);

  delay(15);

  servo_12.write(70);

  delay(15);

  /*运动状态*/

  if (digitalRead(A2)) {

    green();

    face();   //调用函数,显示图案

  } else {

    red();

    letter(a);   //调用函数,显示中文和变量

    zhuaqu();

    green();

    face();   //调用函数,显示图案

    delay(5000);

  }

}

/*舵机初始位置*/

void stop() {

  red_green();

  servo_3.write(160);

  delay(15);

  servo_4.write(10);

  delay(15);

  servo_7.write(20);

  delay(15);

  servo_8.write(30);

  delay(15);

  servo_11.write(5);

  delay(15);

  servo_12.write(70);

}

/*指示灯绿灯*/

void green() {

  digitalWrite(A0, HIGH);

  digitalWrite(A1, LOW);

}

/*指示灯熄灭*/

void off() {

  digitalWrite(A0, LOW);

  digitalWrite(A1, LOW);

}

/*指示灯红灯*/

void red() {

  digitalWrite(A0, LOW);

  digitalWrite(A1, HIGH);

}

/*指示灯闪烁*/

void red_green() {

  red();

  delay(200);

  off();

  delay(20);

  green();

  delay(200);

  off();

  delay(20);

}

/*根据舵机读取的参数判断夹取餐具的种类(盘、碗)并放置到指定位置*/

void panduanzhonglei() {

  int x = servo_12.read();

  if (80 < x < 100) {                          //盘子

    for (int i = 30; i <= 50; i = i + (+1)) {   //到达剩饭桶

      servo_3.write(i);

      delay(30);

    }

    for (int i = 30; i >= 20; i = i + (-1)) {

      servo_4.write(i);

      delay(30);

    }

    for (int i = 20; i >= 10; i = i + (-1)) {

      servo_8.write(i);

      delay(30);

    }

    for (int i = 10; i >= 5; i = i + (-1)) {

      servo_8.write(i);

      delay(30);

    }

    for (int i = 5; i <= 100; i = i + (1)) {   //倒剩饭

      servo_11.write(i);

      delay(20);

    }

    for (int i = 100; i >= 5; i = i + (-1)) {

      servo_11.write(i);

      delay(20);

    }

    for (int i = 50; i <= 80; i = i + (+1)) {

      servo_3.write(i);

      delay(30);

    }

    for (int i = 50; i <= 105; i = i + (1)) {   //爪子张开

      servo_12.write(i);

      delay(30);

    }

    for (int i = 105; i >= 50; i = i + (-1)) {   //爪子闭合

      servo_12.write(i);

      delay(30);

    }

    for (int i = 5; i <= 10; i = i + (1)) {

      servo_8.write(i);

      delay(30);

    }

    for (int i = 80; i <= 130; i = i + (1)) {

      servo_3.write(i);

      delay(30);

    }

    digitalWrite(A3, LOW);   //放勺子

    digitalWrite(A4, LOW);

    delay(300);

    for (int i = 130; i <= 160; i = i + (1)) {

      servo_3.write(i);

      delay(30);

    }

    for (int i = 20; i >= 10; i = i + (-1)) {

      servo_4.write(i);

      delay(30);

    }

  } else {                                     //碗

    for (int i = 30; i <= 50; i = i + (+1)) {   //到达剩饭桶

      servo_3.write(i);

      delay(30);

    }

    for (int i = 30; i >= 20; i = i + (-1)) {

      servo_4.write(i);

      delay(30);

    }

    for (int i = 20; i >= 10; i = i + (-1)) {

      servo_8.write(i);

      delay(30);

    }

    for (int i = 10; i >= 5; i = i + (-1)) {

      servo_8.write(i);

      delay(30);

    }

    for (int i = 5; i <= 100; i = i + (1)) {   //倒剩饭

      servo_11.write(i);

      delay(20);

    }

    for (int i = 100; i >= 5; i = i + (-1)) {

      servo_11.write(i);

      delay(20);

    }

    for (int i = 50; i <= 110; i = i + (+1)) {

      servo_3.write(i);

      delay(30);

    }

    for (int i = 50; i <= 105; i = i + (1)) {   //爪子张开

      servo_12.write(i);

      delay(30);

    }

    for (int i = 105; i >= 50; i = i + (-1)) {   //爪子闭合

      servo_12.write(i);

      delay(30);

    }

    for (int i = 5; i <= 10; i = i + (1)) {

      servo_8.write(i);

      delay(30);

    }

    for (int i = 110; i <= 130; i = i + (1)) {

      servo_3.write(i);

      delay(30);

    }

    digitalWrite(A3, LOW);   //放勺子

    digitalWrite(A4, LOW);

    delay(300);

    for (int i = 130; i <= 160; i = i + (1)) {

      servo_3.write(i);

      delay(30);

    }

    for (int i = 20; i >= 10; i = i + (-1)) {

      servo_4.write(i);

      delay(30);

    }

  }

}

/*吸附轻质铁质勺子 放入指定位*/

void xunzhao() {

  digitalWrite(A3, LOW);   //电磁铁通电

  digitalWrite(A4, HIGH);

  for (int i = 30; i <= 60; i = i + (1)) {   //寻找勺子

    servo_3.write(i);

    delay(60);

  }

  for (int i = 60; i >= 30; i = i + (-1)) {

    servo_3.write(i);

    delay(60);

  }

  for (int i = 30; i <= 40; i = i + (1)) {   //寻找

    servo_3.write(i);

    delay(60);

  }

}

/*机械臂抓取过程*/

void zhuaqu() {

  for (int i = 160; i >= 30; i = i + (-1)) {   //转向

    servo_3.write(i);

    delay(20);

  }

  for (int i = 10; i <= 30; i = i + (1)) {   //前倾

    servo_4.write(i);

    delay(30);

  }

  for (int i = 10; i <= 20; i = i + (1)) {   //下降

    servo_8.write(i);

    delay(30);

  }

  xunzhao();

  for (int i = 50; i <= 115; i = i + (1)) {   //爪子张开

    servo_12.write(i);

    delay(30);

  }

  for (int i = 30; i <= 40; i = i + (1)) {   //前倾

    servo_4.write(i);

    delay(60);

  }

  for (int i = 115; i >= 50; i = i + (-1)) {   //爪子闭合

    servo_12.write(i);

    delay(30);

  }

  for (int i = 40; i >= 30; i = i + (-1)) {   //前倾

    servo_4.write(i);

    delay(60);

  }

  panduanzhonglei();   //引用判断餐具种类

}

/*显示屏显示函数*/

void face() {

  u8g2.clearBuffer();   //清空显示屏缓存

  u8g2.drawCircle(56, 40, 8, U8G2_DRAW_LOWER_LEFT);   

  u8g2.drawCircle(56, 40, 8, U8G2_DRAW_LOWER_RIGHT);  

  u8g2.drawCircle(72, 40, 8, U8G2_DRAW_LOWER_LEFT);   

  u8g2.drawCircle(72, 40, 8, U8G2_DRAW_LOWER_RIGHT);  

  u8g2.drawCircle(56, 41, 8, U8G2_DRAW_LOWER_LEFT);   

  u8g2.drawCircle(56, 41, 8, U8G2_DRAW_LOWER_RIGHT);  

  u8g2.drawCircle(72, 41, 8, U8G2_DRAW_LOWER_LEFT);   

  u8g2.drawCircle(72, 41, 8, U8G2_DRAW_LOWER_RIGHT);  

  u8g2.drawLine(40, 18, 20, 30);                     

  u8g2.drawLine(88, 18, 108, 30);                     

  u8g2.drawLine(40, 17, 20, 29);                     

  u8g2.drawLine(88, 17, 108, 29);                     

  u8g2.sendBuffer();   //加载以上内容

}

void letter(int a) {

  u8g2.clearBuffer();   //清空显示屏缓存

  //int8_t a=u8g2.getMaxCharHeight();                      //获取最大高度

  //int8_t b=u8g2.getMaxCharWidth();                       //获取最大宽度

  u8g2.setFont(u8g2_font_unifont_t_chinese2);   //设置字体

  u8g2.drawUTF8(10, 20, "工作中请注意");       //显示文字,左下角位置坐标为(10,34)

  u8g2.drawUTF8(20, 40, "谢谢配合");

  u8g2.sendBuffer();   // 加载以上内容

}

② 运动底盘代码

/*运动底盘代码控制机器人的行走*/

/**/

void bizhang();   /*避障*/

void xunji();    /*寻线*/

void stop();     /*停止*/

void turnR();    /*右转*/

void turnL();    /*左转*/

void runback();   /*后退*/

void runfoward();/*前进*/

void redlight(); /*红灯*/

void green();    /*绿灯*/

void red_green();/*闪烁*/

void off();      /*熄灯*/

void jingbao();   /*蜂鸣警报*/

int tonePin = 7; /* 蜂鸣器的pin */

void setup() {

  //电机驱动

  pinMode(9, OUTPUT);

  pinMode(10, OUTPUT);

  pinMode(5, OUTPUT);

  pinMode(6, OUTPUT);

  //蜂鸣器

  pinMode(7, OUTPUT);

  pinMode(2, INPUT);

  //传感器

  pinMode(A0, INPUT);

  pinMode(A1, INPUT);

  pinMode(A3, INPUT);

  pinMode(A4, INPUT);

  pinMode(A5, INPUT);

  pinMode(A2, INPUT);

  //信号灯

  pinMode(3, OUTPUT);

  pinMode(4, OUTPUT);

  pinMode(11, OUTPUT);

  pinMode(12, OUTPUT);

  Serial.begin(9600);

}

/*主函数通过判断控制小车底盘运动*/

void loop() {

  Serial.print(digitalRead(2));

  Serial.println(digitalRead(8));

  if (!(digitalRead(A2))) {

    red();

    stop();

    delay(200);

    bizhang();

  }

  if (digitalRead(8)==0&& digitalRead(2)==0) {

    red();

    stop();

    delay(30000);

    runfoward();

    delay(1800);

  } else {

    green();

    xunji();

  }

}

/*蜂鸣警报*/

void jingbao() {

  for (int i = 200; i <= 1000; i += 100) {   //警报声

    tone(7, i);

    delay(10);

  }

  for (int i = 1000; i >= 200; i -= 100) {   //警报声

    tone(7, i);

    delay(10);

  }

}

/*前进*/

void runfoward()   //前进

{

  analogWrite(5, 150);

  analogWrite(6, 0);

  analogWrite(9, 80);

  analogWrite(10, 0);

}

/*后退*/

void runback()   //后退

{

  analogWrite(5, 0);

  analogWrite(6, 160);

  analogWrite(9, 0);

  analogWrite(10, 160);

}

/*左转*/

void turnL()   //

{

  analogWrite(5, 180);

  analogWrite(6, 0);

  analogWrite(9, 0);

  analogWrite(10, 80);

  /*digitalWrite(5,LOW);

   digitalWrite(6,LOW);

   digitalWrite(3,LOW);

   digitalWrite(4,HIGH); */

}

/*右转*/

void turnR()   //

{

  analogWrite(5, 0);

  analogWrite(6, 150);

  analogWrite(9, 180);

  analogWrite(10, 0);

  /*digitalWrite(5,LOW);

    digitalWrite(6,HIGH);

    digitalWrite(3,LOW);

    digitalWrite(4,LOW);*/

}

/*停止*/

void stop()   //停止

{

  red();

  analogWrite(5, 0);

  analogWrite(6, 0);

  analogWrite(9, 0);

  analogWrite(10, 0);

  /*digitalWrite(5,LOW);

    digitalWrite(6,LOW);

    digitalWrite(3,LOW);

    digitalWrite(4,LOW);*/

}

void bizhang() {

  stop();

  delay(2000);

}

/*绿灯*/

void green() {

  digitalWrite(3, HIGH);

  digitalWrite(12, LOW);

  digitalWrite(4, HIGH);

  digitalWrite(11, LOW);

}

/*熄灯*/

void off() {

  digitalWrite(3, LOW);

  digitalWrite(12, LOW);

  digitalWrite(4, LOW);

  digitalWrite(11, LOW);

}

/*红灯*/

void red() {

  digitalWrite(3, LOW);

  digitalWrite(12, HIGH);

  digitalWrite(4, LOW);

  digitalWrite(11, HIGH);

}

/*闪灯*/

void red_green() {

  red();

  delay(200);

  off();

  delay(20);

  green();

  delay(200);

  off();

  delay(20);

}

/*循迹函数   循迹配合提示灯与蜂鸣警报*/

void xunji() {

  int num1, num2, num3, num4, num5;

  num1 = digitalRead(A0);

  num2 = digitalRead(A1);

  num3 = digitalRead(A3);

  num4 = digitalRead(A4);

  num5 = digitalRead(4);

  /*打印信息*/

  /* Serial.print(num1);

  Serial.print(num2);

  Serial.print(num3);

  Serial.print(num4);

  Serial.println(num5);*/

  green();

  if (num1 == 1 && num2 == 1 && num3 == 1 && num4 == 1) {

    runfoward();

    delay(5);

  } else if (num1 == 1 && num2 == 0 && num3 == 1 && num4 == 1) {

    turnL();

    delay(200);

  } else if (num1 == 1 && num2 == 1 && num3 == 0 && num4 == 1) {

    turnR();

    delay(200);

  } else if (num1 == 0 && num2 == 0 && num3 == 0 && num4 == 0) {

    stop();

  }

}

③ 装卸机械臂代码

/*装卸机械臂代码*/

/**/

#include 

#include 

U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, SCL, SDA);

Servo servo_3; /*3号舵机*/

Servo servo_4; /*4号舵机*/

Servo servo_7;/*7号舵机*/

Servo servo_8;/*8号舵机*/

void zhuangxie();   /*装卸回收箱*/

void red();        /*红灯*/

void green();      /*绿灯*/

void red_green();   /*闪烁*/

void off();        /*熄灭*/

void chushiwei();   /*初始位*/

void face();       /*提示屏显示*/

void setup() {

  /*舵机接口*/

  servo_3.attach(3);

  servo_4.attach(4);

  servo_7.attach(7);

  servo_8.attach(11);

  u8g2.begin();        //启动u8g2驱动程序

  u8g2.clearBuffer();   //清空显示屏缓存

  pinMode(A0, INPUT);

  pinMode(12, OUTPUT);

  pinMode(8, OUTPUT);

  chushiwei();

 

  Serial.begin(9600);//打开串口

}

/*主函数   当识别到回收机器人运动到前方停止时进行抓取并更改显示屏状态、指示灯转换*/

void loop() {

  Serial.println(digitalRead(A0));

  chushiwei();

  /*没识别到*/

  if (digitalRead(A0)) {

    green();

    face();

  } else {//识别到

    red();

    zhuangxie();

    green();

    delay(10000);

  }

}

/*初始位函数 机械臂回到初始位*/

void chushiwei() {

  servo_3.write(20);

  delay(15);

  servo_4.write(90);

  delay(15);

  servo_7.write(130);

  delay(15);

  servo_8.write(85);

  delay(15);

}

/*显示屏显示工作状态*/

void face() {

  u8g2.clearBuffer();   //清空显示屏缓存

  u8g2.drawCircle(56, 40, 8, U8G2_DRAW_LOWER_LEFT);  

  u8g2.drawCircle(56, 40, 8, U8G2_DRAW_LOWER_RIGHT);

  u8g2.drawCircle(72, 40, 8, U8G2_DRAW_LOWER_LEFT);   

  u8g2.drawCircle(72, 40, 8, U8G2_DRAW_LOWER_RIGHT);  

  u8g2.drawCircle(56, 41, 8, U8G2_DRAW_LOWER_LEFT);   

  u8g2.drawCircle(56, 41, 8, U8G2_DRAW_LOWER_RIGHT);  

  u8g2.drawCircle(72, 41, 8, U8G2_DRAW_LOWER_LEFT);   

  u8g2.drawCircle(72, 41, 8, U8G2_DRAW_LOWER_RIGHT);

  u8g2.drawLine(40, 18, 20, 30);                     

  u8g2.drawLine(88, 18, 108, 30);                   

  u8g2.drawLine(40, 17, 20, 29);                   

  u8g2.drawLine(88, 17, 108, 29);                   

  u8g2.sendBuffer();   //加载以上内容

}

/*装卸机械臂装卸过程*/

void zhuangxie() {

  for (int i = 20; i <= 85; i++) {   //右转

    servo_3.write(i);

    delay(25);

  }

  for (int i = 85; i >= 65; i--) {   //爪子张开

    servo_8.write(i);

    delay(25);

  }

  for (int i = 90; i <= 120; i++) {   //前倾

    servo_4.write(i);

    delay(25);

  }

  for (int i = 130; i >= 120; i--) {   //下降

    servo_7.write(i);

    delay(25);

  }

  for (int i = 65; i <= 85; i++) {   //爪子闭合

    servo_8.write(i);

    delay(25);

  }

  for (int i = 120; i <= 80; i--) {   //抬升

    servo_7.write(i);

    delay(25);

  }

  for (int i = 120; i >= 110; i--) {   //抬升

    servo_4.write(i);

    delay(40);

  }

  for (int i = 120; i >= 110; i--) {   //下降

    servo_7.write(i);

    delay(40);

  }

  for (int i = 85; i >= 15; i--) {   //右转

    servo_3.write(i);

    delay(25);

  }

  for (int i = 110; i <= 130; i++) {   //下降

    servo_4.write(i);

    delay(25);

  }

  for (int i = 85; i >= 65; i--) {   //爪子张开

    servo_8.write(i);

    delay(25);

  }

  for (int i = 130; i >= 110; i--) {   //上升回正

    servo_4.write(i);

    delay(25);

  }

  for (int i = 65; i <= 85; i++) {   //爪子闭合

    servo_8.write(i);

    delay(25);

  }

  for (int i = 20; i <= 150; i++) {   //回正

    servo_3.write(i);

    delay(25);

  }

  for (int i = 85; i >= 65; i--) {   //爪子张开

    servo_8.write(i);

    delay(25);

  }

  for (int i = 110; i <= 130; i++) {   //下降

    servo_4.write(i);

    delay(25);

  }

  for (int i = 65; i <= 85; i++) {   //爪子闭合

    servo_8.write(i);

    delay(25);

  }

  for (int i = 130; i >= 80; i--) {   //上升回正

    servo_4.write(i);

    delay(25);

  }

  for (int i = 150; i >= 85; i--) {   //回正

    servo_3.write(i);

    delay(40);

  }

  for (int i = 80; i <= 130; i++) {   //下降

    servo_4.write(i);

    delay(40);

  }

  for (int i = 85; i >= 65; i--) {   //爪子张开

    servo_8.write(i);

    delay(40);

  }

  for (int i = 130; i >= 80; i--) {   //上升回正

    servo_4.write(i);

    delay(40);

  }

  for (int i = 65; i <= 85; i++) {   //爪子闭合

    servo_8.write(i);

    delay(40);

  }

  for (int i = 80; i <= 90; i++) {   //上升回正

    servo_4.write(i);

    delay(40);

  }

  for (int i = 85; i >= 20; i--) {   //右转

    servo_3.write(i);

    delay(30);

  }

  for (int i = 110; i <= 130; i++) {   //下降

    servo_7.write(i);

    delay(30);

  }

}

/*红灯*/

void red() {

  digitalWrite(12, HIGH);

  digitalWrite(8, LOW);

}

/*熄灯*/

void off() {

  digitalWrite(12, LOW);

  digitalWrite(8, LOW);

}

/*绿灯*/

void green() {

  digitalWrite(12, LOW);

  digitalWrite(8, HIGH);

}

*更多详情请见:【S033】校园餐具回收分类机器人

你可能感兴趣的:(机器人,开源)