当前位置:文档之家› 循迹小车课程设计报告

循迹小车课程设计报告

智能循迹小车设计与制作课程设计报告系别:专业:班级:成员:指导老师:时间:二〇一一年6月30日一、设计目的:1、学会智能电子产品的功能设计与任务分析,能进行小型电子产品方案设计;2、掌握基于51单片机、FPGA模数混合硬件系统设计和程序设计;3、熟悉电子信息类企业项目完整的运作过程及管理规范,培养团队协作能力、沟通能力、创新能力和组织能力。

二、智能循迹小车任务分析这是一种基于STC89C51单片机的小车寻迹系统。

该系统采用两组高灵敏度的光电对管,对路面黑色(白色)轨迹进行检测,并利用单片机产生PWM波,控制小车速度。

测试结果表明,该系统能够平稳跟踪给定的路径。

整个系统基于普通玩具小车的机械结构,并利用了小车的底盘、前后轮电机及其自动复原装置,能够平稳跟踪路面黑色轨迹运行三、智能循迹小车循迹原理该智能小车在画有黑线的白纸“路面”上行驶,由于黑线和白纸对光线的反射系数不同,可根据接收到的反射光的强弱来判断“道路”—黑线。

利用了简单、应用比较普遍的检测方法—发光二极管+光敏电阻。

发光二极管+光敏电阻,即利用光线在不同颜色的物理表面具有不同的反射性质的特点。

在小车行驶过程中不断地向地面发射白光,当白光遇到白色地面时发生漫发射,反射光被装在小车上的接收管接收;如果遇到黑线则红外光被吸收,则小车上的接收管接收不到信号。

四、智能循迹小车总体方案整个电路系统分为检测、控制、显示、驱动四个模块。

首先利用光电对管对路面信号进行检测,经过比较器处理之后,送给软件控制模块进行实时控制,然后显示小车的运行状态,输出相应的信号给驱动芯片驱动电机转动,从而控制整个小车的运动。

系统方案方框图如图1所示。

图1 智能小车寻迹系统框图五、智能循迹小车各模块方案1、循迹模块设计方案1:用红外发射管:接收管自己制作光电对管循迹传感器。

红外发射管发出红外线,当发出的红外线照射到白色的平面后反射,若红外接收管能接收到反射回的光线则检测出白线继而输出低电平,若接收不到发射出的光线则测出黑线继而输出高电平。

这样自己制作组装的寻迹传感器基本能够满足要求,但是工作不够稳定,且容易受外界光线的影响,因此我们放弃了这个方案。

方案2:发光二极管+光敏电阻组成光敏探测器,光敏电阻的阻值可以根跟随周围环境光线的变化而变化。

当光线照射到白线上面时,光线发射强烈,光线照射到黑线上面时,光线发射较弱。

因此光敏电阻在白线和黑线上方时,阻值会发生明显的变化。

将阻值的变化值经过比较器就可以输出高低电平。

该方案虽然有明显的光线的车前但灵敏度好。

因此我们采用这种方案。

如理图如下:R61限制发射二极管的电流,发射管的电流和发射功率成正比,但受其极限输入正向电流50mA的影响,用R1=150的电阻作为限流电阻,Vcc=5V 作为电源电压,测试发现发射功率完全能满足检测需要;可变电阻RP61可限制接收电路的电流,一方面保护接收红外管;另一方面可调节检测电路的灵敏度。

因为传感器输出端得到的是模拟电压信号,所以在输出端增加了比较器,先将LM339输出电压与2.5V进行比较,再送给单片机处理和控制。

传感器的安装正确选择检测方法和传感器件是决定循迹效果的重要因素,而且正确的器件安装方法也是循迹电路好坏的一个重要因素。

从简单、方便、可靠等角度出发,同时在底盘装设5个光敏二极管,进行两级方向纠正控制,将大大提高其循迹的可靠性,具体位置分布如图3所示。

图3 光敏电阻的分布图图中循迹传感器全部在一条直线上。

其中X1与Y1为第一级方向控制传感器,X2与Y2为第二级方向控制传感器,并且黑线同一边的两个传感器之间的宽度不得大于黑线的宽度。

