直角转弯4驱差动小车的设计思想

本文介绍五路循迹模块的使用方法,包括通过不同数值组合判断车辆行驶状态及复杂路况,如十字路口、T型路口等,并给出具体实现代码示例。

  使用五路循迹模块可以识别比较复杂的路况,比如十字路口,T型路口,以及没有路了。
  首先,要有一个扫描路况的函数,这个函数要有唯一的函数出口。在扫描函数里边要包括五路的循迹情况,也就是说执行一次扫描函数,就要知道(几乎)同一时间内五个循迹模块的情况。可以使用这种办法:给每一个循迹模块定一个值,五个模块分别是abcde,要求任意的值,不是其他任意若干个值的和。举个栗子

#define SIG_MID  1//中间  
#define SIG_LEFT  10//左转
#define SIG_RIGHT 20//右转
#define SIG_LEFT_LITTLE  2//中左
#define SIG_RIGHT_LITTLE  4//中右

  这是一个示意图(俯视图)
这里写图片描述
  圆圈表示某个红外循迹模块,数字是它的值。以下是扫描函数的示例

char SearchSignal(void)//检测循迹模块的情况
{
    char CMD_back = 0;//用于返回检测到的信号

    if(SEARCH_M_IO == WHITE_AREA)
    {
        CMD_back += SIG_MID;
    }

    if(SEARCH_ML_IO == WHITE_AREA)
    {
        CMD_back += SIG_LEFT_LITTLE;
    }

    if(SEARCH_MR_IO == WHITE_AREA)
    {
        CMD_back += SIG_RIGHT_LITTLE;
    }
    if(SEARCH_L_IO == WHITE_AREA)
    {
        CMD_back += SIG_LEFT;
    }
    if(SEARCH_R_IO == WHITE_AREA)
    {
        CMD_back += SIG_RIGHT;
    }
    return CMD_back;//用累加的方法得到一个唯一值,可方便处理,提升效率
}

  如果扫描的结果返回3就是中和中左一起扫描到了白线(默认黑路白线)
  如果扫描的结果返回25就是中和中右,最右一起扫描到了白线
  后边使用数值来表示某个位置的循迹模块
  2和4之间的距离要大于循迹线的宽度,而1和2的水平方向的距离要小于循迹线的宽度。
  例如,我使用了1.5cm的线,那么24的距离选择了2.5cm,12的距离就是1.25cm
  如此做的好处是:在正常行驶的时候(非急转弯),至少总有一个模块扫描到黑线。理想状态是在直线行驶时总是只有1扫描到白线。当然,由于车子自身的原因和道路不完全笔直(也可能人为弄弯曲来考验车子的性能),所以需要2和4来辅助循迹。在右边的循迹模块遇到白线的时候,说明车子偏左了,可以往右挪一点。
  对于扫描结果的处理分成两部分,先是根据扫描到的循迹模块的结果来判断路况,务必要判断清楚路况之后再行驶。
  以下是没遇到转弯时的处理函数

void GowithCorrect(void)//控制小车整体修正着走直线,正常情况下使用此模式
{
    ctrl_comm =  SearchSignal();
/****************************************************************/
/****************************************************************/
    if(ctrl_comm == 1 )
    {
            ctrl_comm_flag = GO_LINE;
    }
/****************************************************************/      
    else if (ctrl_comm == 5)//
    {
            ctrl_comm_flag = RIGHTMORE;
    }
/****************************************************************/      
    else if (ctrl_comm == 4)//
    {
        ctrl_comm_flag = RIGHTLITTLE;
    }
/****************************************************************/      
  else if (ctrl_comm == 3)
    {
            ctrl_comm_flag = LEFTMORE;
    }
/****************************************************************/      
    else if (ctrl_comm == 2)
    {
        ctrl_comm_flag = LEFTLITTLE;
    }

/****************************************************************/
            if(ctrl_comm_flag == GO_LINE)
            {
                CarGo();
            }
            else if(ctrl_comm_flag == RIGHTMORE)
            {
                MoveRightMore();
            }
            else if(ctrl_comm_flag == RIGHTLITTLE)
            {
                MoveRightLittle();
            }
            else if(ctrl_comm_flag == LEFTMORE)
            {
                MoveLeftMore();
            }
            else if(ctrl_comm_flag == LEFTLITTLE)
            {
                MoveLeftLittle();
            }
}

  5代表中间和右边的循迹模块(也就是循迹模块)同时扫到,说明偏左一点点,可以往右边挪一点。
  4代表只有右边的循迹模块扫到,说明偏左比较多,可以多挪一点。但是,要尽可能避免这种情况,尽量保持中间的循迹模块始终能扫描到白线。
  MoveRightLittle函数是左边轮子转得快,右边轮子转的慢的函数。
  以上是正常行进的判断。如果函数写的得当,这3个循迹模块的配合就可以完成正常行驶+有平缓弧度的转弯了。下面来说一下如何进行直角转弯,和识别T型路口,十字路口。
