基于51单片机,应用超声波、红外开关的自主行走小车

版权声明:转载请标明原文章地址 https://blog.csdn.net/weixin_41543617/article/details/83995057

一、 设计任务
a.熟悉机器人的构造及组成,实现机器人按指令行走(前进,左转,右转,匀加速,匀减速,停止等)
b.通过红外传感器触发,实现每次触发的时候运行状态的改变
c.通过超声波传感器测量距离,并且能够串口观察测量数据
d.根据超声波测量距离的不同实现运行状态的转换
e.利用红外传感器作为触发开关,利用超声波传感器测距,最终控制机器人在规划的场地内避开障碍物走遍整个场地。
二、模块使用
1.红外模块
红外传感器

模块接口说明:
(1)VCC 外接 3.3V-5V 电压(可以直接与 5v 单片机和 3.3v 单片机相连)
(2)GND 外接 GND
(3)OUT 小板数字量输出接口(0 和 1)
2.超声波(HC-SR04)
超声波模块实物图
工作原理:
(1)采用IO口TRIG触发测距,给至少10us的高电平信号;
(2)模块自动发送8个40khz的方波,自动检测是否有信号返回;
(3)有信号返回,通过IO口ECHO输出一个高电平,高电平持续的时间就是超声波从发射到返回的时间。测试距离=(高电平时间*声速(340M/S))/2;
(4)本模块使用方法简单,一个控制口发一个10US以上的高电平,就可以在接收口等待高电平输出。一有输出就可以开定时器计时,当此口变为低电平时就可以读定时器的值,此时就为此次测距的时间,方可算出距离。如此不断的周期测,即可以达到你移动测量的值

3.行走机构为360度舵机
三、代码

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

#define uchar unsigned  char
#define uint  unsigned   int  
#define  ECHO  P1_4
#define  TRIC  P1_2
#define  RED   P0_0
	
uint  time=0;
uint  timer=0;
float         S=0;
bit           flag =0;
	
uint i=0;
uint end=0;
uint turn=0;
/*************计算超声波探测距离***************************/
void Conut(void)
{
		 time=TH0*256+TL0;
		 TH0=0;
		 TL0=0;
		 S=(time*1.85)/100;     //算出来是CM
		 if(flag==1)		    //超出测量
		 {
			  flag=0;
			  S=1000;
		 	  printf("-----\n"); 
		 }
		  printf("S=%f\n",S); 
}
/********************************************************/
  void zd0() interrupt 1 		 //T0中断用来计数器溢出,超过测距范围
  {
   	 flag=1;					 //中断溢出标志
  }
/************************启动超声波****************************/
   void  StartModule() 		       
  {
	  TRIC=1;			                 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_();
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_();
	  TRIC=0;
  }
/********************控制小车姿态************************************/
     //	P1_0=1;             	//P1_0输出高电平 1300 右正
    //	P1_1=1;			 		//P1_1输出高电平 1700 左正
void stop(void)
{
  		
		P1_0=1;          		
		delay_nus(1500);
		P1_1=1;
		P1_0=0;
		delay_nus(1500);
		P1_1=0;          		
		P1_1=0;     		
		delay_nms(20);  
}
void forward(void)
{
		P1_1=1;
		delay_nus(1700);  		
		P1_0=1;            		
		P1_1=0;            		
		delay_nus(1300);
		P1_0=0;            		
		P1_1=0;
		delay_nms(20); 
		if(RED==0)
		{
		     while(1)
		  	 {stop();} 
		}  
}	

void left(void)
{
	for(i=23;i>0;i--)
	{
			P1_1=1;
			delay_nus(1300);  		
			P1_0=1;            		
			P1_1=0;            		
			delay_nus(1300);
			P1_0=0;            		
			P1_1=0;
			delay_nms(20); 
	
			if(RED==0)
			{
			     while(1)
			  	 {stop();} 
			} 
	} 
}

void right(void)
{
	for(i=23;i>0;i--)
	{	
			P1_1=1;
			delay_nus(1700);  		
			P1_0=1;            		
			P1_1=0;            		
			delay_nus(1700);
			P1_0=0;            		
			P1_1=0;
			delay_nms(20);
			if(RED==0)
			{
			     while(1)
			  	 {stop();} 
			} 
	}  
}

void backward(void)
{
		P1_1=1;
		delay_nus(1300);  		
		P1_0=1;            		
		P1_1=0;            		
		delay_nus(1700);
		P1_0=0;            		
		P1_1=0;
		delay_nms(20);  
}	
/********************读取超声波测距***********************************/
void read(void)
{
 	 StartModule();
	 while(!ECHO);		//当RX为零时等待
	 TR0=1;			    //开启计数
	 while(ECHO);			//当RX为1计数并等待
	 TR0=0;				//关闭计数
     Conut();			//计算 

}
/******************************************************/
void main(void)
{  
	TMOD |=0x20;   //设置定时器T/C1工作在方式2,定时1工作于自动重载模式
	SCON=0x50;     //设置串行口工作方式1
	TH1=0xfd;      //波特率9600
	TL1=0xfd;
	TR1=1;         //启动定时器
	ES=1;	        //开串行口中断
	TH0=0;
	TL0=0; 
	TR0=1;  
	ET0=1;             //允许T0中断
	TR1=1;			   //开启定时器
	TI=1;
	
	EA=1;			   //开启总中断
	
	end=0;
	turn=0;
	while(RED);
	while(RED==0);
	while(1)
	{
		 read();
	     if(S>=100)
			 forward(); 
		 else
		 {
		    turn++;
			end=0;
	 	 }
		if(end==0)
		{
	       switch(turn){
		       
			   case 1: 		
						left();
						for(i=40;i>0;i--)
						{
							forward();
						}
						left();
						end=1;
						break;
			   case 2:		
						left();
						end=1;
						break;
			   case 3:		
						right();
						end=1;
						break;
			   case 4:	   
						right();
						for(i=40;i>0;i--)
						{
							forward();
						}
						right();
						end=1;
						break;
			   case 5:		
						left();
						end=1;
						break;
			   case 6:		
						right();
						end=1;
						break;
			   case 7:		
						left();
						left();
						end=1;
						break;
			   case 8:		
						left();
						end=1;
						break;
			   case 9:	   
						left();
						turn=0;
						end=1;
						break;

			   default:    
						break;

			   }	
		}
	}
} 

猜你喜欢

转载自blog.csdn.net/weixin_41543617/article/details/83995057