小车前进时,始终保持(如图3中所示的行走轨迹黑线)在X1和Y1这两个第一级传感器之间,当小车偏离黑线时,第一级传感器就能检测到黑线,把检测的信号送给小车的处理、控制系统,控制系统发出信号对小车轨迹予以纠正。

第二级方向探测器实际是第一级的后备保护,它的存在是考虑到小车由于惯性过大会依旧偏离轨道,再次对小车的运动进行纠正,从而提高了小车循迹的可靠性。

2、控制模块设计此部分是整个小车运行的核心部件,起着控制小车所有的运行状态作用。

控制方法很多,大部分都采用单片机控制。

这里选择了ATMEL公司的AT89C52作为控制芯片,在芯片体积小、集成度高、可靠性好、容量足够、驱动能力强、运用方便、经济廉价。

3、电机驱动模块从单片机输出信号功率很弱,即使在没有其它外在负载是也无法带动电机,所以在实际电路中我们加入了电机驱动芯片提高输入电机信号的功率,从而能够根据需要控制电机转动。

根据驱动功率大小以及连接电路的简单化要求选择L298为直流电机驱动芯片。

电路图如下:4、FPGA系统软件设计原理图:4.1寻迹模块寻迹板送过来的4路检测信号送到FPGA板,FPGA将此4路信号送出至4个LED灯显示状态(检测至黑线亮,否则灭);同时将此4路信号送到单片机。

显示模块及要求(采用1602)小车启动:小车启动时,显示“Start”。

小车左拐:小车左拐时,显示“Left”。

小车右拐:小车右拐时,显示“Right”。

小车前进:小车前进时,显示“Running”。

小车后退:小车后退时,显示“Back”。

停车:小车停车时,显示“Stop”。

4.2提示音模块(1)小车启动小车启动前发出3声“嘟、嘟、嘟”的声音,提示音结束后,FPGA发出一个启动信号给单片机,从而启动小车。

(2)停车小车停车时,FPGA播放一首音乐,音乐播放结束即表示小车完成了任务。

4.3 FPGA设计总原理图如下:5、单片机控制模块5.1 启动小车小车在接收到FPGA送过来的启动指令后,读取寻迹信号,根据寻迹信号确定小车的运行状态,将小车的运行状态送至FPGA,同时根据相应算法,驱动小车的左右电机前进。

由于其实跑道与正常跑道有一段路程不好处理,所以需要冲一段路程才能使跑到正常轨道。

5.2 正常前进当寻迹板中间两个传感器检测到黑线,小车都正常前进。

5.3 左拐弯当最左端的两个传感器同时检测到黑线,或只有一个检测到黑线时,右端其它传感器检测到白色时,小车应左拐弯。

但是根据跑道要求,当循迹板第一次检测到全黑时,小车应左转。

5.4 右拐弯当最右端的两个传感器检同时测到黑线,或只有一个检测到黑线时,左端其它传感器检测到白色时,小车应右拐弯。

5.5 后退当4个传感器都检测到白色,小车后退。

5.6 停车当4个传感器同时第六次检测到黑线,小车停车。

小车停车后,发出一个停车标志信号送给FPGA,使FPGA播放音乐。

5.7中断模块5.8 电机控制模块5.9 小车速度的PWM调制PWM基本原理PWM是通过控制固定电压的直流电源开关频率,从而改变负载两端的电压,进而达到控制要求的一种电压调整方法。

在PWM驱动控制的调整系统中,按一个固定的频率来接通和断开电源,并根据需要改变一个周期内“接通”和“断开”时间的长短。

通过改变直流电机电枢上电压的“占空比”来改变平均电压的大小,从而控制电动机的转速。

六、心得体会这次循迹小车课程设计不得不说是个大工程,让我们从中学会了许多东西,特别是分工与合作。

从最开始的买元器件,到焊接、调试循迹板,再到FGPA的VHDL程序和C语言程序的编写,都不简单。

我们的循迹板在第一次焊接完毕,经过调试后,能正常工作。

但是,当我们把它装在小车上让它去跑时,问题就来了,有个灯就不亮了。

后来经过检测后,终于又弄好了。

然后在写C 语言时,主要就是调节小车的速度和转弯时的角度。

