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

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

单位:华北科技学院

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

1. 场景调研

1.1 项目实施目的

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

实地调研

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

现有餐具回收机器人

1.2 项目实施意义

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

2. 机器人本体设计

2.1 总体结构

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

整体结构

2.2 机械结构

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

底盘结构

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

机械爪结构

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

装卸机械臂结构

2.3 电路控制与设备调试

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

(1)餐具回收运输系统

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

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

(2)回收箱装卸系统

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

回收站 

3. 作品创新点

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

3.1 双机协同作业

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

双机三维模型

3.2 多种传感器联合应用

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

传感器

3.3 抓取结构的改进

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

抓取结构演变过程

3.4 回收箱结构可变

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

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

3.5 PWM调速

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

4. 难点及解决方案

4.1精准启停问题

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

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

4.2 抓取与装卸问题

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

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

4.3 双机协同的准确运行

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

4.4 餐具的精确分类

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

5. 前景展望

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

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

6. 示例程序

① 车载机械臂代码

/*车载机械臂代码*/

#include <U8g2lib.h>   //显示屏库函数

#include <Servo.h>    //舵机库

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 <Servo.h>

#include <U8g2lib.h>

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】校园餐具回收分类机器人

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/215532.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ElementUI+vue+nodejs培训学校课程预约网站的设计与开发

该系统将采用B/S结构模式&#xff0c;前端部分主要使用html、css、JavaScript等技术&#xff0c;使用Vue和ElementUI框架搭建前端页面&#xff0c;后端部分将使用Nodejs来搭建服务器&#xff0c;并使用MySQL建立后台数据系统&#xff0c;通过axios完成前后端的交互&#xff0c;…

题目:神奇的进制

解题思路&#xff1a; 用电脑自带的计算器&#xff0c;切换到程序员模式。里面有进制转换功能。 由题目&#xff0c;要求严格递增且都为字母&#xff0c;还要大于2023&#xff0c;则数字16进制为ABC。

❀My学习Linux命令小记录(10)❀

目录 ❀My学习Linux命令小记录&#xff08;10&#xff09;❀ 36.fold指令 37.expr指令 38.iperf指令 39.telnet指令 40.ssh指令 ❀My学习Linux命令小记录&#xff08;10&#xff09;❀ 36.fold指令 功能说明&#xff1a;控制文件内容输出时所占用的屏幕宽度&#xff0c…

智能优化算法应用:基于供需算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于供需算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于供需算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.供需算法4.实验参数设定5.算法结果6.参考文献7.MATLAB…

基于PHP的在线日语学习平台

有需要请加文章底部Q哦 可远程调试 PHP在线日语学习平台 一 介绍 此日语学习平台基于原生PHP开发&#xff0c;数据库mysql。系统角色分为用户和管理员。(附带参考设计文档) 技术栈&#xff1a;phpmysqlphpstudyvscode 二 功能 学生 1 注册/登录/注销 2 个人中心 3 查看课程…

善网商城上线洁柔产品 公益人专享爱心价官方正品

近日&#xff0c;中国善网慈善商城&#xff08;以下简称善网商城&#xff09;系统经升级后重新上线。目前善网商城线上销售的中顺洁柔旗下慈善产品已顺利获得中顺洁柔纸业股份有限公司授权&#xff0c;双方就合作事宜达成共识&#xff0c;并于近日签订线上经营授权书。 &#x…

Optional源码分析(涉及Objects源码和Stream源码)

研究Optional源码之前先谈一谈Objects源码。 主要代码&#xff1a; ForceInlinepublic static <T> T requireNonNull(T obj) {if (obj null) {throw new NullPointerException();} else {return obj;}}ForceInlinepublic static <T> T requireNonNull(T obj, Str…

C/C++,图算法——凸包的快速壳(Quick Hull)算法的源代码

1 文本格式 // C program to implement Quick Hull algorithm // to find convex hull. #include<bits/stdc.h> using namespace std; // iPair is integer pairs #define iPair pair<int, int> // Stores the result (points of convex hull) set<iPair>…

外包干了2个月,技术退步明显。。。。。

先说一下自己的情况&#xff0c;本科生生&#xff0c;18年通过校招进入武汉某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年国庆&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测…

Linux --- 进程控制

