原创 盛方跟我学做智能车第三节 黑白线循迹实验

2010-2-24 17:41 3242 4 4 分类: MCU/ 嵌入式

第三节 小车循迹实验


一、实验原理:


       本实验采用直流不调制反射式的红外光电传感器,循迹光电传感器原理,利用黑白线对红外线不同的反射能力。然后通过光敏二极管或光敏三极管,接收反射回的不同光强信号,把不同光强转换为电流信号,最后通过电阻,转换为单片机可识别的高低电平。光电传感器实现循迹的基本电路如图4所示。


201021211483843292.jpg


图4  循迹传感器基本电路


       电路解释:TC端是传感器工作控制端,为高电平时,发光二极管不工作,传感器休眠,为低电平时,传感器启动。Signal端为检测信号输出,当遇到黑线,黑线吸收大量的红外线,


反射的红外线很弱,光敏三极管不导通,signal输出高电平,当遇到白线,与黑线相反,反射的红外线很强,使光敏三极管导通,signal输出低电平。


二、实验接线:


       VCC接5V电源,GND接单片机逻辑地,左边传感器的signal接51单片机P1^0,右边传感器的signal接51单片机P1^1,参照图5。


201021211483841443.jpg


图5  循迹传感器连接图


三、实验任务:


1、调整左右传感器之间的距离,两探头距离约等于黑线宽度最合适,一般黑线宽度选择范围为3 – 5 厘米比较合适。注意:该传感器的灵敏度是可调的,偶尔传感器遇到黑线却不能送出相应的信号,通过调节传感器上的可调电阻,适当的增大或减小灵敏度。另外,循迹传感器的安放也算是比较有讲究的,有两种方法,一种是两个都是放置在黑线内侧但紧贴黑线边缘,第二种是都放置在黑线的外侧,同样紧贴黑线边缘。本实验采用第二种方法。


2、编写程序实现小车能沿着黑线走,不要让小车偏离黑线。当小车先前前进时,如果向左偏离了黑线。那么右边传感器会产生一个低电平,单片机判断这个信号,然后向右拐。回到黑线后。两传感器输出信号为高电平。小车前进。如果小车向右偏离黑线,左边传感器产生一个低电平,单片机判断这个信号,然后向左拐。如此如此,小车必不偏离黑线。


四、实验源程序:


/*******************************************************************


 


 公司名称:盛方单片机


 公司网址:www.sfmcu.com


 模块名称:006.c


 功    能:小车循迹。           


 说    明:通过定时器0产生PWM调速。


 程序设计:tongwei     


 设计时间:2009.09.15       


 版 本 号:


*********************************************************************/


#include< reg52.h >


 


#define uchar unsigned char


#define uint unsigned int


 


#define MOTOR_C P0                  //P0口作为电机的控制口。


#define SIGNAL P1                   //P2口的低两位为循迹传感器输入口。


#define SHELVES 25                  //速度总档数。


 


#define BACK 0xC6                   //后退


#define FORWARD 0xA5                //前进


 


sbit PWM_R = P0^7;                  //右电机PWM输入口


sbit PWM_L = P0^2;                  //左电机PWM输入口


 


void timer_init( void );            //定时器初始化函数。


void right( void );                 //右转弯函数。


void left( void );                  //左转弯函数。


void forward( void );               //前进函数。


 


uchar percent_l = 0;                //左轮占空比


uchar percent_r = 0;                //右轮占空比


uchar run_time = 0;                 //车轮运行一步的时间


 


/********************************************************************


 


 函 数 名:timer_init()


 功    能:初始化定时器0


 说    明:无


 入口参数:无


 返 回 值:无 


 设    计:tongwei           日    期:2009.09.15


 修    改:                  日    期:


***********************************************************************/


void timer_init( void )


{


    TMOD = 0x02;                //定时器0工作在方式2,定时值自动重载,启动仅受TR0的控制。


    TH0 = 256 - 200;            //定时周期为 200us * SHELVES


    TL0 = 256 - 200;


 


    EA = 1;                     //开总中断。


    ET0 = 1;                    //开定时器0中断。


    TR0 = 1;                    //启动定时器0。


}


 


/********************************************************************


 


 函 数 名:right()


 功    能:小车右转


 说    明:通过控制左右轮不同的占空比,实现左右转。


 入口参数:无


 返 回 值:无 


 设    计:tongwei           日    期:2009.09.15


 修    改:                  日    期:


***********************************************************************/


void right( void )


