小R科技-WIFI机器人网·机器人创意工作室

 找回密码
 立即注册
查看: 15193|回复: 12

原创:5路超声波避障的单片机小车

[复制链接]
发表于 2014-9-6 13:15:24 | 显示全部楼层 |阅读模式
小车用的是52单片机的四驱wifi,两侧电机串联,超声波模块是便宜实用的HC-SR04,本打算再多加几路,可惜模块太占地方,IO口也不多了。

后面附单片机代码,主要实现5路超声波避障(带软PWM),比单纯光电避障模块抗干扰性好,比舵机带超声波方式的响应速度快。避障代码只是用来测试,还可以进一步完善。目前简单测试了一下,对于几厘米细柱和钻不进去的孔洞容易卡住,以及死角要多转一会才能出来。

QQ图片20140906131132.jpg

评分

参与人数 1威望 +2 金钱 +3 贡献 +3 收起 理由
liuviking + 2 + 3 + 3

查看全部评分

回复

使用道具 举报

 楼主| 发表于 2014-9-6 13:16:44 | 显示全部楼层
代码部分:

/***********************************************************************************************************/
//5路超声波避障实验:51单片机 +  HC-SR04超声波
//
/***********************************************************************************************************/
            
     #include <AT89x52.H>                //器件配置文件
         #include <intrins.h>

         #define  RX1  P3_6                   //小车左侧超声波HC-SR04接收端
         #define  TX1  P1_7                   //发送端

     #define  RX2  P3_3                   //左前方超声波
         #define  TX2  P3_2                  

         #define  RX3  P2_4                   //正前方超声波
         #define  TX3  P2_5

         #define  RX4  P3_5                   //右前方超声波
         #define  TX4  P3_4
                                                                                         
         #define  RX5  P3_7                   //右侧超声波
         #define  TX5  P1_6

        #define Left_moto_pwm          P1_5         //PWM信号端
        #define Right_moto_pwm          P1_4          //PWM信号端

//定义小车驱动模块输入IO口
        sbit IN1=P1^0;
        sbit IN2=P1^1;
        sbit IN3=P1^2;
        sbit IN4=P1^3;
        sbit EN1=P1^4;
        sbit EN2=P1^5;

          bit Right_moto_stop=1;
        bit Left_moto_stop =1;

        #define Left_moto_go      {IN1=0,IN2=1,EN1=1;}  //左电机向前走
        #define Left_moto_back    {IN1=1,IN2=0,EN1=1;}         //左边电机向后走
        #define Left_moto_Stop    {EN1=0;}  //左边电机停转                     
        #define Right_moto_go     {IN3=1,IN4=0,EN2=1;}        //右边电机向前走
        #define Right_moto_back   {IN3=0,IN4=1,EN2=1;}        //右边电机向后走
        #define Right_moto_Stop   {EN2=0;}        //右边电机停转


        unsigned char pwm_val_left  =0;//变量定义
        unsigned char push_val_left =0;// 左电机占空比N/20
        unsigned char pwm_val_right =0;
        unsigned char push_val_right=0;// 右电机占空比N/20


                         unsigned int  time=0;
                         unsigned int  timer=0;               
                         unsigned long S1=0;
                         unsigned long S2=0;
                         unsigned long S3=0;
                         unsigned long S4=0;
                         unsigned long S5=0;


       
        void delay_1ms(unsigned char x)          //1ms延时函数,100ms以内可用
        {
        unsigned char i;
        while(x--)
        for(i=124;i>0;i--);
        }


