这是一台能沿着预设黑色轨迹自主巡游的机器人,它在“深圳”地图上依次经过12个“景点”,并在每个景点自动掉头,最终回到起点。项目核心是一块搭载51单片机的BoeBot小车,配合4路QTI灰度传感器,通过状态机决策实现路径跟踪、路口识别和转向控制。

        传感器:4路QTI(红外反射式)传感器,连接至P1.4~P1.7(高四位),输出数字电平(0=黑线,1=白底)

#include<uart.h>
#include<BoeBot.h>

void Follow_Line(void);
int  Get_4QTI_State(void);
void MoveAStep(int LeftP,int RightP);
void RightTurn(int steps);
void LeftTurn(int steps);
void Rotate(int steps);
void Forward(int steps);                                                                                                                                                                                                                             

int right90Steps=42;//向右转90度所需的循环次数
int left90Steps=33;//向左转90度所需的循环次数
int UTurnSteps=45;//旋转180度所需的循环次数
int whereamI=0;//经过的景点数
int crossSteps=8,j=1,k=1;

void main(void)
{
	 uart_Init();
     delay_nms(2000);//延时2s,消除打开开关对小车的影响
	 while(1)
	 {
		  Follow_Line();
	 }		
}

void Follow_Line(void)
{
	int QTIState;
	int LeftPulse,RightPulse;
	QTIState=Get_4QTI_State();//获取小车的状态
	switch(QTIState)
	{
		case 0x10 : LeftPulse=1700;RightPulse=1700;break;//右转     0001		
case 0x30 : LeftPulse=1700;RightPulse=1500;break;//小幅右转 0011
	    case 0x20 : LeftPulse=1550;RightPulse=1450;break;//前进	    0010     
		case 0x40 : LeftPulse=1550;RightPulse=1450;break;//前进	    0100      
		case 0x60 : LeftPulse=1550;RightPulse=1450;break;//前进     0110       
		case 0x80 : LeftPulse=1300;RightPulse=1300;break;//左转     1000
		case 0xc0 : LeftPulse=1500;RightPulse=1300;break;//小幅左转 1100
case 0xe0 :                                //          1110
if(whereamI==8&&k==1) 
{
RightTurn(right90Steps);
LeftPulse=1500;RightPulse=1500;k++;break;
} //经过景点8后到达十字路口,非理想状态下未检测到“1111”,而是检测到“1110”,为保证准确也让其右转
else if(whereamI==2||whereamI==4||whereamI==10)
		            {
RightTurn(right90Steps);
LeftPulse=1500;RightPulse=1500;break;
	}//经过景点2、4、10后到达丁(十)字路口,非理想状态下未检测到“1111”,而是检测到“1110”,为保证准确也让其右转
			        else if(whereamI==5)
		            {
			              Forward(crossSteps);LeftPulse=1500;RightPulse=1500;break;
}//经过景点5后到达十字路口时, 非理想状态下未检测到“1111”,而是检测到“1110”,为保证准确也让其直行
		            else
		            {
			              LeftTurn(left90Steps); LeftPulse=1500;RightPulse=1500;break;
		            }
		  case 0x70:  if(whereamI==8&&k==1)                          // 0111
                    {
                          RightTurn(right90Steps);
LeftPulse=1500;RightPulse=1500;k++;break;
                    }//经过景点8后到达十字路口时, 非理想状态下未检测到“1111”而                                                                                      是检测到“0111”,为保证准确也让其右转
else if(whereamI==8&&k==2)                          		            {
			              LeftTurn(left90Steps);LeftPulse=1500;RightPulse=1500;break;
	}//经过景点8后,再经过一个十字路口到达第二个十字路口时,非理想状态下未检测到“1111”而是“0111”,为保证准确也让其左转
			        else if(whereamI==10||whereamI==5)                     
		            {
                        Forward(crossSteps);LeftPulse=1500;RightPulse=1500;break;
                    }//经过景点10后到达第二个丁字路口时使其直行,经过景点5后非理想状态下检测到“0111”,为保证准确也让其直行
		            else
		            {
                        RightTurn(right90Steps);LeftPulse=1500;RightPulse=1500;break;
                    }	                                                               
		  case 0xf0 : switch(whereamI)                      //1111
		            {
			            case 5:Forward(crossSteps);LeftPulse=1500;RightPulse=1500;break;
                              //经过景点5后到达十字路口时使其直行
						case 6: if(j==1)
				              {
			                      LeftTurn(left90Steps);
LeftPulse=1500;RightPulse=1500;j++;break;
						      }//经过第6个景点到达第1个十字路口时,使其左转
							  else
							  {
							      RightTurn(right90Steps);
LeftPulse=1500;RightPulse=1500;break;
							  }//经过第6个景点到达第2个十字路口时,使其右转
						case 8: if(k==1)
					          {
											 RightTurn(right90Steps);
LeftPulse=1500;RightPulse=1500;k++;break;	                           }//经过第8个景点到达第1个十字路口时,使其右转
						       else
							   {
									  LeftTurn(left90Steps);
LeftPulse=1500;RightPulse=1500;break;
}//经过第8个景点到达第2个十字路口时,使其左转
						case  9:
					    case 12 :
LeftTurn(left90Steps);
LeftPulse=1500;RightPulse=1500;break;
//经过第9个或第12个景点后到达十字路口时,使其左转
					        default  :RightTurn(right90Steps);
LeftPulse=1500;RightPulse=1500;break;
		                }break;
		   case 0x00: switch(whereamI)         // 0000
                    { 
						case 12  :Forward(12);Rotate(40);delay_nms(20000);
LeftPulse=1500;RightPulse=1500;break;
//游完所有景点后到达起始点时先直行一段距离,然后旋转180度,回到初始位置,延时20s,方便关闭电源结束巡游
			            default  :Rotate(UTurnSteps);whereamI++;
LeftPulse=1500;RightPulse=1500;break;
//每到达一个景点就旋转180度实现掉头,whereamI加1,即经过了一个景点
					}break;										
		  default : LeftPulse=1500;RightPulse=1500;break;
  }
	MoveAStep(LeftPulse,RightPulse);//给形参传递不同的值使小车实现不同的运动
}
int Get_4QTI_State(void)
{
	return P1&0xf0;//返回一个十六进制的整形数据以得到小车的状态
}
void Forward(int steps)//前进
{
	int i;
	for(i=0;i<steps;i++)
	MoveAStep(1700,1300);
}
void MoveAStep(int LeftP,int RightP) //给形参传递不同的值使小车实现不同的运动
{
	P1_1=1;
 	delay_nus(LeftP);            
	
 	P1_1=0;
 	P1_0=1;
 	delay_nus(RightP);           
	
 	P1_0=0;
 	delay_nms(20);
}
void RightTurn(int steps) //右转            
{
 	int i;
	for(i=0;i<steps;i++)
	MoveAStep(1700,1500);
}
void LeftTurn(int steps)//左转        
{
    int i;
	for(i=0;i<steps;i++)
	MoveAStep(1500,1300);
}
void Rotate(int steps) //掉头          
{
    int i;
	for(i=0;i<steps;i++)
	MoveAStep(1700,1700);
}

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