作者:范永晨 杨丽鹏 张东生
单位:唐山学院
指导老师:袁娜
都说21世纪为物流的天下,物流行业牵扯到各个领域。目前,劳动人口数量下降、老龄化现象加速、工资上涨,土地成本提升,随着市场不断发展,物流企业的压力也逐渐增大,这样的背景下,"机器人"成为降低物流人工成本和提高仓储物流效率的最主要的解决方案。要想缓和市场带来的压力,只有不断的提升自身能力。智能化设备的应用将给物流业带来生机,也给物流业带来更多的收益。作为物流业,各企业的竞争压力也逐渐大,面对压力企业就需要不断给自己升级。物流企业的效率、成本、客户的评价等都很重要。物流搬运机器人作为高智能设备在物流业的作用很明显。最直接的效果就是搬运效率的提升,效率是每个物流企业都很看重的关键,更是客户评价物流公司好坏的指标。如果快递很慢,是不会得到客户好评的。如今物流搬运机器人的出现,无人操作,可以持续的处理各类货物,不用休息,让整个的处理快件的速度大大提升,客户对物流企业的好感在增加,企业的竞争力也在提升。接着是物流成本的下降,物流企业的成本有人工、破损、搬运等诸多项目组成。面对市场竞争的加大降低成本势在必行。物流搬运机器人可以实现无人操作,如此一来,人工成本消失。工作效率提升,那么单位时间创造的利润就增加的。
基于以上调研,智能物流搬运机器人在物流业中的价值是不可估量的,不但实现的无人操作,还实现了高效低成本的运行,为企业带来利好。
1. 作品功能简介
一个完整的智能物流搬运系统有很多部分组成,如分拣、搬运、码垛等等,我们设计的智能车主要实现的是搬运这一部分,六电机驱动,四个舵机实现夹取,主要功能如下:
1.1 红外识别夹取
小车安装红外模块,红外传感器模块对环境光线适应能力强,其具有一对红外发射与接收管,发射管发射出频率的红外线,当检测方向遇到障碍物(反射面)时,红外线反射回来被接收管接收,小车停止,机械臂在红外识别位置对物体进行夹取并放置到小车存储仓,完成这一系列动作后小车继续运行。
1.2 灰度循迹
采用三灰度循迹传感器,三个灰度传感器排列在车前底部,当只有中间传感器检测到黑色时,小车直行;左边传感器检测到黑色时,小车执行右转指令;右边传感器检测到黑色时,小车执行左转指令。
1.3 智能避障
避障功能利用了超声波传感器实现,当位于小车前方的超声波传感器检测到小车前方有障碍物时,小车会绕过障碍物,沿着原先路线行驶。
2. 作品实际应用
我国是工业制造业大国,在诸多产业中都需要搬运大量的生产所需要的物资。我国制造业不断地向智造业转型,工业生产不断地向自动化转型。我们的设计的智能循迹搬运车能够实现自动化搬运货物,据我们的实际调查,我们的智能循迹搬运车可以按照一定的轨迹进行运动,在循迹的同时检测货物,进行货物装载。同时能进行以下场景的工作:
① 仓储业,仓储业是较早应用的场所。用于实现出入库的自动搬运,目前应用较多的搬运型智能小车是码垛型小车,码垛型有各种形式的,腾阳公司生产的码垛智能小车有低位码垛机,高位码垛机,立柱式和坐标式码垛小车,全国还有很多不同类型的智能搬运小车,每天在大量的完成出入库货物的码垛和搬运任务。
② 制造业,搬运小车目前在制造业中主要用于汽车制造业,它可以随着生产工艺流程的调整而调整,使一条生产线上能够制造出更多种类的产品,并且更加高效、准确、灵活的完成物料的搬运任务。
③ 邮局、图书馆、港口码头和机场,在邮局、图书馆、码头和机场等场合,物品的运送存在着作业量变化大,动态性强,作业流程经常调整,以及搬运作业过程单一等特点,搬运小车的并行作业、自动化、智能化和柔性化的特性能够很好的满足上式场合的搬运要求。
④ 烟草、医药、食品、化工,对于搬运作业有清洁、安全、无排放污染等要求的烟草、医药、食品、化工等行业中,搬运小车的应用也受到重视。在国内的许多卷烟企业,应用了灰度引导循迹令搬运小车完成托盘货物的搬运工作。
3. 所用主要元件
3.1 灰度传感器
3.1.1 简介
有一只发光二极管和一只光敏电阻,安装在同一面上。灰度传感器利用不同颜色的检测面,对光的反射程度不同,光敏电阻利用不同检测面返回的光不同、其阻值也不同的原理来进行颜色深浅检测。在有效的检测距离内,发光二极管发出白光,照射在检测面上,检测面反射部分光线,光敏电阻检测此光线的强度并将其转换为机器人可以识别的信号。灰度既可以当作数字量传感器使用,也可以当作模拟量传感器使用。
3.1.2 工作原理
灰度检测的有效距离在0.7cm~3cm之间,当传感器检测到有深色标记时,将会触发传感器,使其输出口有低电平输出;当传感器检测到浅色标记时,传感器将不会被触发,所以其输出口是高电平输出。
3.2 超声测距模块
3.2.1 简介
超声测距模块使用HC-SR04 超声波测距模块,可提供2cm-400cm 的非接触式距离感测功能,测距精度可达高到3mm;模块包括超声波发射器、接收器与控制电路。
3.2.2 超声波时序图
以上时序图表明你只需要提供一个10uS 以上脉冲触发信号,该模块内部将发出8 个40kHz 周期电平并检测回波。一旦检测到有回波信号则输出回响信号。回响信号的脉冲宽度与所测的距离成正比。由此通过发射信号到收到的回响信号时间间隔可以计算得到距离。
公式:uS/58=厘米或者uS/148=英寸;或是:距离=高电平时间*声速(340M/S)/2;建议测量周期为60ms 以上,以防止发射信号对回响信号的影响。
3.2.3 工作原理
① 采用IO口TRIG 触发测距,给最少10us 的高电平信呈。
② 模块自动发送8 个40khz 的方波,自动检测是否有信号返回。
③ 有信号返回,通过IO 口ECHO 输出一个高电平,高电平持续的时间就是波从发射到返回的时间。测试距离=(高电平时间*声速(340M/S))/2。
3.3 近红外传感器
3.3.1 简介
近红外传感器是一种开关量传感器,它可以检测到前方是否有物体存在,当检测到有物体存在时,传感器输出口会输出低电平;相反在未检测到前方有物体时,传感器输出口会输出一个高电平。主控芯片可根据传感器采集的电平高低做出相应的动作指令。
3.3.2 工作原理
近红外线传感器是利用红外线的物理性质来进行测量的传感器。红外线又称红外光,它具有反射、折射、散射、干涉、吸收等性质。而近红外传感器正是利用其这一特性工作的,当前方有物体并且在红外线反射范围之内时,传感器会接收到反射的红外线,进而触发近红外传感器。
3.4 小型直流驱动轮
3.4.1. 运动功能说明
从方向上说有正转、反转两种;从控制方式上说,有数字量输出和模拟量(PWM)输出两种,模拟量输出可以调整速度。
3.4.2 结构说明
构成本模组的零部件主要是直流电机、1:10模型轮胎,以及配套的直流电机的支架、输出头、联轴器、螺丝、螺母、螺柱等。
3.5 舵机关节模组
3.5.1 运动功能说明
舵机关节模组的主要运动方式为用舵机带动U型支架摆动,从而模仿生物关节运动的效果。
3.5.2 结构说明
构成本模组的零部件主要是舵机(行程0度~180度)、舵机支架、舵机输出头、舵机双折弯(U型支架)、螺丝、螺母等。
3.6 舵机夹爪模组
3.6.1 运动功能说明
夹爪模组的主要运动模式为张开以及闭合。
3.6.2结构说明
构成本模组的零部件主要是舵机(行程0度~180度)、舵机输出头、舵机支架、齿轮组、连杆组等。
4. 作品难点及解决方案
① 在用红外识别快递,小车停车定点夹取时,由于小车的惯性,在识别到物体时,往往会继续向前行驶一小段距离,造成小车和物体位置与先前识别的位置有偏差,机械臂不能准确夹取物体。为了使小车稳定停止后机械臂能准确夹取,经过反复实验,确定了小车红外识别到物体准备停车到小车稳定停车这一段距离,将红外传感器位置从原先位置提前了同样的距离,最终小车能准确识别夹取。
② 在用灰度传感器循迹时,由于晚上灯光较暗,加上起初车轮底盘较低,遮光造成循迹识别不准确,车辆难以按原轨道行驶,为解决以上问题,我们前轮选用直径更大的车轮以增高底盘,增大透光。
③ 小车在爬坡时,经常性的卡在坡上,为了满足场景的各种可能外在因素,保障小车稳定运行,我们选择改变小车结构,增大底盘的同时,将小车后轮变为可活动型,使其能顺利通过小坡。
5. 软件设计
在小车的设计中,我们根据开发板的具体情况使用arduino软件,采用主流设计语言C语言对开发板进行编程实现各项功能。C语言功能丰富,表达能力强,目标程序效率高,可移植性好,既有高级语言的优点,又有低级语言的许多特点,应用十分广泛。
5.1 智能循迹搬运车总体流程
此部分是小车运行的核心部分,起着控制小车运行状态的作用,具有导向和决策的功能。
① 首先要对小车进行初始化,在这个阶段小车会通过红外传感器和超声波传感器检测物体,同时在循迹。
② 接着当开发板判断是否有物体,如果前进道路上有物体存在,小车进行基于超声波的避障程序,避开障碍后按原路路线前进,若红外传感器识别到物体则,小车停止前进,启动机械臂自动夹取的程序,对物体进行夹取。
③ 当夹取完毕之后,小车会继续循迹,当遇到下一个物体的时候,小车会再次停下,对物体进行夹取。程序控制流程图如下所示:
5.2 小车功能代码
① 小车避障代码
java
#define Trig A1 //引脚Tring 连接 A1
#define Echo A0 //引脚Echo 连接 A0
int pin[3] = {A2, A4, A3};
byte value;
byte value_his = 0;
float cm; //距离变量
float temp; //记录上一次的传感器值
void setup()
{
Serial.begin(9600);
pinMode(Trig, OUTPUT);
pinMode(Echo, INPUT);
pinMode( 5 , OUTPUT);
pinMode( 6 , OUTPUT);
pinMode( 9 , OUTPUT);
pinMode( 10 , OUTPUT);
analogWrite(9,1); //analogWrite values from 0 to 255
analogWrite(10,1); //analogWrite values from 0 to 255
analogWrite(5,1); //analogWrite values from 0 to 255
analogWrite(6,1); //analogWrite values from 0 to 255
}
void loop()
{ get_echo();
if(cm<20){ //距离小于20cm就执行下面的动作
//执行相应的动作
Back ();
delay(500);
Left();
delay(300);
Forwards();
delay(1300);
Right();
delay(900);
Forwards();
delay(1000);
}
else //距离不小于20cm就执行这个动作
{
value = 0;
for(int i=0; i<3; i++)
{
value |= (digitalRead(pin[i]) << i);
}
if(value == 0x07){ //当传感器都没有触发时默认为上一次的值
value = value_his;
}
switch (value)
{
case 0x00: //全部触发
Forwards();
break;
case 0x01: //触发右边两个
while(digitalRead(pin[1])){ //通过while 循环使小车回到跑道中间
Right();
}
break;
case 0x03: //触发右边一个
while(digitalRead(pin[1]))
{
Right();
}
break;
case 0x04: //触发左边两个
while(digitalRead(pin[1]))
{
Left();
}
break;
case 0x05: //触发中间一个
Forwards();
break;
case 0x06: //触发左边一个
while(digitalRead(pin[1]))
{
Left();
}
break;
default:
Stop();
}
value_his = value;
}
}
void get_echo() {
//给Trig发送一个低高低的短时间脉冲,触发测距
digitalWrite(Trig, LOW); //给Trig发送一个低电平
delayMicroseconds(2); //等待 2微妙
digitalWrite(Trig,HIGH); //给Trig发送一个高电平
delayMicroseconds(10); //等待 10微妙/
digitalWrite(Trig, LOW); //给Trig发送一个低电平
temp = float(pulseIn(Echo, HIGH)); //存储回波等待时间
//pulseIn函数会等待引脚变为HIGH,开始计算时间,再等待变为LOW并停止计时
//返回脉冲的长度
cm = (temp * 17 )/1000; //把回波时间换算成cm
//声速是:340m/1s 换算成 34000cm / 1000000μs => 34 / 1000
//因为发送到接收,实际是相同距离走了2回,所以要除以2
//距离(厘米) = (回波时间 * (34 / 1000)) / 2
//简化后的计算公式为 (回波时间 * 17)/ 1000
Serial.print("Echo =");
Serial.print(temp);//串口输出等待时间的原始数据
Serial.print(" | | Distance = ");
Serial.print(cm);//串口输出距离换算成cm的结果
Serial.println("cm");
}
void Left()
{
digitalWrite( 5 , HIGH );
digitalWrite( 6 , LOW );
digitalWrite( 9 , LOW );
digitalWrite( 10 ,HIGH );
}
void Right()
{
digitalWrite( 5 , LOW );
digitalWrite( 6 , HIGH );
digitalWrite( 9 , HIGH );
digitalWrite( 10 , LOW );
}
void Forwards()
{
digitalWrite( 5 , HIGH );
digitalWrite( 6 , LOW );
digitalWrite( 9 , HIGH );
digitalWrite( 10 , LOW );
}
void Stop()
{
digitalWrite( 5 , LOW );
digitalWrite( 6 , LOW );
digitalWrite( 9 , LOW );
digitalWrite( 10 , LOW );
}
void Back() //后退函数
{
digitalWrite(5, LOW);
digitalWrite(6, HIGH);
digitalWrite(9, LOW);
digitalWrite(10, HIGH);
}
② 机械臂夹取代码
java
#include<Servo.h> //调用舵机库
#define Servo_duo1 4 //定义舵机串口
#define Servo_duo2 7
#define Servo_duo3 11
#define Servo_duo4 12
//舵机1
#define Angle_1 30
#define Angle_2 150
//舵机2
#define Angle_3 60
#define Angle_4 100
//舵机3
#define Angle_5 75 //设置舵机转动的角度为75度
#define Angle_6 60 //设置舵机转动的角度为60度
//舵机4
#define Angle_7 100
#define Angle_8 0
Servo myservo1; //声明舵机对象
Servo myservo2;
Servo myservo3;
Servo myservo4;
Servo myservo5;
Servo myservo6;
Servo myservo7;
Servo myservo8;
int pin[3] = {A2, A4, A3};//定义灰度传感器串口
byte value;
byte value_his = 0; //记录上一次的传感器值
void setup()
{ Serial.begin(12500);//开启串口,并设置波特率为12500
pinMode( 5 , OUTPUT);
pinMode( 6 , OUTPUT);
pinMode( 9 , OUTPUT);
pinMode( 10 , OUTPUT);
pinMode(14, INPUT);
}
void loop()
{
if(!(digitalRead(14)))
{ Stop();
jixiebi();
}
else{
xunji();
}}
void Left()
{
digitalWrite( 5 , HIGH );
digitalWrite( 6 , LOW );
digitalWrite( 9 , LOW );
digitalWrite( 10 , HIGH );
}
void Right()
{
digitalWrite( 5 , LOW );
digitalWrite( 6 , HIGH );
digitalWrite( 9 , HIGH );
digitalWrite( 10 , LOW );
}
void Forwards()
{
digitalWrite( 5 , HIGH );
digitalWrite( 6 , LOW );
digitalWrite( 9 , HIGH );
digitalWrite( 10 , LOW );
}
void Back()
{
digitalWrite( 5 , LOW );
digitalWrite( 6 , HIGH );
digitalWrite( 9 , LOW );
digitalWrite( 10 , HIGH );
}
void Stop()
{
digitalWrite( 5 , LOW );
digitalWrite( 6 , LOW );
digitalWrite( 9 , LOW );
digitalWrite( 10 , LOW );
}
void jixiebi()
{//舵机4开
Serial.begin(9600);//开启串口,并设置波特率为9600
myservo4.attach(Servo_duo4);//设置舵机引脚
myservo4.write(Angle_7); //4号引脚舵机直接转到0度
delay(1000); //等待1秒
//舵机1夹
myservo1.attach(Servo_duo1);//设置舵机引脚
myservo1.write(Angle_1); //1号引脚舵机直接转到30度
delay(1000); //等待1 秒
//舵机3夹
myservo3.attach(Servo_duo3);//设置舵机引脚
myservo3.write(Angle_5); //11号引脚舵机直接转到75度
delay(1000); //等待1秒
//舵机2夹
myservo2.attach(Servo_duo2);//设置舵机引脚
myservo2.write(Angle_3); //4号引脚舵机直接转到60度
delay(1000); //等待5秒
//舵机4夹
myservo4.attach(Servo_duo4);//设置舵机引脚
myservo4.write(Angle_8); //4号引脚舵机直接转到0度
delay(1000); //等待1秒
//舵机2放
myservo2.attach(Servo_duo2);//设置舵机引脚
myservo2.write(Angle_4); //4号引脚舵机直接转到100度
delay(2000); //等待2秒
//舵机1放
myservo1.attach(Servo_duo1);//设置舵机引脚
myservo1.write(Angle_2); //4号引脚舵机直接转到150度
delay(1000); //等待1秒
//舵机3放
myservo3.attach(Servo_duo3);//设置舵机引脚
myservo3.write(Angle_6); //11号引脚舵机直接转到60度
delay(1000); //等待1秒
//舵机4开
myservo4.attach(Servo_duo4);//设置舵机引脚
myservo4.write(Angle_7); //4号引脚舵机直接转到100度
}
void xunji()
{value = 0;
for(int i=0; i<3; i++)
{
value |= (digitalRead(pin[i]) << i);
}
if(value == 0x07){ //当传感器都没有触发时默认为上一次的值
value = value_his;
}
switch (value)
{
case 0x00: //全部触发
Forwards();
break;
case 0x01: //触发右边两个
while(digitalRead(pin[1])){ //通过while 循环使小车回到跑道中间
Right();
}
break;
case 0x03: //触发右边一个
while(digitalRead(pin[1]))
{
Right();
}
break;
case 0x04: //触发左边两个
while(digitalRead(pin[1]))
{
Left();
}
break;
case 0x05: //触发中间一个
Forwards();
break;
case 0x06: //触发左边一个
while(digitalRead(pin[1]))
{
Left();
}
break;
}
value_his = value;
}
6. 结束语
我们的循迹搬运车由于设计并不复杂,我们没有在电路中增加冗余的功能,但是我们保存了各种硬件接口和软件子程序接口,方便以后的扩展和进一步的开发。在本次设计中,通过我们共同的努力,我们完成了循迹搬运小车的设计与制作,本设计中的循迹搬运车能完成了题目要求的大局部功能,同时也提高了我们的创新意识和团队合作意识,培养了我们认真分析问题、独立解决问题的能力,稳固了我们对所学理论的实际运用。还锻炼了我们的动手实践能力,使我们更有信心在电子行业中继续学习下去。
参考文献
【1】王秋爽,曾兆龙单片机开发根底与经典设计实例。2021年3月第一版
【2】肖洪兵、等,跟我学用单片机,北京:北京航空航天大学出版社,2002:154-162.
【3】华成英童诗白模拟电子技术根底第四版高等教育出版社
【4】吴锤红 MCS -51微机原理与接口技术厦门大学出版社
【5】张毅刚单片机原理及应用2003年12月第一版高等教育出版社
【6】江新,李华军,刘东俊,单片机程序设计及应用从根底到时间,北京,电力电子出版社,2006年3月第一版
【7】李正军,计算机控制系统,北京:机械工业出版社,2005:57-106。
【8】机械工业出版社北京,李朝青,单片机& DSP 外围数字 IC 技术手册,北京:北京航空航天大学出版社,2002:I-48
【9】文艳,谭鸿。 Protel 99 SE 电子电路设计,北京:机械工业出版社,2006:2-110。
【10】元增民,张文希,单片机原理与应用根底,长沙:国防科技大学出版社,2006:1-30。
【11】李朝青,单片机原理及接口技术,第3版,北京:航空航天大学出版社,2005:39-231。
【12】童诗白、华成英。模拟电子技术根底,北京:高等教育出版社,2003,(5):41-245
更多详情请见:【S044】智能循迹搬运车****