使用五路循迹模块可以识别比较复杂的路况,比如十字路口,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;
}
}
本文介绍五路循迹模块的使用方法,包括通过不同数值组合判断车辆行驶状态及复杂路况,如十字路口、T型路口等,并给出具体实现代码示例。
1万+

被折叠的 条评论
为什么被折叠?



