视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
基于51单片机的红外遥控-自动避障-贴墙行走-人体感应智能小车机器人
2025-10-02 18:37:33 责编:小OO
文档
基于51单片机的红外遥控-自动避障-贴墙行走-人体感应智能小车机器人

队员1

姓名:周葛

学院:仪器科学与电器工程学院 专业:测控技术与仪器

年级:大一

教学号:65130109

邮箱:zhouge94@live.cn

队员2

姓名:成妍

学院:药学院 专业:生物医学工程(再生医学)

年级:大一

教学号:73130430

邮箱:lianyungangcheng@sina.cn

作品类别:基本电子技术应用类

目录

一、引言    1

二、总体设计    1

三、单元电路设计    2

1)单片机最小驱动模块    2

2)红外接收模块    3

方案选择    3

方案确定    3

理论分析与方案论证    3

3)电机驱动模块    4

4)避障循迹贴墙模块    5

方案选择    5

方案确定    5

理论分析与方案论证    6

5)电源模块    7

6)人体感应模块    7

四、软件设计    8

五、整体测试    8

六、结论    9

【参考文献】    9

【附录】    10

源程序    10

一、引言

以STCC52单片机为核心,制作一款红外线遥控小车,小车具有自动驾驶、手动驾驶和循迹前进等功能。自动驾驶时,小车在前进过程中可以自动躲避障碍物。手动驾驶时,可以手动遥控小车前进、后退、左转、右转、加速等操作。寻迹时小车可以按轨迹前进。

红外遥控的特点是利用红外线进行点对点通信的技术,不影响周边环境,不干扰其他电器设备。室内近距离(小于10米),信号无干扰、传输准确度高、体积小、功率低的特点,遥控中得到了广泛的应用。

本系统采用成品红外发射遥控器,具有21个按键,采用NEC红外传输协议。接收端使用1838一体化接受头,通过单片机中断程序处理红外信号。

二、总体设计

本系统由硬件和软件两部分组成。硬件部分由红外线接受电路,控制电路,直流电机驱动,障碍物检测电路,人体感应电路五部分组成,完成红外编码信号的接受,直流电机的驱动,障碍物检测、墙体检测、地面检测,人体感应检测等功能。软件部分主要完成信号的检测和处理、直流电机的控制,障碍物的规避等功能。STCC52单片机主要完成对红外信号解码,判断是否遇到障碍物,判断小车是否离开地面,控制直流电机的正反转、启动、停止、急速减速等工作。系统结构框图如图l所示。

图一

三、单元电路设计

1)单片机最小驱动模块

单片机只有连好最小驱动电路后才会运行存储在其内部的程序。如图二。

单片机最小系统复位电路的极性电容C3的大小直接影响单片机的复位时间,一般采用10~30uF,51单片机最小系统容值越大需要的复位时间越短。

单片机最小系统晶振Y1也可以采用6MHz或者11.0592MHz,在正常工作的情况下可以采用更高频率的晶振,51单片机最小系统晶振的振荡频率直接影响单片机的处理速度,频率越大处理速度越快。

单片机最小系统起振电容C1、C2一般采用15~33pF,并且电容离晶振越近越好,晶振离单片机越近越好。

图二

2)红外接收模块

方案选择

⏹方案1:使用BL9148自制发射电路,使用BL9149接受处理信号。优点是程序简单,缺点增加了电路复杂性。

⏹方案2:使用成品遥控器,遥控器使用CD2025纽扣电池供电,方便携带。接收电路使用红外接收管,自制滤波整合电路对红外信号进行处理。使用在通过单片机中断程序处理解码信号。虽然增加了程序的复杂性,但是简化了电路。

⏹方案3:在方案二的基础上,使用1838一体化接受头代替红外接收管。

方案确定

⏹为提高电路的可靠性,遥控器的便携性,我们选择方案三。

理论分析与方案论证

红外接收电路通常被厂家集成在一个元件中,成为一体化红外接收头。如图三。

内部电路包括红外监测二极管,放大器,限副器,带通滤波器,积分电路,比较器等。红外监测二极管监测到红外信号,然后把信号送到放大器和限幅器,限幅器把脉冲幅度控制在一定的水平,而不论红外发射器和接收器的距离远近。交流信号进入带通滤波器,带通滤波器可以通过30khz到60khz的负载波,通过解调电路和积分电路进入比较器,比较器输出高低电平,还原出发射端的信号波形。注意输出的高低电平和发射端是反相的,这样的目的是为了提高接收的灵敏度。

