找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2514|回复: 8
打印 上一主题 下一主题
收起左侧

单片机黑线寻迹小车程序,如何快速识别黑线,无延迟切换转弯?

[复制链接]
跳转到指定楼层
楼主
ID:582255 发表于 2022-4-8 08:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
程序功能:红外寻迹小车,跑道为黑色,其他地方为白色。左右两个红外传感器,当传感器在黑线上时,没有反射光进入传感器,判断压线,左边压线就左转,反之右转。
实际效果:小车右边检测到黑线后不能马上右转,而是前进一下,前进后就脱离了跑道,不能再寻迹。
用KEIL单步调试时发现,如果直行时遇到了左右传感器检测到信号后,没有马上转弯,而是反复执行了上一个状态的前进函数,这就导致了在寻迹时不能马上转弯。请问一下如何快速检测、快速切换前进状态?主函数在下面

单片机源程序如下:
  1. #include<AT89X52.H>                  //包含51单片机头文件,内部有各种寄存器定义
  2. #include<ZY-4WD_PWM.H>                  //包含IO口定义等函数

  3. #define uchar unsigned char
  4. #define uint  unsigned int

  5. sbit pwm=P1^6;//PWM信号输出口  舵机信号输出口


  6. unsigned char n,count,angle;//距离标志位,0.5ms次数,角度标识

  7. uchar i;
  8. void DelayUs2x(uchar t)
  9. {   
  10.         while(--t);
  11. }
  12. void DelayMs(uchar t)
  13. {
  14.         while(t--)
  15.         {
  16.             //大致延时1mS        
  17.                 DelayUs2x(245);
  18.             DelayUs2x(245);
  19.         }
  20. }



  21. /*------------------------------------------------
  22.                     定时器01初始化
  23. //定时器1工作方式1 (舵机 ),定时器0 电机PWM调速控制信号
  24. ------------------------------------------------*/


  25. void Time1_Int() interrupt 3//舵机
  26. {
  27.         TH1=0xfe;         //0.5ms初值
  28.         TL1=0x33;         
  29.         if(count<angle)//判断0.5ms次数是否小于角度标识
  30.     pwm=1;//确实小于,pwm输出高电平
  31.     else
  32.     pwm=0;//大于则输出低电平
  33.         count++;//0.5ms次数加1
  34.         count=count%40;//次数始终保持为200即保持周期为20ms
  35.         //if(count>=20)count=0;
  36. }


  37. //主函数
  38.         void main(void)
  39. {        

  40.           angle=3;//舵机居中
  41.     count=0;
  42.     P0=0XF0;   //关电机        


  43. /*        
  44. B:                for(i=0;i<50;i++) //判断S4是否按下
  45.                 {
  46.                    delay(1);        //1ms内判断50次,如果其中有一次被判断到K4没按下,便重新检测
  47.                    if(P3_2!=0)//当S4按下时,启动小车前进.

  48.                    goto B; //跳转到标号B,重新检测  
  49.                 }
  50. */
  51.         //本实验学习的知识蜂鸣器,注意要在HJ-4WD头文件里定义IO口
  52.                      BUZZ=0;        //50次检测K4确认是按下之后,蜂鸣器发出“滴”声响,然后启动小车。
  53.                delay(50);
  54.                BUZZ=1;//响50ms后关闭蜂鸣器

  55.                          TMOD=0X11;
  56.                 TH0= 0XFc;                  //1ms定时
  57.                  TL0= 0X66;
  58.                    TR0= 1;
  59.                 ET0= 1;
  60.                 EA = 1;                           //开总中断

  61.                 TH1=0xfe;        //0.5ms
  62.                 TL1=0x33;         
  63.                         ET1=1;
  64.                         TR1= 1;
  65.         


  66.         while(1)        //无限循环
  67.         {
  68. //有信号为0  没有信号为1
  69.                  
  70.          
  71.                          //有信号为0  没有信号为1

  72.               if(Left_1_led==1&&Right_1_led==1)

  73.                           {
  74.                        run();
  75.                       angle=3 ;
  76.                       } //调用前进函数

  77.                           else
  78.                          {                          
  79.                                                if(Left_1_led==1 && Right_1_led==0)            //左边检测到黑线
  80.                                   {
  81.             angle=4;
  82.                                           leftrun();                  //调用小车左转  函数
  83.                                           for(time=0;time<100;time++);

  84.                              }
  85.                            
  86.                                                              if(Left_1_led==0 && Right_1_led==1)                //右边检测到黑线
  87.                                   {         
  88.                                       angle=2;
  89.                                                   rightrun();                   //调用小车右转        函数
  90.               for(time=0;time<100;time++);
  91.                                   }


  92.                         }         
  93.          
  94.                                  
  95.          }
  96. }
复制代码

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:855733 发表于 2022-4-8 09:19 | 只看该作者
调一下传感器的灵敏度?试试用switch case?
回复

使用道具 举报

板凳
ID:582255 发表于 2022-4-8 09:27 | 只看该作者
头文件:
#ifndef _LED_H_
#define _LED_H_


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

        /***蜂鸣器接线定义*****/
    sbit BUZZ=P0^6;

    #define Left_1_led      P3_5         // 左传感器      
        #define Right_1_led       P3_6         //右传感器  
       
        #define PWMSD            5         ////速度调节变量 0-20。。。0最小,20最大
            
        #define Left_moto_pwm          P0_4         //PWM信号端 ,EN1
        #define Right_moto_pwm          P0_5          //PWM信号端,EN2


        #define Left_moto_go      {P0_0=1,P0_1=0;}  //左电机向前走
        #define Left_moto_back    {P0_0=0,P0_1=1;}         //左边电机向后转
        #define Left_moto_Stop    {P0_4=0;}  //左边电机停转                     
        #define Right_moto_go     {P0_2=1,P0_3=0;}        //右边电机向前走
        #define Right_moto_back   {P0_2=0,P0_3=1;}        //右边电机向后走
        #define Right_moto_Stop   {P0_5=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
        bit Right_moto_stop=1;
        bit Left_moto_stop =1;
        unsigned  int  time=0;
   