{


//  timer_init();               //初始化定时器0。


    MOTOR_C = FORWARD;          //方向向前


    percent_r = 1;              //右轮速度慢。


    percent_l = 4;              //左轮速度快。


}


 


/********************************************************************


 


 函 数 名:left()


 功    能:小车左转


 说    明:通过控制左右轮不同的占空比,实现左右转。


 入口参数:无


 返 回 值:无 


 设    计:tongwei           日    期:2009.09.15


 修    改:                  日    期:


***********************************************************************/


void left( void )


{


//  timer_init();               //初始化定时器0。


    MOTOR_C = FORWARD;          //方向向前


    percent_r = 4;              //右轮速度快。


    percent_l = 2;              //左轮速度慢。


}


 


/********************************************************************


 


 函 数 名:forward()


 功    能:小车前进


 说    明:


 入口参数:无


 返 回 值:无 


 设    计:tongwei           日    期:2009.09.15


 修    改:                  日    期:


***********************************************************************/


void forward( void )


{


//  timer_init();               //初始化定时器0。


    MOTOR_C = FORWARD;          //方向向前


    percent_r = 3;              //右轮同速度。


    percent_l = 3;              //左轮同速度。


}


 


/********************************************************************


 


 函 数 名:stop()


 功    能:停车


 说    明:


 入口参数:无


 返 回 值:无 


 设    计:tongwei           日    期:2009.09.15


 修    改:                  日    期:


***********************************************************************/


void stop( void )


{


//  timer_init();               //初始化定时器0。


    MOTOR_C = FORWARD;          //方向向前


    percent_r = 0;              //右轮零速度。


    percent_l = 0;              //左轮零速度。


}


 


/********************************************************************


 


 函 数 名:uchar check_sig()


 功    能:检测信号,并返回信号代码。


 说    明:


 入口参数:无


 返 回 值:无 


 设    计:tongwei           日    期:2009.09.15


 修    改:                  日    期:


***********************************************************************/


uchar check_sig( void )


{


    uchar temp = 0;


    temp = SIGNAL & 0x03;       //信号输入口就只有低两位,得到信号码。


    return temp;


}


 


/********************************************************************


 


 函 数 名:tack()


 功    能:实现循迹功能。


 说    明:对采集的信号进行分析,转换为对电机的控制。


 入口参数:无


 返 回 值:无 


 设    计:tongwei           日    期:2009.09.15


 修    改:                  日    期:


***********************************************************************/


void track( void )


{


    uchar sig = 0;              //存储采集的信号


    timer_init();               //初始化定时器0


    while( 1 )


    {


        run_time = 0;           //清计时器,重新开始。


        sig = check_sig();      //存储信号码


        switch( sig )


        {


            case 0:             //两探头都没检测到信号。


                forward();


                break;


            case 1:             //右边检测到信号。


                right();


                break;


            case 2:             //左边检测到信号。


                left();


                break;


            case 3:             //两边同时检测到信号。


                stop();


                break;


            default:


                break;


        }


        while(run_time < 3);    //运行一步,时间为 3*5ms


    }


}


 


/********************************************************************


 


 函 数 名:timer_zero()


 功    能:定时器0中断服务函数


 说    明:无


 入口参数:无


 返 回 值:无 


 设    计:tongwei           日    期:2009.09.15


 修    改:                  日    期:


***********************************************************************/


void timer_zero( void ) interrupt 1


{


    static uchar temp = 0;                  //中断次数计数,


 


    EA = 0;                                 //关总中断,屏蔽其他中断。


 


    if(temp < SHELVES)                      //高电平保持时间。


    {          


        if(temp < percent_l)


        {


            PWM_L = 1;                      //左电机高电平


        }


        else


        {


            PWM_L = 0;                      //左电机低电平


        }


 


        if(temp < percent_r)


        {


            PWM_R = 1;                      //右电机高电平


        }


        else


        {          


            PWM_R = 0;                      //右电机低电平


        }


 


        temp ++;                            //实现计数


    }


    else                                    //一个PWM周期结束,计数清零。


    {


        temp = 0;


        run_time++;


    }      


 


    EA = 1;                                 //开总中断。


}


 


/********************************************************************


 


 函 数 名:main()


 功    能:


 说    明:


 入口参数:无


 返 回 值:无 


 设    计:tongwei           日    期:2009.09.15


 修    改:                  日    期:


***********************************************************************/


void main( void )


{


    track();


}

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
4
关闭 站长推荐上一条 /3 下一条