图三

3)电机驱动模块

使用L298电机驱动模块如图。

此L298模块可以驱动两台直流电机。分别为M1和M2。引脚ENA,ENB可用于输入PWM脉宽调制信号对电机进行调速控制。(如果无须调速可将两引脚接5V,使电机工作在最高速状态,既将短接帽短接)实现电机正反转就更容易了,输入信号端IN1接高电平输入端IN2接低电平,电机M1正转。(如果信号端IN1接低电平, IN2接高电平,电机M1反转。)控制另一台电机是同样的方式,输入信号端IN3接高电平,输入端IN4接低电平,电机M2正转。(反之则反转),PWM信号端A控制M1调速,PWM信号端B控制M2调速。

图四

  

4)避障贴墙模块

方案选择

⏹方案1:使用超声波模块,根据超声波测出的障碍物距离,控制小车规避障碍物,优点反应距离远,抗干扰能力强。缺点体积庞大,且超声波模块只能用于避障,不能用于循迹功能。

⏹方案2:使用红外反射式光耦。前方左右各一个可检测障碍物。底部左右两个可用于循迹,中部左右各一个可用于贴墙走功能。当有障碍物时反射红外光,时红外接收管反向导通性增强,通过一定的电路形成电位变化,输入单片机。

⏹方案3:在方案二的基础上加一个LM393电压比较器,将红外接收管端连续变化的电位信号转化为清晰的高低电平信号。

方案确定

综合设计的实用性,简易性,可靠性,我选择方案三。

理论分析与方案论证

障碍物检测和轨迹检测原理是一样的,其电路如图5所示。从经济的角度考虑,该模块选用了六个反射式光耦,反射式光耦由一个红外发射管和一个光敏三极管组成。LM393P是电压比较器,当3脚的电压大于2脚电压时,输出端1脚输出高电平,反之输出低电平。高低电平的电缝值取决于2脚的电压,调整电位器R23使2脚电压为3V。避障电路安装在小车头部的左右两边,用于检测左右障碍物。工作过程是:当无障碍物时,不反射红外线,光敏i极管截止。3脚在R16的上拉作用下为高电平(5V),大于2脚电压(3V),1脚输出高电平;反之,当遇到障碍物时,l脚输出低电平。左边遇到障碍物时小车右转,右边遇到障碍物时小车左转。

底部地面电路安装在小车底部,当小车处于地面时,地面发射红外线,传感器接收到让小车工作。当小车离开地面时,传感器接收不到信号,小车不工作。

图五

5)电源模块

7805三端稳压集成电路,电子产品中,常见的三端稳压集成电路有正电压输出的78 ×× 系列和负电压输出的79××系列。顾名思义,三端IC是指这种稳压用的集成电路,只有三条引脚输出,分别是输入端、接地端和输出端。

本系统电池采用两节锂电池供电,正常供电电压为7.4v,电机驱动模块使用原始电压,单片机及其他模块采用7805芯片降压稳压至5v供电,调高了系统的稳定性。7805降压稳压模块电路图如图六

图六

6)人体感应模块

本模块采用HC-SR501 人体红外感应模。HC-SR501 是基于红外线技术的自动控制模块,采用德国原装进口LHI778 探头设计,灵敏度高,可靠性强,超低电压工作模式,广泛应用于各类自动感应电器设备。人进入其感应范围则输出高电平,人离开感应范围则自动延时关闭高电平,输出低电平。当小车工作在此模式时,小车工作一段时间自动停止检测车周围是否有人。当没有人时,小车自动进行避障行走;当有人时,自动停止,等待人通过遥控器发出下一步指令。

四、软件设计

程序流程图如图八:

图八

五、整体测试

本设计在调试过程中也遇到很多问题。在后来的调试过程中一一进行了改正与调整。本电路总共设计了14个输入按键。图七是遥控器的功能图七。

手动遥控自动避障贴墙行走
人体感应前进
右转静止左转
后退
加速
差速左拐原速差速右拐
减速
图七

六、结论

经实践表明,本文所设计制作的红外线遥控小车运行稳定、遥控灵敏、占用系统硬件资源少。且在不改变硬件电路,仅通过软件编程小车就可以实现多处障碍物检测、报警等功能。

由于目前的遥控装置大多对某一设备进行单独控制,而在本设计中的红外遥控电路设计了多个控制按键,可以对不同的设备,也可以对同一设备的多个功能进行不同的控制。基本符合技术要求。