/********************************************************/
       
        void Count1()          //计算左侧超声波距离的函数
        {
         while(!RX1);                //当RX1为零时等待
         TR0=1;                            //开启计数
         while(RX1);                //当RX1为1计数并等待
         TR0=0;                                //关闭计数
         time=TH0*256+TL0;
         TH0=0;
         TL0=0;                          
         S1=(time*1.7)/100;     //算出来是CM         
        }

    void Count2()          //计算函数
        {
         while(!RX2);                //当RX2为零时等待
         TR0=1;                            //开启计数
         while(RX2);                //当RX2为1计数并等待
         TR0=0;                                //关闭计数
         time=TH0*256+TL0;
         TH0=0;
         TL0=0;                                                                         
         S2=(time*1.7)/100;     //算出来是CM                 
        }


         void Count3()          //计算函数
                {
                 while(!RX3);                //当RX1为零时等待
                 TR0=1;                            //开启计数
                 while(RX3);                //当RX1为1计数并等待
                 TR0=0;                                //关闭计数
                 time=TH0*256+TL0;
                 TH0=0;
                 TL0=0;                                         
                 S3=(time*1.7)/100;     //算出来是CM         
                }

         void Count4()          //计算函数
                {
                 while(!RX4);                //当RX1为零时等待
                 TR0=1;                            //开启计数
                 while(RX4);                //当RX1为1计数并等待
                 TR0=0;                                //关闭计数
                 time=TH0*256+TL0;
                 TH0=0;
                 TL0=0;                                                                  
                 S4=(time*1.7)/100;     //算出来是CM               
                }

         void Count5()          //计算函数
        {
         while(!RX5);                //当RX1为零时等待
         TR0=1;                            //开启计数
         while(RX5);                //当RX1为1计数并等待
         TR0=0;                                //关闭计数
         time=TH0*256+TL0;
         TH0=0;
         TL0=0;                                                               
         S5=(time*1.7)/100;     //算出来是CM       
        }



/************************************************************************/
        //前进
        void run(void)
        {
             push_val_left=8;         //左电机调速,速度调节变量 0-20。。。0最小,20最大,四驱大轮>6
                 push_val_right=8;         //右电机调速
                 Left_moto_go ;   //左电机往前走
                 Right_moto_go ;  //右电机往前走                 
        }
/************************************************************************/
        //后退
        void backrun(void)
        {
    push_val_left=8;         
    push_val_right=8;         
        Left_moto_back ; //左电机往前走
        Right_moto_back ; //右电机往前走
        }
/************************************************************************/
        //左转
        void leftrun(void)
        {
    push_val_left=20;         
    push_val_right=20;         
        Left_moto_back ; //左电机往后走
        Right_moto_go ; //右电机往前走
        }
/************************************************************************/
        //右转
        void rightrun(void)
        {
    push_val_left=20;         
    push_val_right=20;
        Left_moto_go ; //左电机往前走
        Right_moto_back ; //右电机往后走
        }
/************************************************************************/
        //停止
        void stoprun(void)
        {
        Left_moto_Stop ; //左电机停
        Right_moto_Stop ; //右电机停
        }




/************************************************************************/
/*                    PWM调制电机转速                                   */
/************************************************************************/

/*                    左电机调速                                        */
/*调节push_val_left的值改变电机转速,占空比            */

                void pwm_out_left_moto(void)
                {
                   if(Left_moto_stop)
                   {
                          if(pwm_val_left<=push_val_left)
                               {
                                     Left_moto_pwm=1;        
                                   }
                             else
                               {
                                 Left_moto_pwm=0;                
                                   }
                        if(pwm_val_left>=20)
                               pwm_val_left=0;
                   }
                   else   
                          {
                           Left_moto_pwm=0;                         
                                  }
                }
/******************************************************************/
/*                    右电机调速                                  */  
           void pwm_out_right_moto(void)
        {
          if(Right_moto_stop)
           {
            if(pwm_val_right<=push_val_right)
                      {
                       Right_moto_pwm=1;   
                           }
                else
                      {
                           Right_moto_pwm=0;   
                          }
                if(pwm_val_right>=20)
                       pwm_val_right=0;
           }
           else   
                  {
                   Right_moto_pwm=0;  
                      }
        }
     


/********************************************************/
     void timer0() interrupt 1                  //T0中断
  {
   
  }