/************************************************************************/       
//延时函数       
   void delay(unsigned int k)
{   
     unsigned int x,y;
         for(x=0;x<k;x++)
           for(y=0;y<2000;y++);
}
/************************************************************************/
//前速前进
     void  run(void)
{
     push_val_left=PWMSD;         //速度调节变量 0-20。。。0最小,20最大
         push_val_right=PWMSD;
         Left_moto_go ;   //左电机往前走
         Right_moto_go ;  //右电机往前走
}
    void stop(void)
                {
                                                Left_moto_Stop;
                                          Right_moto_Stop;
                }

//左转
     void  leftrun(void)
{         
   push_val_left=PWMSD;
         push_val_right=PWMSD;
         Right_moto_go ;  //右电机往前走
     Left_moto_back   ;  //左电机后走
}

//右转
     void  rightrun(void)
{
         push_val_left=PWMSD;
         push_val_right=PWMSD;
     Left_moto_go  ;   //左电机往前走
         Right_moto_back    ;  //右电机往后走       
}


/************************************************************************/
/*                    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;

              }
}
      
/***************************************************/
///*TIMER0中断服务子函数产生PWM信号*/
        void timer0()interrupt 1   using 2
{
     TH0=0XFc;          //1ms定时
         TL0=0X66;
         time++;
         pwm_val_left++;
         pwm_val_right++;
         pwm_out_left_moto();
         pwm_out_right_moto();
}       

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

#endif
回复

使用道具 举报

地板
ID:844772 发表于 2022-4-8 11:17 | 只看该作者
我一般根据情况使用下面方法:1、减慢车速,足够慢,就不会错过;2、加延时,其实你已经加了,就是加的太少了就是这句,for(time=0;time<100;time++);多加点,这个必须要调试的,而且跟电量有关,最好你能检测电源电压做个变量加到延时中。当然这种硬延时不大好,我喜欢加标志变量延时的,不影响路线检测;3、改控制策略,比如左压线后,要左转到右压线为止(记得要去掉上面的延时)。或者左压线左转到再次左压线等这个也要测一下的。4、我觉得你最应该的是多上几个红外,使用pid控制,就能跑得飞快,要不搞舵机干啥。
回复

使用道具 举报

5#
ID:582255 发表于 2022-4-8 11:25 | 只看该作者
感谢PID控制是个好方法啊。
如果我把速度调慢,怎么调啊?调pwm=P1^6这个的占空比吗
回复

使用道具 举报

6#
ID:844772 发表于 2022-4-8 12:08 | 只看该作者
aktuan007 发表于 2022-4-8 11:25
感谢PID控制是个好方法啊。
如果我把速度调慢,怎么调啊?调pwm=P1^6这个的占空比吗

你那个显然是舵机啊,你程序不全,感觉是count=count%40;在调占空比。看你的提问,觉得你先加延时,去试车比较好。
回复

使用道具 举报

7#
ID:161164 发表于 2022-4-8 13:12 | 只看该作者
if(Left_1_led==1 && Right_1_led==0)            //左边检测到黑线
0=压线
Right_1_led==0 是右压线吧?

舵机是干什么用的?
中断内time为什么要++?
回复

使用道具 举报

8#
ID:123289 发表于 2022-4-8 13:44 | 只看该作者
比较一下:
你在黑夜开近光灯与开远光灯拐弯的情形,你远光灯会好一些!速度慢会好一些!
其实关键点是:有足够的预判时间!
假设从你决定拐弯开始到完成拐弯,需要两秒钟的时间。那么你的预判时间就是两秒!
所以,完成命题的需求是,传感器必须在2秒之前得到拐弯信息!
大多数人认为拐弯需要减速,看上去是对的。其实关键点是:以低于最小的安全拐弯速度拐弯就可以了。
你要注意以下几点:
1、最小拐弯速度。(道路环境条件相关)
2、完成拐弯的时间。(以当前速度、制动能力相关)
3、小车行进的速度。(与在何处开始起动拐弯程序相关)
4、依据1、2、3、计算出开始拐弯动作的起点在哪里。这个点,距拐弯点的距离,就是小车传感器必须能探知的点(提前预判)!
余下的事,可参考其它人支着。
回复

使用道具 举报

9#
ID:844772 发表于 2022-4-8 14:49 | 只看该作者
aktuan007 发表于 2022-4-8 11:25
感谢PID控制是个好方法啊。
如果我把速度调慢,怎么调啊?调pwm=P1^6这个的占空比吗

之前没看到你后来发的程序。 你已经定义速度了啊,#define PWMSD            5         ////速度调节变量 0-20。。。0最小,20最大
改一下就行了,但这个不是线性调整的,太小估计就走不动了。我觉得你程序很奇怪,明明用了舵机转弯,为啥还要用电机差动转弯呢,电机转弯效率低啊。还有中断内的time要删掉,你应该增加主程序for循环产生的延时才对。你用的是什么底盘,配置的不太合理啊。
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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