本想在底部增加循迹功能,但出于传感器数量有限,底部只剩下两个红外传感器,实现循迹困难。因此改为检查是否离地的功能模块。

但是本遥控电路也有不完善的地方,它只能单通道实现对多个设备的控制,即它不能同时控制两个或者两个以上的设备。

在设计过程中,通过大量的查阅资料,认真研究教材,对单片机有了更为深刻的理解,在设计软件时,须仔细的分析硬件电路,画出程序流程图,培养了我的耐性和刻苦钻研的精神。

【参考文献】

1、《实例解读51单片机完全学习与应用(配教学视频)》,杨欣编著,电子工业出版社。

2、《爱上单片机》,杜洋著,人民邮电出版社。

3、《全国大学生电子设计竞赛教程--基于ti器件设计方法》,黄春根等著,电子工业出版社。

【附录】

源程序

#include

unsigned char IrValue[6];

unsigned char jd1,jd2,m1,m2,count,Time,i,value,flag;

sbit IRIN=P3^2;

sbit pwm1=P2^0;

sbit pwm2=P2^1;

sbit left1=P2^2;

sbit left2=P2^3;

sbit right1=P2^5;

sbit right2=P2^4;

sbit led=P2^6;

sbit person=P2^7;

sbit xia1=P1^2;

sbit xia2=P1^0;

sbit qian1=P1^1;

sbit qian2=P1^3;

sbit hou1=P1^4;

sbit hou2=P1^5;

void IrInit();

void DelayMs(unsigned int );

void Timer0_Init();

void go();

void back();

void turnleft();

void turnleft1();

void turnright();

void turnright1();

void add();

void pluse();

void yaokong();

void bizhang();

void stop();

void stop1();

void main()

  pwm1=0;

  pwm2=0;

  count=0;

  led=1;

  

  jd1=85;//右轮速度初始化取值范围0~200

  jd2=70;//左轮速度初始化取值范围0~200

  IrInit();

  Timer0_Init();

  left1=0;

  left2=0;

  right1=0;

  right2=0;

  qian1=1;

  qian2=1;

  //xia1=0;

  //xia2=0;

  hou1=1;

  hou2=1;

  flag=0;

  //preson=1;

  while(1) 

  {

          while(flag==1)//手动遥控

            {

          if ((xia1==1)|(xia2==1)) stop();

          else if((xia1==0)&(xia2==0))  yaokong();

             } 

           while (flag==2)  //贴墙走

             {

                if ((xia1==1)&(xia2==1)) stop();

                else

                {

                    if ((hou1==1)&(hou2==1))  stop();

                    else if ((hou1==0)&(hou2==1)&((qian1==1)|(qian2==1)))    {go();}

                    else if ((hou1==0)&(hou2==1)&((qian1==0)&(qian2==0))) {turnright();DelayMs(5000);}

                    else if ((hou1==1)&(hou2==0)&((qian1==1)|(qian2==1)))    {go();}

                    else if ((hou1==1)&(hou2==0)&((qian1==0)&(qian2==0))) {turnleft();DelayMs(5000);}

                     }

             }  

           while (flag==3){

            if ((xia1==1)&(xia2==1)) stop();

            else bizhang();}//避障

           while (flag==4)

             {

            if ((xia1==1)&(xia2==1)) stop();

            else 

            {

                if(person==1) bizhang();

                else if(person==0)

                {

                    stop();

                }

             }

             }       

  }}

void Timer0_Init() //函数功能:定时器初始化,每1us执行一次

{

    TMOD=0x01;

    TH0=0xff;//65436/256

    TL0=0x9c;//65436%256

    TR0=1;

    EA =1;        //打开总中断

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

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

}

void Timer0_Int() interrupt 1//中断程序