而最难的是FPGA程序的编写,特别是音乐的编程,真的很复杂,花了我们很多时间才把它写好。

而1602液晶的编写,用到了我们没有学过的状态机,经过查找资料后,才弄清楚状态机到底是什么回事。

由于这次课程设计的工作量很大,所以我们组这次的分工非常明确。

一个人写C语言程序,一个人写VHDL程序,一个人负责循迹板的焊接与调试,还有一个负责资料的收集和报告的书写。

最后,经过我们组的分工协作,终于把循迹小车的制作完成了。

这次课程设计,收获最大的,还是告诉了我们要主动去学习新的知识。

附录一:循迹板原理图附录二:单片机C 语言程序#include<reg52.h>/*********************第一部分 ***************************************/ //以下是点击驱动芯片 L298 管脚位声明sbit PWM1=P1^0; //电机使能端sbit PWM2=P1^1;sbit IN1=P1^2; //电机控制端sbit IN2=P1^3;sbit IN3=P1^4;sbit IN4=P1^5;sbit start=P0^0; //小车启动信号sbit stop=P0^1; //小车停止信号sbit RP1=P2^3; //此处是传感器管脚位声明sbit RP2=P2^2;sbit RP3=P2^1;sbit RP4=P2^0;int count1,count2; //用于中断计数//延时函数,延时z秒void delay(int z){int x,y;for(x=z;x>0;x--)for(y=124;y>0;y--);}/*********************第二部分电机控制子函数****************************/void forward1()//电机 1 前进{IN1=0;IN2=1;}void forward2()//电机 2 前进{IN3=0;IN4=1;}void back1()//电机 1 后退{IN1=1;IN2=0;}void back2()//电机 2 后退{IN3=1;IN4=0;}/***************电机的速度控制用PWM调速************************/ void speed(int cnt1,int sd1,int cnt2,int sd2){if(cnt1<sd1) //电机1 PWM调速PWM1=1;elsePWM1=0;if(cnt2<sd2) //电机2 PWM调速PWM2=1;elsePWM2=0;}/***************电机的前进、左转、右转控制************************/ void turn(int cnt1,int sd1,int cnt2,int sd2){forward1();forward2();speed(cnt1,sd1,cnt2,sd2);}/***************电机的后退控制************************/void back(int cnt1,int sd1,int cnt2,int sd2){back1();back2();speed(cnt1,sd1,cnt2,sd2);}/*********************第三部分主函数****************************/void main(){int num=0;stop=0;TMOD=0x01; //中断模式设置EA=1;TH0=(65536-1000)/256; //定时1msTL0=(65536-1000)%256;ET0=1;TR0=1;start=1; //给FPGA发送START信号delay(3000); //等待FPGA发送循迹信号delay(3000);等待FPGA发送循迹信号start=0;turn(count1,250,count2,250); //使小车冲上黑色轨道delay(350); //延时等待小车冲上黑色轨道while(1){if(RP1==1&&RP2==1&&RP3==1&&RP4==1)back(count1,50,count2,50); // 1111 当四个LED检测到黑线时,小车后退if(RP1==1&&RP2==0&&RP3==0&&RP4==1)turn(count1,200,count2,200); //1001 当第二三格LED检测到黑线时,小车前进if(RP1==0&&RP2==1&&RP3==1&&RP4==0)turn(count1,150,count2,150); // 0110 当第一、三个LED检测到黑线时,小车减速前进/**********************小车左转*****************************/if(RP1==0&&RP2==1&&RP3==1&&RP4==1)turn(count1,0,count2,150); // 0111 当最右边的LED检测到黑线时,小车左转if(RP1==1&&RP2==0&&RP3==1&&RP4==1)turn(count1,80,count2,150); // 1011 当第二个LED检测到黑线时,小车偏左转if(RP1==0&&RP2==0&&RP3==1&&RP4==1)turn(count1,0,count2,100); // 0011 当第一、二个LED检测到黑线时,小车左转if(RP1==0&&RP2==0&&RP3==0&&RP4==1)turn(count1,0,count2,200); // 0001 当第一、二、三个LED检测到黑线时,小车左大转/***********************小车右转*******************************/if(RP1==1&&RP2==1&&RP3==0&&RP4==1)turn(count1,150,count2,80); // 1101 当第三个LED检测到黑线时,小车偏右转if(RP1==1&&RP2==1&&RP3==1&&RP4==0)turn(count1,180,count2,0); // 1110 当第四个LED检测到黑线时,小车右转if(RP1==1&&RP2==1&&RP3==0&&RP4==0)turn(count1,100,count2,0); //1100 当第三四格LED检测到黑线时,小车右转if(RP1==1&&RP2==0&&RP3==0&&RP4==0)turn(count1,200,count2,0); // 1000 当第二、三、四个LED检测到黑线时,小车右大转/**************小车检测到全黑情况的处理----停车与左转----*************/if(RP1==0&&RP2==0&&RP3==0&&RP4==0){if(num==0){back1(); // 0000 当四个LED第一次检测到黑线时,左轮后退,右轮前进小车左转forward2();delay(100); //延时100ms,等待小车转过弯道}if(num>0 && num<6){turn(count1,200,count2,200);// 0000 当四个LED再次检测到黑线的次数小于6次时,// 即到达斑马线时小车前进速度大于后退速度}if(num>=6){PWM1=0;PWM2=0; //当四个LED第六次检测到黑线时,小车停止stop=1; //发送停止信号给FPGA,使FPGA播放音乐}num++;}}}/*********第四部分中断服务函数 *******************************/void time0()interrupt 1{TH0=(65536-1000)/256;//定时1msTL0=(65536-1000)%256;count1++;count2++;if(count1>=500)//周期是 500mscount1=0;if(count2>=500)//周期是 500mscount2=0;}附录三:FPGA的1602液晶VHDL程序library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.STD_LOGIC_ARITH.ALL;use IEEE.STD_LOGIC_UNSIGNED.ALL;--------------------------------------------------------------------------entity LCD1602c isport(CLK,RST : in std_logic; --状态机时钟信号,同时也是液晶时钟信号,其周期应该满足液晶数据的建立时间flag_start,flag_stop:in std_logic; --开始和停止信号,使液晶显示start和stop 并伴随音乐text1:in std_logic_vector(3 downto 0);--将FPGA检测到的数据传给单片机speaker:in std_logic; --音乐的输入端,开始和停止时才播放音乐dududu:in std_logic ; --开vector(3 downto 0); --寻迹板的四路信号输入--始的时候响3次嘟嘟声text1_out:out std_logic_vector(3 downto 0); --将寻迹板的四路信号不做处理直接从FPGA输出给单片机led:out std_logic_vector(5 downto 0);--设置寻迹板的四路信号对应的四个led灯代表其寻迹状态后两个表示开始和停止LCD_EN,LCD_RS,LCD_RW : out std_logic;--使能信号、寄存器选择信号液晶读写信号LCD_Data : out std_logic_vector(7 downto 0) ;--液晶数据信号speaker_out:out std_logic); --音乐输出end LCD1602c;--------------------------------------------------------------------------architecture Behavioral of LCD1602c istype state is (set_cls,set_func,set_DisCon,set_InMode,set_ddram,write_ddram,set_delay); --状态机,7种状态signal C_ST :state; --定义状态信号type ram1 is array(0 to 9) of std_logic_vector(7 downto 0); --type ram2 is array(0 to 9) of std_logic_vector(7 downto 0);type ram3 is array(0 to 9) of std_logic_vector(7 downto 0);type ram4 is array(0 to 9) of std_logic_vector(7 downto 0);type ram5 is array(0 to 9) of std_logic_vector(7 downto 0);type ram6 is array(0 to 9) of std_logic_vector(7 downto 0);constanttextram1:ram1:=(x"80",x"80",x"62",x"61",x"63",x"6B",x"80",x"80",x"80",x"80");--backconstanttextram2:ram2:=(x"74",x"75",x"72",x"6E",x"80",x"72",x"69",x"67",x"68",x"74"); --turn rightconstanttextram3:ram3:=(x"61",x"64",x"76",x"61",x"6E",x"63",x"65",x"80",x"80",x"80"); --advanceconstanttextram4:ram4:=(x"74",x"75",x"72",x"6E",x"80",x"6C",x"65",x"66",x"74",x"80"); --turn leftconstanttextram5:ram5:=(x"80",x"73",x"74",x"61",x"72",x"74",x"80",x"80",x"80",x"80"); --startconstanttextram6:ram6:=(x"80",x"73",x"74",x"6F",x"70",x"80",x"80",x"80",x"80",x"80"); --stopsignal CLK1 : std_logic; --signal cnt1: std_logic_vector(3 downto 0);signal a:std_logic_vector(5 downto 0);--检测信号和开始及停止信号共六位信号-------------------------------------------------------------------------begina<=text1&flag_start&flag_stop;text1_out<=text1;--将四路寻迹板的信号不作处理直接输出给单片机LCD_EN <= CLK ; --LCD_RW <= '0' ; --process(CLK)variable n2:integer range 0 to 499; --常整常量用于从0到500计数分频,可以不要这个进程因为不要循环显示beginif rising_edge(CLK) then --当时钟上升沿到来时if n2<499 thenn2:=n2+1;elsen2:=0; Clk1<=not Clk1;--end if;end if;end process;------------------------------------------------------------------------------PROCESS (CLK,RST)variable cnt1: std_logic_vector(3 downto 0);--32BEGINif RST='0' then C_ST<=set_cls; LCD_RS<='0'; LCD_RW<='0';--rw=0是写操作LCD_Data<="00000001"; cnt1:="0000";--清屏指令0x01elsif (CLK'event AND CLK ='1') THENCASE C_ST IS --判断状态WHEN set_cls => --清屏状态LCD_RS<='0'; LCD_RW<='0'; LCD_Data<="00000001"; --清屏指令0X01C_ST <= set_func; --将功能设置状态给c_st信号WHEN set_func => --功能设置0 0 1 DL N F * * DL:高电平时为8位总线,低电平时为4位总线--N:低电平时为单行显示,高电平时双行显示 F: 低电平时显示5x7的点阵字符,高电平时显示5x10的点阵字符LCD_RS<='0'; LCD_RW<='0'; LCD_Data<="00111000";--cnt1<="00000"; --0x38,表示8位宽度,2行C_ST <=set_DisCon;when set_discon=> --显示开关控制LCD_RS<='0'; LCD_RW<='0'; LCD_Data<="00001100"; --0x0C,表示开显示,关光标,关闪烁C_ST<=set_InMode;when set_InMode=> --设置输入方式LCD_RS<='0'; LCD_RW<='0'; LCD_Data<="00000110";--0x06,AC+1(左移),不移位C_ST<=set_ddram;when set_ddram=>LCD_RS<='0'; LCD_RW<='0';if cnt1<"1001" then cnt1:=cnt1+1; --else cnt1:="0000"; end if; --if cnt1<="1001" then LCD_Data<="10000100"+cnt1; --LCD1602第一行首地址80H+00Hend if;C_ST<=write_ddram;when write_ddram=>LCD_RS<='1'; LCD_RW<='0'; --if a="111001" then LCD_Data<=textram2(conv_integer(cnt1));led<="111000"; --向右elsif a="110001" then LCD_Data<=textram2(conv_integer(cnt1));led<="011100";--向右elsif a="011101" then LCD_Data<=textram4(conv_integer(cnt1));led<="001100";--向左elsif a="001101" then LCD_Data<=textram4(conv_integer(cnt1));led<="110000";--向左elsif a="100101" then LCD_Data<=textram3(conv_integer(cnt1));led<="011000"; --前进elsif a="111101" then LCD_Data<=textram1(conv_integer(cnt1));led<="111100";--后退elsif a="100111" then LCD_Data<=textram5(conv_integer(cnt1));led<="011010";--开始elsif a="000001" then LCD_Data<=textram6(conv_integer(cnt1));led<="111101";--结束end if;C_ST<=set_delay;when set_delay=>LCD_RS<='0'; LCD_RW<='0'; LCD_Data<="00000000"; --C_ST<=set_func; --回到功能设置状态,一直循环下去when others => null;END CASE;END IF;END PROCESS;process(a)begincase(a)iswhen"100110" => speaker_out<=dududu;when"000001"=> speaker_out<=speaker;when others =>speaker_out<='1';end case;end process;end Behavioral;附录五小车实物。

相关主题