普通的90°左转:
  10必然读到,扫描的结果是10到17
普通的90°右转:
  扫描结果20到27
①先看十字路口,所有的循迹模块都扫到,和为37,肯定是十字路口。
这里写图片描述
T型路口分为左转,右转和不能直行的T路口三种情况。如上图所示
情况判别如下:
②T型路口左转,90°的左转+延时,然后判断1,2,4循迹模块的情况,如果扫描到白线,说明是T型路口左转
③T型路口左转,90°的右转+延时,然后判断1,2,4循迹模块的情况,如果扫描到白线,说明是T型路口右转
④不能直行的T路口与十字路口:
  出现30到37的结果时,稍微延时一下,使得那一排4个循迹模块所在的直线超过白线,然后判断循迹模块1,2,4的情况,如果这三个循迹模块有白线说明是十字路口,否则是不能直行的T路口。
  注意①②③③这些情况都是理想状态,实际上即便车子完全垂直于循迹线到达这些路口时,如T路口左转,10和2也可能不会同时扫描到。因为器件差异和比较电压的差异,即便10和2同时到达了线的上方,这次扫描的结果也可能不是12。可以通过多次判断来确保不判断错。如果一次判断对的几率只有0.9的话,那么判断两次(只需要一次判断对,结果就是对的),判断对的几率就是0.99了。
  下面是一个判断直角左转或者T路口左转的例子。由于到了十字路口或不能直行的T路口也可能是先读到10,再读到20,所以这些情况也需要在读到10的时候讨论。

    else if ((ctrl_comm > 9)&&(ctrl_comm < 19) )//最左侧的循迹模块读到
        {
            CarGo();
            Delayms(50);
            ctrl_comm_temp = SearchSignal();
            if ((ctrl_comm_temp > 9)&&(ctrl_comm_temp <19))//略微延迟以后还是最左侧的循迹模块
                {
                    CarGo();
                    Delayms(450);
                    ctrl_comm_temp = SearchSignal();
                }
            else if((ctrl_comm_temp>30)&&(ctrl_comm_temp<37))//最外侧两边都扫描到,可能是T路口
                {
                    ctrl_comm_flag_tmp = T_ROAD;//暂时设置为T路口
                }
            else//未知的情况,让停车。
                {
                    ctrl_comm_flag = UNKNOW_ROAD;
                }

            if((ctrl_comm_temp < 6)&&(ctrl_comm_temp > 0))//判断是不是左转T路口
                {
                     ctrl_comm_flag = T_LEFT;
                }
            else if(ctrl_comm_temp == 0) //否则是直角左转的路口
                {
                    ctrl_comm_flag = RT_LEFT;
                }
        }

  建议将路况的判断与转弯的过程分开,直到判断清楚路况以后再根据命令直行或转弯。下面是直角左转的例子。
  CarLeft()是左侧轮子倒转,右侧正转,实现了小车基本上以左后轮为轴的左转。转到1循迹模块或者4循迹模块扫描到即可。

                else if (ctrl_comm_flag == RT_LEFT)//左转直角路口
                {
                        char tmp;
                    do{
                        CarLeft();
                        tmp = SearchSignal();
                    }while((tmp != 1)&&(tmp != 4));
                }

T路口的左转,先左转,使20扫过线,然后继续左转,转到1或4.

    else if (ctrl_comm_flag == T_LEFT)//左转T路口 -|
                    {
                        if(CMD_Next == CMD_LEFTONT)  //如果下一个命令是T路口左转
                        {
                                    char tmp;
                                do{
                                    CarLeft();
                                    tmp = SearchSignal();
                                }while(tmp < 19);                       
                                do{
                                    CarLeft();
                                    tmp = SearchSignal();
                                }while((tmp != 1)&&(tmp != 4));
                                CMD_Next_Index++;
                        }
                        else if(CMD_Next == CMD_GOSTRAIGHT)
                            {
                                CarGo();
                                Delayms(500);
                                CMD_Next_Index++;
                            }
                            else//可能未知的情况,停车
                            {
                                CarStop();
                                CMD_Now = CMD_STOP;
                            }


                    }

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值