1.引言
1.1目的
1.通过解决相关实际问题,以巩固、加深对嵌入式的认识和相关知识的理解,提高综合运用课程知识的能力。
2.熟悉与计算机相关的嵌入式方面的电子元器件和电路特性,能正确反映设计和实验成果,提高自主创新能力。
3.培养严肃认真的工作作风和严谨科学态度。通过课程设计实践,获得初步的应用经验,为以后从事生产和科研工作打下的坚实的基础。
4.培养根据课题需要选学参考书籍、查阅手册图表和文献资料的自学能力。通过独立思考,深入钻研有关问题,学会自己分析解决问题。
5.了解与课程有关的电子电路以及元器件技术规范,按课程设计任务书的要求编写设计说明书。提高自己的动手能力,培养严肃、认真的工作作风和科学态度。
6.为了完成一款自主设计、制作的嵌入式作品,以提升个人能力和队嵌入式的兴趣。
7.对避障小车的避障原理有充分的理解,掌握其避障的方法,能够对实验过程中出现的问题进行解决,发现问题,解决问题。
1.2背景
学习智能小车系统,有助于提高搭建系统的能力和对自动控制技术的理解。智能小车是一个较为完整的智能化系统,而智能化的研究已成为我国追赶世界科技水平的重要任务。智能小车有它特有的特点:成本低,涉及的知识面广,易于拓展[1]。整个智能小车系统作为一个完整的系统,从它的原理图的实现到实物的完成的过程,不仅需要深厚的电子方面的知识,还有对电路实现的良好掌握,对于培养学生的实践能力都有重要的意义。智能小车的竞赛在我国各大高校中都受到了重视,吸引了大批的高校学生的兴趣,而且取得了很多优异的成果,为我国推进智能化的进程做出了巨大的贡献,也为智能汽车的发展提供了理论依据[2-3]。
只有当把理论和模型应用到实践中,这样的创新才用意义,我们国家这几年在智能化方面的进步越来越快,也推动了我国在国际社会上在智能化方面的话语权。智能小车是智能化的一部分,它的系统里的避障、循迹、红外遥控的技术用到了智能化,将智能化应用到传统技术上是21世纪发展的趋势。
我国虽然从改革开放以来大力发展科技创新,但是在智能化的创新水平与国外较发达的国家相比还有巨大的差距,智能竞赛在高校越来越流行,也证明了我国教育在这方面很快会赶上世界上的发展水平。本次设计是以单片机为电路板,通过编程和一些外围电路的设计来实现红外遥控,避障,循迹等功能。最重要的是把模型上的研究应用到实际生活中,智能车辆便做到了这一点[4-6]。在实际应用中比如在倒车的过程中实现的红外警报系统是以智能小车为模型而研发出来的。对于电子知识的热爱与钻研有利于研发更多智能车辆,使我们的生活更加便利、智能化。
本次课程设计主要任务是实现基于51单片机智能小车红外避障和循迹的主要功能应用。以红外避障的功能解决小车在不同的环境避开行走的障碍物,直到终点,以红外循迹的功能去感应黑线找到走出迷宫的线索为目标。让机器人小车变得更加灵活。
2 需求分析
智能小车作为现代的新发明,是以后的发展方向,他可以按照预先设定的模式在一个环境里自动运作,不需要人为的管理,可应用于科学勘探等等用途;并且能实现显示时间、速度、里程,具有红外自动寻迹、避障等功能,可程控行驶速度、定位停车,远程传输图像、按键控启动K4让小车运行起来,利用红外传感器感应黑线进行寻迹,利用红外反射感应进行红外避障功能。
图1 智能小车设计思维导图
如图1所示,我们使用STC89C52RC单片机电路板控制整个机器人小车的功能,通过接线建立好小车的电路图连接以及通过C51书写红外避障以及循迹功能程序。在设计好的场地,从出发点到终点,通过现有的功能顺利躲开障碍物的干扰以及通过智能机器人寻找黑线的功能一直走好直线且顺利到达终点,完成任务。在车的模型上分析,我们也补充到了红外感应原理,红外传播通过我们学习物理光学知识后,能解决为什么避障反应慢的问题,并解决了。
如图2所示,智能小车初步构想流程图,让整个项目实现的目标更加清晰明了。利用红外传感器,其优点是对近距离的障碍物反应速度灵敏,不同方位的传感器之间信号不会相互干扰,最终选择红外传感器作为小车的眼睛,进行避障。
由于本次实验小车轮子没有实现转弯功能,所以通过设定左右两组轮子的不同前进速度来实现转弯功能。当向右转时,左侧轮子的速度要比右侧轮子的前进速度快,反之实现左转功能,此设计需小心谨慎,防止出现轮子不同步,无法实现转弯功能。
图2 智能小车功能模块流程图
3.系统设计
3.1总体设计
3.1.1 设计思路
总体来说,这个程序设计还算比较简单,比较基础,目的就是要学会基本的应用,这个过程中利用红外线传感器发射和接收信号模块来控制单片机,让单片机翻译传输指令,从而实现相应的功能。具体的过程如下:四路红外传感器,每一路发射一个信号,检测接收到的信号,若出现高电平,则说明该方向前方有障碍物,则单片机控制电机正转和反转,从而实现绕开障碍物继续前行。同时还增加一个无线发射和无线接收模块控制单片机,让单片机翻译传输指令,从而实现相应的功能。无线发射模块发出指令,无线接收模块接收信号后,传递给单片机,单片机翻译接收到信号后,传输给驱动电路驱动电机旋转,从而实现让小车的前进、后退、左转和右转。
在主控制器模块上分析,采用STC89C52单片机作为整个系统的核心,用其控制行进中的小车,以实现其既定的性能指标。充分分析我们的系统,其关键在于实现小车的自动控制,而在这一点上,单片机就显现出来它的优势——控制简单、方便、快捷。这样一来,单片机就可以充分发挥其资源丰富、有较为强大的控制功能及可位寻址操作功能、价格低廉等优点。51单片机具有功能强大的位操作指令,I/O口均可按位寻址,程序空间多达8K,对于本设计也绰绰有余,更可贵的是51单片机价格非常低廉。
图3 系统硬件总框图
系统硬件总框图如图3所示,用单片机作为处理器,开机启动后,通过一个直流电源给各个模块供电,当小车遇到障碍物时,脉冲调制的红外线传感器将检测到的信号发送给单片机,单片机根据程序发出相应的控制信号控制小车自动避开障碍物。其中具体的实现过程为:由传感器发出信号,检测前方是否有障碍物存在,当存在障碍物时通过把反馈信号送至单片机处理系统,然后通过改变两个电动机的转速转向改变小车方向直至前方无障碍物存在,然后小车继续向前行走。
图4 软件程序设计思路流程图
系统程序流程如图4所示。首先,软件系统设计利用红外传感器检测道路前方的障碍物,单片机通过检测各传感器的工作状态,并将采集到的数据进行综合分析处理后,产生高低电平控制电机驱动模块工作,实现对小车方向和速度的控制,从而实现电动小车自动避障的功能。
图5 系统软件程序设计流程图
该方案的编程思路是先确定主程序,之后根据各硬件电路功能来设计子程序模块,最后再将各模块嵌入主程序中。这样编程结构简单,由于子程序模块与硬件电路一一对应,所以调试起来十分方便。本设计软件方框图如图5所示
考虑到本系统需要检测障碍物的距离,避开障碍物,为了使用方便、系统稳定性、便于操作和调试。还考虑到避障程序中有循迹感应模块,目的也就是为了解决走偏问题,根据巡黑线和避开障碍物来完成走迷宫的游戏。
3.1.2 电路原理图
图6 51单片机检测模块电路原理图
如图6所示,小车开发板是51单片机构成的,采用 STC89C51 单片机作为智能小车部分的控制核心,单片机最小系统电路如图10:单片机最小应用系统主要由单片机、复位电路、震荡电路等部分组成。单片机的复位是为了初始化单片机的工作状态,当程序运行出错或者因操作错 误而使系统处于锁死状态,可以按复位按键重新初始化单片机。RST引脚是复位的输入端,要实现复位操作必须使RST引脚上至少保持两个机器周期的高电平,从高电平变为低电平的复位。而且单片机电路板控制着小车按键的启动以及红外光谱的避障感应传感器,以及遇到障碍物的报警蜂鸣器和LCD显示屏存储并显示测量小车与障碍物之间的距离的数值。
图7 智能小车底盘参考电路原理图
如图7所示,智能小车底盘电路图,我们利用了传感器模块进行分析,通过传感器接线的方法,将P3.4接入OUT3 左传感器且低电平有效,P3.5接入OUT4 右传感器且低电平有效,当4路红外传感器有信号时相应的LED灯会点亮,低电平有效信号才能显示LED电路。驱动输入驱动电机转动说明 IN1 右电机 高电平反转IN2 右电机 高电平正转EN2 右电机 低电平停车 IN3 左电机 高电平正转 IN4 左电机 高电平反转 EN1 左电机 低电平停车。其优点是电路简单,成本高。但是由于缺少保护电路,只要控制出现错误,就很容易烧坏晶体管,晶体管的价格也不菲,便宜货又电流太小,不足以承受小车的功率,使整个电路瘫痪。然而,使用集成电路LM298,由于集成程度高,内包含稳定的数字电路,就算在编写程序的时候错误或者其他原因使控制端口同时输出通过一种电平,不容易烧坏芯片,使整个电路瘫痪。同时芯片还有使能端,容易控制,且稳定。特有的PWN调制功能端,使电机更容易控制。也使得程序在减速的过程特别是保持左右电机速度平衡的程序编写上变得更加简洁容易。
图8 智能小车红外循迹与红外避障原理图
如图8所示,本次课程设计实验我们设计了红外避障和循迹功能的电路原理图,通过接线搭建好电路后,以及程序调试的实现,我们得出了循迹与避障的比较的相同点与不同点之间的结论。具体如下:
相同点:
1:原理图相同,均采用红外发送接收对管来完成。
2:硬件调节方式相同,都通过滑动电阻调节灵敏度。
3:均为有信号时输出低,指示灯亮起。
不同点:
1:探测方向不同,前者对地面探测,后者对行进方向正前方探测。
2:循迹需要靠没有信号(灯灭)时来判断黑线位置,避障需要靠有信号(灯亮)时来判断障碍物位置。
3:小车行驶速度不同,循迹需要精细的调节左右电机运动,而避障只需判断障碍物后作出一般性躲避,固避障时电机速度可快于循迹。
3.2功能设计
图9 模块功能图
如图9所示,根据C51单片机智能小车的需求分析,从模块图出发,我们设计了主要以红外避障为主、红外循迹为辅解决一个小车走迷宫和行驶路径的问题,目的让小车在受到直线行驶干扰的情况下,完成任务,走出障碍物干扰的困难。
图10 避障程序流程图
根据程序流程图10所示,应用程序软件进行小车避障程序设计,通过不同的if,while语句的判断进行小车转弯的程序设计(在进行程序设计时要注意判断条件的设定),设计完成后,将程序烧录到单片机电路板里,进行小车避障的检测,并发现问题进行相应的改进。当前方没有障碍物的时候车就一直直走。如果前方遇到障碍物,左右两个红外判断,左侧有障碍物,则小车做右转运动。直至左红外感应不到障碍物,这时小车恢复直走。如果左方,右方均有障碍物,则小车先后退,默认向右转,直至前左方,右方任一方向没有障碍,则此时小车开始直走。
图11红外循迹与避障传感器执行流程图
红外探头传感器工作流程图如图11所示。红外光电传感器部分工作流程:先对各红外对管(即红外探头)进行初始化,小车在行驶过程中,怎样保 证在正常轨道上行驶而不跑偏,主要通过左右红外探头不断发射、接收信号来判断是否偏离轨道。若发现左偏,则会使小车向右偏转一定角度;反之,则使小车向左偏转一定角度。
4.系统开发
4.1源程序清单
如表1所示,这是源程序清单的所有功能的整理,能通过接线,C语言函数的控制,让小车能够顺利完成任务的程序清单。可以总结成一个项目框架。
表1 源程序清单
名称 | 作用 |
Main | 主函数清单 |
HJ-4WD_PWM.H | 智能小车驱动IO口定义等函数 |
AT89X52.H | 51单片机头文件,内部有各种寄存器定义 |
BUZZ | 蜂鸣器 |
Run() | 前进 |
leftrun | 左转 |
rightrun | 右转 |
stoprun | 停止 |
timer0()interrupt 1 using 2 | TIMER0中断服务子函数产生PWM信号 |
4.2功能实现
#include //包含51单片机头文件,内部有各种寄存器定义#include //包含HL-1蓝牙智能小车驱动IO口定义等函数 //主函数void main(void){unsigned char i;int s=1; P1=0X00; //关电车电机//本实验学习的按键启动知识 B:for(i=0;i<50;i++) //判断K4是否按下{delay(1);//1ms内判断50次,如果其中有一次被判断到K4没按下,便重新检测 if(P3_7!=0)//当K4按下时,启动小车前进,如有不明,请看慧净51单片机视频教程 goto B; //跳转到标号B,重新检测 } //本实验学习的知识蜂鸣器,注意要在HJ-4WD头文件里定义IO口BUZZ=0;//50次检测K4确认是按下之后,蜂鸣器发出“滴”声响,然后启动小车。delay(50);BUZZ=1;//响50ms后关闭蜂鸣器TMOD=0X01; TH0= 0XFc; //1ms定时 TL0= 0X18; TR0= 1; ET0= 1;EA = 1; //开总中断for(s;s<=10;s++)//有信号为0 没有信号为1{if(s==1){while(1)//无限循环{ //有信号为0 没有信号为1 if(Left_1_led==1&&Right_1_led==1) run(); //调用前进函数 else //右边检测到红外信号 { rightrun(); //调用小车左转函数delay(35); stoprun(); //调用小车停止函数delay(50); run(); //直走delay(150); leftrun();delay(30); //右转23毫秒stoprun(); //调用小车停止函数delay(50); //停止50毫秒 break; }}}if(s==2){while(1)//无限循环{ //有信号为0 没有信号为1 if(Left_1_led==1&&Right_1_led==1)run(); //调用前进函数else{ leftrun(); //调用小车右转函数delay(35); stoprun(); //调用小车停止函数delay(50);run(); //直走delay(150); rightrun(); //调用小车左转函数delay(35); stoprun();//调用小车停止函数delay(50); //停止50毫秒 break;}}}if(s==3){while(1)//无限循环{ //有信号为0 没有信号为1if(Left_1_led==1&&Right_1_led==1)run(); //调用前进函数else{ rightrun(); //调用小车左转函数delay(35); stoprun(); //调用小车停止函数delay(50); run(); //直走delay(150); leftrun();delay(35); //右转23毫秒stoprun(); //调用小车停止函数delay(50); //停止50毫秒 break; }}} //停止50毫秒}}
5.系统测试
5.1测试方法
1.在各种环境下,将小车上的单片机电路板按K4持续2-5秒后,有蜂鸣器声音传播后,小车就已经开始启动,从起点出发前进一定的时间。
2.当小车遇到障碍物的时候,这时候红外感应器的感应障碍物或各种能感应红外传播的物体后,小车将会根据左右红外灯感应进行左转或右转以及停止前进。
3.直接小车避开红外障碍物后,若能根据循迹功能检测到黑直线,将会跟着黑直线直走走向终点,完成一项路径行驶任务。
Tip:首先烧入电机控制小程序,控制电机正反转,停止均正常。说明电机及驱动电路无误。然后加入避障子程序,小车运转正常时,调节红外避障模块灵敏度使达到理想效果。在调试程序时,发现有的指令用的不正确,导致电路功能不能完全实现,另外软件程序中的延时有的过长、有的过短。类似的现象还有很多就不一一列举了不过有个缺点,就是在小车遇到深颜色的障碍物,红外光已经被吸收了就无法进行光的反射的红外感应,就没能顺利成功避障,但在逐步接近障碍物的时候就可以避开,还有个问题就是车走不直,需要用到黑线来把直线拉直才能完成最终任务。
5.2测试用例
我们根据51智能小车的需求分析和设计思路进行后,目的为了实现小车走完一个行驶路程的一件事,设计了小车红外避障和小车红外寻迹的功能。我们通过C语言实现了小车的主要避障与循迹功能后,顺利完成了机器人行驶的任务,并且把小车的测试情况汇总出一个测试用例如下表2所示。
表2 测试用例
测试功能序号 | 测试小车功能 | 测试使用方法 | 测试结果现象 | 测试结果是否通过 |
1 | 启动小车 | 按键K4持续2-5秒 | 小车启动发出蜂鸣器声音且前进 | 是 |
2 | 小车前进遇到左侧有障碍物 | 小车左侧红外感应 | 小车先停下向右避障行驶 | 是 |
3 | 小车前进遇右侧有黑线 | 小车右侧黑线感应 | 小车跟着黑线的路径走 | 是 |
4 | 小车行驶中遇到遇到右侧有障碍物 | 小车右侧红外感应 | 小车先停下向左侧避障行驶 | 是 |
5 | 小车前进遇左侧有黑线 | 小车左侧黑线感应 | 小车的左边跟着黑线一直走直线或弧线 | 是 |
参考文献
[1]陆蕊. 基于单片机的智能小车系统的设计[J]. 电子世界, 2017(8):166-166.
[2陈梦婷,胡白燕,黄璨.基于单片机的智能循迹避障小车的设计与实现[J].智能机器人,2016:47-51.
[3]陈海宴.51单片机原理及应用[M].北京:北京航空航天大学出版社.2010:62-65.
[4]高枫.基于ARM的智能寻迹小车的设计与实现[D].山西:中北大学,2012.6.
[5]陈海洋,李东京.基于单片机的智能循迹避障机器人小车设计[J].科技风,2014(20):99.
[6]钱栢霆,李娟.基于单片机的循迹避障智能小车系统的设计[J].电子制作,2015(6x)
[7]李朝青.单片机原理及接口技术.北京:北京航空航天大学版社,2005
[8]谢维成.单片机原理与应用及C51程序设计.北京:清华大学出版社,2006
[9]张海军,宋兴文,赵锐朋,刘杨.基于C51单片机智能小车设计[J].农家参谋,2020(02):187-188.
[10]王君颜,许坤.基于STC89C51单片机的多功能智能小车设计策略研究[J].南方农机,2019,50(04):106.
[11]谢晓敏,闵锐.基于89C51单片机的智能寻迹避障小车设计[J].太原学院学报(自然科学版),2018,36(01):15-18.DOI:10.14152/j.cnki.2096-191X.2018.01.003.
附件 程序清单
Main.c******************************************************************/ //按下K4按键,1秒左右启电小车(注意不要接入测速模块)//按下复位健可以停止小车//注意程序只做参考之用,要达到最理想的效果,还需要同学们细心调试。#include //包含51单片机头文件,内部有各种寄存器定义#include //包含HL-1蓝牙智能小车驱动IO口定义等函数//主函数void main(void){unsigned char i;int s=1; P1=0X00; //关电车电机//本实验学习的按键启动知识B:for(i=0;i<50;i++) //判断K4是否按下{delay(1);//1ms内判断50次,如果其中有一次被判断到K4没按下,便重新检测if(P3_7!=0)//当K4按下时,启动小车前进,如有不明,请看慧净51单片机视频教程goto B; //跳转到标号B,重新检测 } //本实验学习的知识蜂鸣器,注意要在HJ-4WD头文件里定义IO口BUZZ=0;//50次检测K4确认是按下之后,蜂鸣器发出“滴”声响,然后启动小车。delay(50);BUZZ=1;//响50ms后关闭蜂鸣器TMOD=0X01; TH0= 0XFc; //1ms定时 TL0= 0X18; TR0= 1; ET0= 1;EA = 1; //开总中断for(s;s<=10;s++)//有信号为0 没有信号为1{if(s==1){while(1)//无限循环{ //有信号为0 没有信号为1 if(Left_1_led==1&&Right_1_led==1) run(); //调用前进函数 else //右边检测到红外信号 {rightrun(); //调用小车左转函数delay(35); stoprun(); //调用小车停止函数delay(50); run(); //直走delay(150);leftrun();delay(30); //右转23毫秒stoprun(); //调用小车停止函数delay(50); //停止50毫秒 break; }}}if(s==2){while(1)//无限循环{ //有信号为0 没有信号为1 if(Left_1_led==1&&Right_1_led==1)run(); //调用前进函数else{leftrun(); //调用小车右转函数delay(35); stoprun(); //调用小车停止函数delay(50);run(); //直走delay(150); rightrun(); //调用小车左转函数delay(35); stoprun();//调用小车停止函数delay(50); //停止50毫秒 break;}}}if(s==3){while(1)//无限循环{ //有信号为0 没有信号为1if(Left_1_led==1&&Right_1_led==1)run(); //调用前进函数else{rightrun(); //调用小车左转函数delay(35); stoprun(); //调用小车停止函数delay(50); run(); //直走delay(150);leftrun();delay(35); //右转23毫秒stoprun(); //调用小车停止函数delay(50); //停止50毫秒 break; }}} //停止50毫秒}} HJ-4WD#ifndef _LED_H_#define _LED_H_ //定义小车驱动模块输入IO口 sbit IN1=P1^2;sbit IN2=P1^3;sbit IN3=P1^6;sbit IN4=P1^7;sbit EN1=P1^4;sbit EN2=P1^5;/***蜂鸣器接线定义*****/ sbit BUZZ=P2^3; #define Left_1_led P3_5 //左传感器 #define Right_1_led P3_4 //右传感器 #define Left_moto_pwm P1_5 //PWM信号端#define Right_moto_pwm P1_4 //PWM信号端#define Left_moto_go {P1_2=0,P1_3=1;} //左电机向前走#define Left_moto_back {P1_2=1,P1_3=0;} //左边电机向后转#define Left_moto_Stop {P1_5=0;} //左边电机停转 #define Right_moto_go {P1_6=1,P1_7=0;}//右边电机向前走#define Right_moto_back {P1_6=0,P1_7=1;}//右边电机向后走#define Right_moto_Stop {P1_4=0;} //右边电机停转 unsigned char pwm_val_left =0;//变量定义unsigned char push_val_left =0;// 左电机占空比N/20unsigned char pwm_val_right =0;unsigned char push_val_right=0;// 右电机占空比N/20bit Right_moto_stop=1;bit Left_moto_stop =1;unsigned int time=0;/************************************************************************///延时函数 void delay(unsigned int k){ unsigned int x,y; for(x=0;x<k;x++) for(y=0;y<2000;y++);}/************************************************************************///前进 void run(void){ push_val_left=8.99; //速度调节变量 0-20。。。0最小,20最大 push_val_right=8; Left_moto_go ; //左电机往前走 Right_moto_go ; //右电机往前走}//左转 void leftrun(void){ //push_val_left=6; push_val_right=5; Right_moto_go ; //右电机往前走 Left_moto_back; //左电机后退}//右转 void rightrun(void){ push_val_left=5; //push_val_right=6; Left_moto_go ; //左电机往前走 Right_moto_back ; //右电机后退}//停止 void stoprun(void){ push_val_left=0; push_val_right=0; Left_moto_stop ; //左电机停止 Right_moto_Stop ; //右电机停止}/************************************************************************//* PWM调制电机转速 *//************************************************************************//* 左电机调速 *//*调节push_val_left的值改变电机转速,占空比 */void pwm_out_left_moto(void){ if(Left_moto_stop) { if(pwm_val_left=20) pwm_val_left=0; } else { Left_moto_pwm=0;// Left_moto_pwm1=0; }}/******************************************************************//* 右电机调速 */ void pwm_out_right_moto(void){ if(Right_moto_stop) { if(pwm_val_right=20) pwm_val_right=0; } else { Right_moto_pwm=0;// Right_moto_pwm1=0; }}/***************************************************////*TIMER0中断服务子函数产生PWM信号*/void timer0()interrupt 1 using 2{ TH0=0XFc; //1Ms定时 TL0=0X18; time++; pwm_val_left++; pwm_val_right++; pwm_out_left_moto(); pwm_out_right_moto(); }/*********************************************************************/#endif