{

   TH0=0xff;

   TL0=0x9c;

   m1=count;

   m2=count;

if(m1  else pwm1=0;

if(m2  else pwm2=0;

   count++;

   count%=200; //20m秒需要数200次

}

void yaokong()

{

              switch(value)

                {

                        case 0x15:stop();break;    //按键

                        case 0x40:go();break;

                        case 0x19:back();break;

                        case 0x07:turnleft();break;

                        case 0x09:turnright();break;

                        case 0x1c:stop1();break;

                        case 0x08:turnleft1();break;

                        case 0x5a:turnright1();break;

                        default:break;

                }

}

void go()

{

  led=~led;

  left1=0;

  left2=1;

  right1=0;

  right2=1;

  //value=0;

}

void stop()

{

  led=~led;

  left1=0;

  left2=0;

  right1=0;

  right2=0;

  //value=0;

}

void back()

{

  led=~led;

  left1=1;

  left2=0;

  right1=1;

  right2=0;

  //value=0;

}

void turnright()

{

  led=~led;

  left1=1;

  left2=0;

  right1=0;

  right2=1;

  //value=0;

}

void turnright1()

{

  unsigned int j,k;

  j=0;k=0;

while (j<3)

    {

      jd1=jd1-10;

      j++;

    }

  DelayMs(1000);

  while    (k<3)

    {

      jd1=jd1+10;

      k++;

    }

}

void turnleft()

{

  led=~led;

  left1=0;

  left2=1;

  right1=1;

  right2=0;

  //value=0;

}

void stop1(void)

{

  jd1=85;//右轮速度初始化取值范围0~200

  jd2=70;//左轮速度初始化取值范围0~200

}

void turnleft1()

{

  unsigned int m,n;

  m=0;n=0;

while (m<3)

    {

      jd2=jd2-10;

      m++;

    }

  DelayMs(1000);

while (n<3)

    {

      jd2=jd2+10;

      n++;

    }

}

void add()

{

      jd1=jd1+10;

      jd2=jd2+10;

if(jd1>145) jd1=145;

if(jd2>130) jd2=130;

     }

void pluse()

{

      jd1=jd1-10;

      jd2=jd2-10;

if(jd1<65) jd1=65;

if(jd2<50) jd2=50;

     }

void bizhang()

{

  //Timer0_Init();

      if((qian1==1)&(qian2==1)) go();

      else if((qian1==0)&(qian2==0))

      {

       DelayMs(1000);back();DelayMs(800);turnright();DelayMs(800);

      }

      else if((qian1==1)&(qian2==0)) 

      {

          back();DelayMs(1000);turnleft();DelayMs(800);

      }

      else if((qian1==0)&(qian2==1))

      {

          back();DelayMs(1000);turnright();DelayMs(800);

      }

}

void DelayMs(unsigned int x)   //延迟函数,0.14ms误差 0us

{

 unsigned char i;

  while(x--)

 {

for (i = 0; i<13; i++)

 {}

 }

}

void IrInit() // 初始化红外线接收

{

    IT0=1;//下降沿触发

    EX0=1;//打开中断0允许

    IRIN=1;//初始化端口

}

void ReadIr() interrupt 0//读取红外数值的中断函数  返回值value

{

    unsigned char j,k;

    unsigned int err;

    Time=0;                     

    DelayMs(70);

    if(IRIN==0)        //确认是否真的接收到正确的信号

    {     

        

        err=1000;                //1000*10us=10ms,超过说明接收到错误的信号

        /*当两个条件都为真是循环,如果有一个条件为假的时候跳出循环,免得程序出错的时

        侯,程序死在这里*/    

        while((IRIN==0)&&(err>0))    //等待前面9ms的低电平过去          

        {            

            DelayMs(1);

            err--;

        } 

        if(IRIN==1)            //如果正确等到9ms低电平

        {

            err=500;

            while((IRIN==1)&&(err>0))         //等待4.5ms的起始高电平过去

            {

                DelayMs(1);

                err--;

            }

            for(k=0;k<4;k++)        //共有4组数据

            {                

                for(j=0;j<8;j++)    //接收一组数据

                {

                    err=60;        

                    while((IRIN==0)&&(err>0))//等待信号前面的560us低电平过去

//                    while (!IRIN)

                    {

                        DelayMs(1);

                        err--;

                    }

                    err=500;

                    while((IRIN==1)&&(err>0))     //计算高电平的时间长度。

                    {

                        DelayMs(1);//0.14ms

                        Time++;

                        err--;

                        if(Time>30)

                        {

                            EX0=1;

                            return;

                        }

                    }

                    IrValue[k]>>=1;     //k表示第几组数据

                    if(Time>=8)            //如果高电平出现大于565us,那么是1

                    {

                        IrValue[k]|=0x80;

                    }

                    Time=0;        //用完时间要重新赋值                            

                }

            }

            value=IrValue[2];

            switch(value)

              {

                case 0x45:flag=1;led=~led;break;

                case 0x47:flag=2;led=~led;break;

                case 0x46:flag=3;led=~led;break;

                case 0x44:flag=4;led=~led;break;

                case 0x18:add();led=~led;break;

                case 0x52:pluse();led=~led;break;

                default:break;

              }                             //判断模式

        }

    }

}下载本文

显示全文
专题