目录 1. 进程创建 1.1. 内核数据结构的处理 1.2. 代码的处理 1.3. 数据的处理&#xff1a; 方案一&#xff1a;fork创建子进程的时候&#xff0c;直接对数据进行拷贝处理&#xff0c;让父子进程各自私有一份 方案二&#xff1a;写实拷贝(copy on write) 1.4. fork常规用…

RocketMQ-整合SpringBoot

SpringBoot整合RocketMQ 创建Maven工程&#xff0c;引入关键依赖&#xff1a; <dependencies><dependency><groupId>org.apache.rocketmq</groupId><artifactId>rocketmq-spring-boot-starter</artifactId><version>2.2.2</ver…

flutter开发实战-readmore长文本展开和收缩控件

flutter开发实战-readmore长文本展开和收缩控件 当长文本展开和收缩控件&#xff0c;我们需要使用readmore来处理长文本展开和收缩&#xff0c;方便阅读 一、引入readmore 在工程的pubspec.yaml中引入插件 readmore: ^2.1.0ReadMoreText的属性如下 const ReadMoreText(this.…

Pandas操作数据库

一&#xff1a;Pandas读取数据库数据 二&#xff1a;Pandas读取海量数据 三&#xff1a;Pandas向数据库存数据 四&#xff1a;Pandas写入海量数据

低噪声,带内置 ALC 回路的双通道均衡放大器,应用于立体声收录机和盒式录音机的芯片D3308的描述

D3308 是一块带有 ALC 的双通道前置放大器。它适用于立体声收录机和盒式录音机。采用 SIP9、SOP14 的封装形式封装。 主要特点 带内置 ALC 回路的双通道均衡放大器 低噪声: VNIl.OuV(典型值)。开环电压增益高: 80dB (典型值)工作电源电压范围宽: 通道间的…

EPS地形图绘制技巧--快捷键

如何导入外业点数据&#xff1f; &#xff08;1&#xff09;打开EPS软件&#xff0c;新建一个工程。如下&#xff1a; &#xff08;2&#xff09;在【文件】-【输入输出】-【调入坐标文件数据】中&#xff0c;调入测量点数据&#xff0c;如下&#xff1a; &#xff08;3&#…

基于粒子群算法思想的电动汽车充放电策略-V2G模型-程序代码!

电动汽车充放电对电网的安全稳定带来影响&#xff0c;合理规划电动汽车充放电时间和策略是目前的研究热点。本程序仿真了汽车有序充电和无需充电两种案例&#xff0c;利用电动汽车合理消纳新能源电量&#xff0c;利用粒子群算法思想来求解模型&#xff0c;程序中案例丰富&#…

平价的开放式耳机怎么选?推荐几款平价好用的耳机,亲测对比

是不是也在为如何在有限的预算内找到一款性价比高的开放式耳机而烦恼呢&#xff1f;别着急&#xff0c;小编为你精心挑选了几款平价好用的开放式耳机&#xff0c;并亲自进行了对比测试&#xff0c;在这个音乐时代&#xff0c;不需要花大价钱就能拥有高品质的音乐体验&#xff0…

MacOS 系统 Flutter开发Android 环境配置

上节我们已经把 开发工具准备齐全&#xff0c;并可以进行Flutter的web开发&#xff0c;本节将做安卓开发环境进行详细说明 接上节这里先说下&#xff0c;系统环境 MacOS14 &#xff08;Sonoma&#xff09; 芯片 Apple M3 执行命令&#xff1a;flutter doctor 提示如下&#…

二蛋赠书十期:《剪映短视频剪辑从入门到精通》

前言 大家好&#xff01;我是二蛋&#xff0c;一个热爱技术、乐于分享的工程师。在过去的几年里&#xff0c;我一直通过各种渠道与大家分享技术知识和经验。我深知&#xff0c;每一位技术人员都对自己的技能提升和职业发展有着热切的期待。因此&#xff0c;我非常感激大家一直…

PPT NO.5 科研绘图常用操作快捷键

1、Ctrl键 ①按住Ctrl键&#xff0c;可以跳选多个对象&#xff1a; ②按住Ctrl键&#xff0c;同时拖动对象即可进行复制&#xff1a; ③按住Ctrl键&#xff0c;可以对对象进行中心放大或中心缩小&#xff1a; 2、Shift键 ①按住Shift键&#xff0c;拖动对象只能水平或垂直移动…