智能循迹小车设计专业:自动化班级:自动化132姓名:罗植升莫柏源梁桂宾指导老师:2014年4月——2010年6月摘要:本课题是基于STC89C52单片机的智能小车的设计与实现,小车完成的主要功能是能够自主识别黑色引导线并根据黑线走向实现快速稳定的寻线行驶。
小车系统以 STC89C52单片机为系统控制处理器;采用红外传感获取赛道的信息,来对小车的方向和速度进行控制。
此外,对整个控制软件进行设计和程序的编制以及程序的调试,并最终完成软件和硬件的融合,实现小车的预期功能。
引言当今世界,传感器技术和自动控制技术正在飞速发展,机械、电气和电子信息已经不再明显分家,自动控制在工业领域中的地位已经越来越重要,“智能”这个词也已经成为了热门词汇。
现在国外的自动控制和传感器技术已经达到了很高的水平,特别是日本,比如日本本田制作的机器人,其仿人双足行走已经做得十分逼真,而且具有一定的学习能力,还据说其智商已达到6岁儿童的水平。
作为机械行业的代表产品—汽车,其与电子信息产业的融合速度也显著提高,呈现出两个明显的特点:一是电子装置占汽车整车(特别是轿车)的价值量比例逐步提高,汽车将由以机械产品为主向高级的机电一体化方向发展,汽车电子产业也很有可能成为依托整车制造业和用车提升配置而快速成为新的增长点;二是汽车开始向电子化、多媒体化和智能化方向发展,使其不仅作为一种代步工具、同时能具有交通、娱乐、办公和通讯等多种功能。
无容置疑,机电一体化人才的培养不论是在国外还是国内,都开始重视起来,主要表现在大学生的各种大型的创新比赛,比如:亚洲广播电视联盟亚太地区机器人大赛(ABU ROBCON)、全国大学生“飞思卡尔”杯智能汽车竞赛等众多重要竞赛都能很好的培养大学生对于机电一体化的兴趣与强化机电一体化的相关知识。
但很现实的状况是,国内不论是在机械还是电气领域,与国外的差距还是很明显的,所以作为机电一体化学生,必须加倍努力,为逐步赶上国外先进水平并超过之而努力。
为了适应机电一体化的发展在汽车智能化方向的发展要求,提出简易智能小车的构想,目的在于:通过独立设计并制作一辆具有简单智能化的简易小车,获得项目整体设计的能力,并掌握多通道多样化传感器综合控制的方法。
所以立“智能循迹小车”一题作为尝试。
此项设计是在以杨老师提供的小车为基础上,采用AT89C52单片机作为控制核心,实现能够自主识别黑色引导线并根据黑线走向实现快速稳定的寻线行驶。
一、实验目的:通过设计进一步掌握51单片机的应用,特别是在嵌入式系统中的应用。
进一步学习51单片机在系统中的控制功能,能够合理设计单片机的外围电路,并使之与单片机构成整个系统。
二、设计方案:该智能车采用红外传感器对赛道进行道路检测,单片机根据采集到的信号的不同状态判断小车当前状态,通过电机驱动芯片L9110发出控制命令,控制电机的工作状态以实现对小车姿态的控制。
三、报告内容安排:本技术报告主要分为三个部分。
第一部分是对整个系统实现方法的一个概要说明,主要内容是对整个技术原理的概述;第二部分是对硬件电路设计的说明,主要介绍系统传感器的设计及其他硬件电路的设计原理等;第三部分是对系统软件设计部分的说明,主要内容是智能模型车设计中主要用到的控制理论、算法说明及代码设计介绍等。
技术方案概要说明本模型车的电路系统包括电源管理模块、单片机模块、传感器模块、电机驱动模块。
工作原理:利用红外采集模块中的红外发射接收对管检测路面上的轨迹 将轨迹信息送到单片机单片机采用模糊推理求出转向的角度和行走速度,然后去控制行走部分最终完成智能小车可以按照路面上的轨迹运行。
硬件电路的设计1、最小系统:小车采用STC89C52单片机作为控制芯片,图1是其最小系统电路。
主要包括:时钟电路、电源电路、复位电路。
其中各个部分的功能如下:1、时钟电路:给单片机提供一个外接的12MHz的石英晶振。
2、电源电路:给单片机提供5V电源。
3、复位电路:在电压达到正常值时给单片机一个复位信号。
图1 单片机最小系统原理图2、电源电路设计:模型车通过自身系统,采集赛道信息,获取自身速度信息,加以处理,由芯片给出指令控制其前进转向等动作,各部分都需要由电路支持,电源管理尤为重要。
在本设计中,51单片机使用5V电源,电机及舵机使用6V电源。
考虑到电源为充电电池组,额定电压为7.2V,实际充满电后电压则为 6.5-6.8V,所以单片机及传感器模块采用7805稳压后的5V电源供电,舵机及电机直接由电池供电。
3、传感器电路:光电寻线方案一般由多对TCRT5000红外收发管组成,通过检测接收到的反射光强,判断黑白线。
原理图由红外对管和电压比较器两部分组成,红外对管输出的模拟电压通过电压比较器转换成数字电平输出到单片机。
图2 赛道检测原理图:4、电机驱动电路:电机驱动芯片L9110,内部包含4通道逻辑驱动电路。
是一种二相和四相电机的专用驱动器,即内含二个H桥的高电压大电流双全桥式驱动器,接收标准TTL逻辑电平信号,可驱动46V、2A以下的电机。
其引脚排列如图1中U4所示,1脚和15脚可单独引出连接电流采样电阻器,形成电流传感信号。
L9110可驱动2个电机,OUT1、OUT2和OUT3、OUT4之间分别接2个电动机。
5、7、10、12脚接输入控制电平,控制电机的正反转,ENA,ENB接控制使能端,控制电机的停转。
也利用单片机产生PWM信号接到ENA,ENB端子,对电机的转速进行调节。
L9110的逻辑功能:表1 SHARP GP2D12实物图外形及封装:图3 L9110实物图L9110电路原理图:由于一片L298N可以直接驱动两个电机,但是为了加大驱动力,我们采用两路并联的方式来驱动电机。
图3.3 L9110电路图软件系统的实现小车循迹规则:若小车偏左的时候,车轮将向右偏转;若小车偏右,车轮将向左偏转;若没有偏移,小车将继续向前;若小车完全偏离黑色轨迹,小车后退以寻找黑色轨迹。
小车程序:#include <AT89X52.h> //调用51单片机的头文件#include <intrins.h>#include <math.h>#define uchar unsigned char//宏定义#define uint unsigned int//宏定义sbit you1=P1^3;//定义单片机控制右边电机的引脚sbit you2=P1^4;//定义单片机控制右边电机的引脚sbit zuo1=P1^5;//定义单片机控制左边电机的引脚sbit zuo2=P1^6;//定义单片机控制左边电机的引脚sbit z=P1^1;//定义单片机连接循迹板左边光电管的引脚sbit y=P1^0;//定义单片机连接循迹板右边光电管的引脚sbit q=P1^2;//定义单片机连接循迹板前边光电管的引脚sbit chongshua=P3^6;//定义单片机控制冲刷的引脚sbit tuodi=P3^7;//定义单片机控制拖地的引脚//---------------------------------------//1602液晶相关I/O设置sbit E=P2^3; //1602液晶的E脚接在P2.3口上sbit RW=P2^4; //1602液晶的RW脚接在P2.4口上sbit RS=P2^5; //1602液晶的RS脚接在P2.5口上//HC-SR04相关I/O设置sbit TIRG=P3^4; //定义IO口,具体可以去查看原理图sbit ECHO=P3^2; //定义IO口,具体可以去查看原理图bit flag =0;uchar k;uchar a=0;//定义一个变量a,用来读取串口的数据void delay(uint z)//一个带参数的延时程序{int i,j;//定义两个变量for(i=10;i>0;i--)for(j=z;j>0;j--);//将参数z赋值给j}void init()//初始化子程序{TMOD=0x20;//设置定时器T1为工作方式2TH1=0xfd;TL1=0xfd;//T1定时器装初值TR1=1;//启动定时器T1REN=1;//允许串口接收SM0=0;SM1=1;//设置串口工作方式1EA=1;//开总中断ES=1;//开串口中断}void qian()//左右轮协同前进子函数{you1=0;you2=1;zuo1=0;zuo2=1;delay(6);//pwm调速此为pwm有效值you1=1;you2=1;zuo1=1;zuo2=1;delay(4);}void zuo()//左右轮协同左转子函数{you1=0;you2=1;zuo1=1;zuo2=0;delay(9);//pwm调速此为pwm有效值you1=1;you2=1;zuo2=1;delay(1);}void mzuo()//左右轮协同左转子函数{you1=0;you2=1;zuo1=1;zuo2=0;delay(10);//pwm调速此为pwm有效值you1=1;you2=1;zuo1=1;zuo2=1;delay(5);}void you()//左右轮协同右转子函数{you1=1;you2=0;zuo1=0;delay(9);//pwm调速此为pwm有效值you1=1;you2=1;zuo1=1;zuo2=1;delay(1);}void myou()//左右轮协同右转子函数{you1=1;you2=0;zuo1=0;zuo2=1;delay(10);//pwm调速此为pwm有效值you1=1;you2=1;zuo1=1;zuo2=1;delay(5);}void hou()//左右轮协同前进子函数{you1=1;you2=0;zuo1=1;zuo2=0;delay(9);//pwm调速此为pwm有效值you1=1;you2=1;zuo1=1;zuo2=1;delay(1);}void ting()//左右轮都停止转动{you1=1;you2=1;zuo1=1;zuo2=1;}void Delay1602(unsigned int t){unsigned int k; //定义一个16位寄存器用来做延时用for(k=0;k<t;k++); //延时}void LCD1602_busy(void){P0_7=1; //将P0.7置1,为读状态做准备RS=0; //RS=0、RW=1、E=1时,忙信号输出到DB7,由P0.7读入RW=1; //RS=0、RW=1、E=1时,忙信号输出到DB7,由P0.7读入E=1; //RS=0、RW=1、E=1时,忙信号输出到DB7,由P0.7读入while(P0_7==1); //由P0.7读入1,表示1602液晶忙,需要等待 E=0; //读完以后,恢复E的电平}void LCD1602_Write_com(unsigned char combuf){RS=0; //选择指令寄存器RW=0; //选择写状态P0=combuf; //将命令字通过P0口送至DBE=1; //E高电平将命令字写入1602液晶 E=0; //写完以后,恢复E的电平}void LCD1602_Write_com_busy(unsigned char combuf){LCD1602_busy(); //调用忙检测函数LCD1602_Write_com(combuf); //调用忙检测函数}void LCD1602_Write_data_busy(unsigned char databuf){LCD1602_busy(); //调用忙检测函数RS=1; //选择数据寄存器RW=0; //选择写状态P0=databuf; //将命令字通过P0口送至DBE=1; //E高电平将命令字写入1602液晶E=0; //写完以后,恢复E的电平}void LCD1602_Write_address(unsigned char x,unsigned char y){x&=0x0f; //列地址限制在0-15间y&=0x01; //行地址限制在0-1间if(y==0) //如果是第一行LCD1602_Write_com_busy(x|0x80); //将列地址写入else //如果是第二行LCD1602_Write_com_busy((x+0x40)|0x80); //将列地址写入}void LCD1602_init(void){Delay1602(1500); //调用延时函数LCD1602_Write_com(0x38); //8位数据总线,两行显示模式,5*7点阵显示Delay1602(500); //调用延时函数LCD1602_Write_com(0x38); //8位数据总线,两行显示模式,5*7点阵显示Delay1602(500); //调用延时函数LCD1602_Write_com(0x38); //8位数据总线,两行显示模式,5*7点阵显示LCD1602_Write_com_busy(0x38); //8位数据总线,两行显示模式,5*7点阵显示LCD1602_Write_com_busy(0x08); //显示功能关,无光标LCD1602_Write_com_busy(0x01); //清屏LCD1602_Write_com_busy(0x06); //写入新的数据后,光标右移,显示屏不移动LCD1602_Write_com_busy(0x0C); //显示功能开,无光标}void LCD1602_Disp(unsigned char x,unsigned char y,unsigned char buf) {LCD1602_Write_address(x,y); //先将地址信息写入LCD1602_Write_data_busy(buf); //再写入要显示的数据}void Timer0(void) interrupt 1{flag=0;}void xunji(){qian();//调用前进子函数,使小车光电管不满足以下几个条件时都处于前进状态while((z==0)&&(y==1)&&(q==1))//判断当左边光电管遇到黑线,{ //右边和前边的光电管遇到白线时左转zuo();//调用左转函数zd=1;}while((z==1)&&(y==0)&&(q==1))//判断当右边光电管遇到黑线,{ //左边和前边的光电管遇到白线时右转you();//调用右转函数yd=1;}while((z==0)&&(y==0)&&(q==1))//判断当左边光电管遇到黑线,右边光电管也遇到黑线{ //前边的光电管遇到白线时停止ting();//调用停止函数hd=1;}while((z==0)&&(y==0)&&(q==0))//判断当左边、右边、前边光电管同时遇到黑线{ //即遇到十字路口,小车前进qian();//调用前进函数}}void csb(){long S;unsigned int i;unsigned int Timeout;LCD1602_init(); //调用1602液晶初始化函数//***定时器Timer0初始化***TMOD&=0xF0; //将TMOD的低4位定时器0控制部分清零TMOD|=0x01; //设置定时器0为方式1TMOD=0x01;TL0=0; //设置定时器0初值低8位TH0=0; //设置定时器0初值高8位TR0=0; //停止定时器0ET0=1; //Timer0中断允许//***开全局中断设置****//定时器Timer0设置了中断允许,此处要开全局中断EA=1; //开全局中断TIRG=1; //发一个脉冲触发信号i=4; //维持约17US,符合不低于10US的要求while(i>0) //维持约17US,符合不低于10US的要求 i--; //维持约17US,符合不低于10US的要求TIRG=0; //撤销触发信号TR0=0; //关闭定时器TL0=0; //设置定时器0初值低8位为0 TH0=0; //设置定时器0初值高8位为0k=0; //清除溢出标志flag=0;Timeout=0;while((ECHO==0)&&((Timeout++)<50000)); //等待回响高电平TR0=1; //回响高电平来后启动定时器Timeout=0;while((ECHO==1)&&((Timeout++)<50000)); //等待回响高电平结束后TR0=0; //关闭定时器S=((TH0*256+TL0)*1)/58;if(flag==1||S>400) //超出测量范围显示“-”{LCD1602_Disp(0, 0, '-'); //显示百位-LCD1602_Disp(1, 0, '-'); //显示十位-LCD1602_Disp(2, 0, '-'); //显示个位-LCD1602_Disp(3, 0, 'C'); //显示CLCD1602_Disp(4, 0, 'M'); //显示M}else{LCD1602_Disp(0, 0, S%1000/100+'0'); //显示百位LCD1602_Disp(1, 0, S%1000%100/10+'0'); //显示十位LCD1602_Disp(2, 0, S%1000%100%10+'0'); //显示个位LCD1602_Disp(3, 0, 'C'); //显示CLCD1602_Disp(4, 0, 'M'); //显示M}i=18000; //维持约77400US,符合不低于60MS的要求 while(i>0) //维持约77400US,符合不低于60MS的要求i--; //维持约77400US,符合不低于60MS的要求}void main()//主程序{init();//调用初始化子程序while(1)//死循环{switch(a)//判断a从串口读取到的数据{case 0x00://如果是0x1f就前进xunji();break;case 0x01://如果是0x2f就后退qian();break;case 0x02://如果是0x3f就左转break;case 0x03://如果是0x4f就右转mzuo();zd=1;break;case 0x04://如果是0x00就停止hou();break;case 0x05://如果是0xa0车灯打开myou();yd=1;break;case 0x06://如果是0xb0车灯关闭chongshua=1;break;case 0x07://如果是0xc0蜂鸣器鸣响hd=1;break;case 0x08://如果是0xc0蜂鸣器鸣响tuodi=1;break;}}}void chuan() interrupt 4//串口中断服务程序{RI=0;//软件清除串口响应a=SBUF;//读取单片机串口接受的蓝牙模块发送的数据}结论根据本次设计要求,我们小组系统地阅读了大量的资料,并认真分析了设计课题的需求,还系统学习了51系列单片机的工作原理及其使用方法,并独自设计智能小车的整个项目。