/***************************************************/  
///*TIMER1中断服务子函数产生PWM信号*/

        void timer1()interrupt 3  
{
        TH1=(65536-1000)/256;         //1ms定时
        TL1=(65536-1000)%256;
         timer++;
         pwm_val_left++;
         pwm_val_right++;
         pwm_out_left_moto();
         pwm_out_right_moto();
}
                  

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

        void  main(void)

  {  
    TMOD=0x11;                   //设T0为方式1,GATE=1;
        TH0=0;
        TL0=0;         
        TH1=(65536-1000)/256;         //1ms定时
        TL1=(65536-1000)%256;
        ET0=1;             //允许T0中断
        ET1=1;                           //允许T1中断
        TR1=1;                           //开启定时器
        EA=1;                           //开启总中断

        while(1)
        {
                                         
         TX1=1;                                 //开启超声波1探测
         delay_1ms(1);
         TX1=0;
     Count1();                        //测距                         

         TX2=1;
         delay_1ms(1);
         TX2=0;
     Count2();                       
                               
         TX3=1;
         delay_1ms(1);
         TX3=0;         
           Count3();       
          
         TX4=1;
         delay_1ms(1);
         TX4=0;
     Count4();       
                                          
         TX5=1;
         delay_1ms(1);
         TX5=0;
     Count5();       
                                 
  
                if(S3<20 && S1<20 && S5<20)        //进入狭窄通道
                {
                         backrun();                        //倒车
                }

            else if(S3<20 && S1<S5 ) //车子与障碍物90度垂直,左边距离小右转
                {
                           rightrun();
                }                               
                else if(S3<20 && S5<S1 )        //车子与障碍物90度垂直,右边距离小左转
                {
                        leftrun();
                }  
       
                 else if(S2<20)
                {
                        rightrun(); //车与障碍物呈45度角时,车的左边比车的右边距离小,右转
               
                }                 
                   else if(S4<20)
                {
                        leftrun(); //车与障碍物呈45度角时,车的右边比车的左边距离小,左转   
                }
       
                else
                 {       
                         run();
                 }                 
       
        }
  }
               
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-9-6 13:38:39 | 显示全部楼层
这个代码里面没有加数码管,如果做的话最好每个超声波单独用数码管单片机测试程序测一下,保证都是好的
回复 支持 反对

使用道具 举报

发表于 2014-9-6 17:57:04 | 显示全部楼层
感谢分享!大神我是初学者现在不会用模拟pwm来控制小车速度,您有类似的代码我学习吗
回复 支持 反对

使用道具 举报

发表于 2014-9-7 09:47:56 | 显示全部楼层
光电避障加上声波避障效果是不是会更好呢
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-9-7 10:59:03 | 显示全部楼层
zhcxb 发表于 2014-9-6 17:57
感谢分享!大神我是初学者现在不会用模拟pwm来控制小车速度,您有类似的代码我学习吗

上面已经有PWM了,可以自己搭建环境测试一下
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-9-7 11:05:01 | 显示全部楼层
本帖最后由 wnfc 于 2014-9-7 11:16 编辑
月耀 发表于 2014-9-7 09:47
光电避障加上声波避障效果是不是会更好呢

超声波不受光干扰,光电避障说实话室内光线强一点就没法用了。作为补充,一些超声无法探测的障碍物,如细柱或进入床底之类的难以判断的时候,可以增加高度探测和碰撞开关检测。通常室内小车速度不会非常快,这样避障基本没什么问题了
回复 支持 反对

使用道具 举报

发表于 2014-10-30 22:44:48 | 显示全部楼层
我是新手。问下,超声波可以探测多远的距离,最多可以加到多少组超声波传感器?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-11-1 13:09:00 | 显示全部楼层
jamsung 发表于 2014-10-30 22:44
我是新手。问下,超声波可以探测多远的距离,最多可以加到多少组超声波传感器?

HC-SR04超声模块探测距离在5米以内,只有IO够,理论上加多少组都可以
回复 支持 反对

使用道具 举报

发表于 2014-11-10 21:52:27 | 显示全部楼层
谢谢分享 佛挡杀佛斯蒂芬森
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

新品特惠推荐上一条 /2 下一条

QQ|QQ技术咨询1|QQ技术咨询2|商务合作微信1:xiaorgeek001|商务合作微信2:XiaoRGEEK|诚聘英才|Archiver|手机版|小R科技-WIFI机器人网·机器人创意工作室 ( 粤ICP备15000788号-6 )

GMT+8, 2024-4-29 14:15 , Processed in 1.104226 second(s), 23 queries .

Powered by XiaoR GEEK X3.4

© 2014-2021 XiaoR GEEK

快速回复 返回顶部 返回列表