实例4,循迹模块的使用和循迹小车的实现

1、循迹模块介绍;

2、循迹原理;

3、硬件接线;

4、循迹编程思路流程图;

5、循迹程序第一稿(后面再写几篇文章加计时、测距、蓝牙等模块)。

一、循迹模块

目前大一新生,多数用的是数字式的循迹模块,当碰到黑线,发出一个1信号,碰到白线发出0信号。这个1和0是根据实际模块电路决定的,有些碰到黑线是0,有些是1,这个可以用万用表测试下,如果是信号引脚碰到黑线的时候,是5v电,那么就是黑线是1,如果碰到白线是5v,那么白线是1。有一个按钮调节灵敏度的,根据实际情况调节好。
后面熟练之后,可以用ADC模块进行黑白线检测。这个后面再了解。

在这里插入图片描述
在这里插入图片描述
外观不一样,注意看引脚的标识。
以这个为例。
在这里插入图片描述

G接GND,V+接5V,S是信号线,接输出到单片机的IO口,当碰到黑线白线会发生跳变。 滑动变阻器是调节灵敏度的旋钮,高度不一样,旋转到合适的数值,碰到黑线和白线有信号的变化就可以,一般放和底面高度8-15mm。

其他模块也一样。

2、循迹模块的布置。

一般需要3-5个循迹模块。
布局很重要,可以设置中间三个距离近一点,边角远一点。
这个关系到循迹条件的判断。
在这里插入图片描述

*3、循迹模块的条件

从做到右叫做LS1,LS0,MS,RS0,RS1,这个名字自己起就可以了。

循迹的几种情况。(注意判断情况条件自己根据自己情况,适当修改,不能太死板哦。)
第一种,直线行走。两个轮子速度一样
1代表黑线,0代表直线。
MS黑线的时候;
00100
第二种,往左小偏转,右轮比左轮的速度快一点。
LS0
黑线
01000
第三种,左大转。
右轮速度更加快一点,左轮干脆停止了。
LS11(黑线)
10000
大转弯到MS碰到黑线,就停止大转弯。
第四种,右边小转
RS0
1
00010
第五种,右边大转
00001
大转弯到中碰到黑线,就停止大转弯。

第六种,直角左转弯
11x00。
中间的那个x代表是0或者1都可以。
转弯到RS0碰到黑线,就停止转弯。

在这里插入图片描述

第七种,直角右转弯。
只需要最右边的两个是黑线就行。
00x11
转弯到LS0碰到黑线,就停止转弯。

在这里插入图片描述

第八种,调头

四个或者5个都是1,碰到黑线,都调头
01111
11110
11111
前进1秒,
然后左轮后退,右轮前进,旋转调头,直到之间的MS碰到黑线停止调头。

在这里插入图片描述

第九种,检测不到线,就原地打圈,极端情况。
00000

3、接线。

由于使用几个模块,几个循迹模块都需要VCC和GND,都接杜邦线到控制板,会比较乱。
因此,最好用洞洞板焊接一个转接板。
实物看实验室的小车。

在这里插入图片描述

电机接线看上一个文章。

4、编程流程图
定义引脚,循迹,电机,按键。
写前进,停止子函数;
初始化。pwm初始化,端口初始化。
while(1)
{
1,按键按下吗?
,是
设置标记flag=1

2、标记flag==1吗?
是,开始循迹
{
	第一种情况
	。。。
	第二种
	。。。
	第n中
	。。。。。
	
}

}


//***************************************************************************下面是接线定义
//左电机
sbit LPWM=P2^0;//电机调节速度的信号
sbit LA2=P0^4;
sbit LA1=P0^5;
//右电机
sbit RPWM=P2^1;
sbit RA2=P0^6;
sbit RA1=P0^7;
//接传感器
sbit L1S=P1^0;
sbit L0S=P1^1;
sbit MS=P1^2;
sbit R0S=P1^3;
sbit R1S=P1^4;
sbit key=P3^4;//接按键,启动按键
void trackline0();
//这个是定义,不声明,后面main函数可以直接用,
//小车前进,根据速度两个轮子速度差,进行前进,转弯等
void qianjin(float vleft,float vright)
{
  HPWM_Set(0,8000,vleft);
	LA2=1;
  LA1=0;
	
	HPWM_Set(1,8000,vright);
	RA2=1;
  RA1=0;
	
}
//小车调头程序,左轮反转,右轮正转
void turnback(float vleft,float vright)
{
  HPWM_Set(0,8000,vleft);
	LA2=0;
  LA1=1;
	
	HPWM_Set(1,8000,vright);
	RA2=1;
  RA1=0;
	
}
//****************************************************************子函数3:void stop()
//小车停止
void stop()
{ 
	LA2=0;
  LA1=0;
	
	RA2=0;
  RA1=0;
}
//*******************************************主函数
void main()
{
	bit startflag=0; //按键控制的启动标记
	bit startflag2=0; //蓝牙控制的启动标记
	
	//每个外设,比如按键,屏幕,PWM等内部资源的初始化,配置一下环境
	//设置准双向口,和普通的51单片机一样
	P0M1=0x00;P0M0=0x00;
	P1M1=0x00;P1M0=0x00;
	P2M1=0x00;P2M0=0x00;
	P3M1=0x00;P3M0=0x00;
	P4M1=0x00;P4M0=0x00;
	P5M1=0x00;P5M0=0x00;
	P6M1=0x00;P6M0=0x00;
	delay_tms(200);
	//屏幕初始化
	OLED_Init();
	//PWM模块初始化
	HPWM_Init();
//*****************************************************************
	//*********************************************正式执行程序
  while(1)
	{		

  //**************************************************************************按键来控制的
		//*****************************
		//检测按键是不是按下,开始启动
		if(key==0)
		{
			delay_tms(10);//延时去抖动
			if(key==0)
			{	
				startflag=1;
				stop();
	 		  delay_tms(1000);//延时,按下两秒之后,小车开始启动进行循迹
			//	delay_tms(2000);
		}
			
	 }	
	 //**********************如果开始标记等于1,说明按下启动键key,这时候小车才开始跑
		if(startflag==1)
		{
			//开始循迹,请看这部分代码,太长了,单独拉出来写,方便看主程序逻辑	
       trackline0();	
		}
// //**************************************************************//函数定义trackline0();
// //**************************************************************功能:按键循迹;
void trackline0()
{
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++第1种情况
	if(L1S==blackline &&L0S==whiteline  && MS==whiteline && R0S==whiteline&& R1S==whiteline)//1 0 0 0 0 
	{
		qianjin(vturnsmallM,vturnbigM);//左da转弯,转到碰到中线停止
		while(1)
		{			
			if(MS==blackline)break;
		}	

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++第2种情况
	else if(L1S==whiteline &&L0S==blackline  && MS==whiteline && R0S==whiteline&& R1S==whiteline)//0 1 0 0 0 
	{
		qianjin(vturnsmall,vturnbig);//左xiao转弯
	}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++第3种情况
	else if(L1S==whiteline &&L0S==whiteline  && MS==blackline && R0S==whiteline&& R1S==whiteline)//00 1 0 0 
	{
		qianjin(vleftmove,vrightmove);//直走
	}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++第4种情况	
	else if(L1S==whiteline &&L0S==whiteline  && MS==whiteline && R0S==blackline&& R1S==whiteline)//0 0 0 1 0 
	{
		qianjin(vturnbig,vturnsmall);//左xiao转弯vturnbig vturnsmall
	}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++第5种情况
	else	if(L1S==whiteline &&L0S==whiteline  && MS==whiteline && R0S==whiteline&& R1S==blackline)//0 0 0 0 1
	{
		qianjin(vturnbigM ,vturnsmallM);//左da转弯vturnbigM  vturnsmallM,碰到黑线,不然一直大转弯,

		while(1)
		{			
			if(MS==blackline)break;
		}

		
		
	}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++第6种情况	
	else 	if(L1S==blackline && L0S==blackline && R1S==whiteline )//11xx0 判断是左转90度
	{
		 
		qianjin(vturnsmall,vturnbig);//左转弯
		while(1)	 
		{ 
				if(R0S==blackline)break;
		}
	
	}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++第7种情况
	else 	if( L1S==whiteline  &&R0S==blackline && R1S==blackline)//0xx11 判断是右转90度
	{
	
  	qianjin(vturnbig,vturnsmall);//

		while(1)	 
		{ 
				if(L0S==blackline)break;
		}

	}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++第8种情况
		else 	if(L1S==blackline &&L0S==blackline&& MS==blackline && R0S==blackline && R1S==whiteline)//1111x 判断是终点,调头,左轮反转,右轮正转,左转调头
	{
			
		
			stop();
		  delay_tms(1000);
		
		  qianjin(vleftmove,vrightmove);
		  delay_tms(1000);
		
	  	stop();
		  delay_tms(1000);
		
	  	turnback(vleftmove,vrightmove);
	//		delay_tms(1000);

			while(1)	 
			{ 
					if(MS==blackline)break;
			}

	}
	
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++第8种情况
		else 	if(L1S==whiteline &&L0S==blackline&& MS==blackline && R0S==blackline && R1S==blackline)//1111x 判断是终点,调头,左轮反转,右轮正转,左转调头
	{
		
			stop();
		  delay_tms(1000);
		
		  qianjin(vleftmove,vrightmove);
		  delay_tms(1000);
		
	  	stop();
		  delay_tms(1000);
		
	  	turnback(vleftmove,vrightmove);
	//		delay_tms(1000);


			while(1)	 
			{ 
					if(MS==blackline)break;
			}
	
	}
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++第8种情况
		else 	if(L1S==blackline &&L0S==blackline&& MS==blackline && R0S==blackline && R1S==blackline)//1111x 判断是终点,调头,左轮反转,右轮正转,左转调头
	{
			
		
			stop();
		  delay_tms(1000);
		
		  qianjin(vleftmove,vrightmove);
		  delay_tms(1000);
		
	  	stop();
		  delay_tms(1000);
		
	  	turnback(vleftmove,vrightmove);

			while(1)	 
			{ 
					if(MS==blackline)break;
			}
	
	}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++第9种情况	这是极端情况,放在最后面判断
		//000找不到直线,如果前面是直走,就转360度,如果是之前右边,就左转,之前左偏,就右转
	else 	if(L1S==whiteline &&L0S==whiteline && MS==whiteline && R0S==whiteline && R1S==whiteline)	
	{
    qianjin(vturnbig,vturnsmall);//
	}
				
}

下载,测试一下程序。

### 关于51单片机循迹小车的代码解释 #### 传感器读取部分 为了实现循迹功能,通常会使用红外传感器来检测地面的颜色变化。当车辆行驶到黑色线条上时,红外发射管发出的光线被吸收;而在白色区域时,则会被反射回来并由接收端捕捉。 ```c unsigned char Read_Track_Sensors(void){ unsigned char track_value; P2 = 0xFF; // 设置P2口为输入模式 track_value = P2 & 0x0F; // 只保留低四位作为传感器数据 return track_value; } ``` 此函数用于获取四个红外传感器的状态值[^1]。通过设置`P2`端口为高阻态(即输入状态),可以确保不会干扰外部信号采集。随后利用位运算操作提取出对应引脚电平情况,并将其返回给调用者以便后续处理逻辑判断。 #### 方向控制算法设计 根据所获得的不同组合形式决定下一步行动方向: - 当所有感应器都处于同一侧时(如全黑或全白),则保持直行; - 如果左侧两个探测到了边界而右侧没有,则右转调整姿态直至重新回到轨迹线上面; - 同理可得对于相反情形应采取左转弯措施; - 若中间位置有且仅有单一光敏元件触发响应,则依据具体分布状况微调角度以纠正偏差。 ```c void Track_Adjustment(unsigned char sensor_data){ switch(sensor_data){ case 0b0000: // 所有传感器均未检测到障碍物 GoStraight(); break; case 0b0001: case 0b0011: TurnRight(); break; case 0b0100: case 0b1100: TurnLeft(); break; default:// 中间位置存在交叉点或其他特殊情况 FineAdjust(); break; } } ``` 上述伪码展示了如何根据不同类型的传感反馈执行相应的动作指令。这里定义了一个名为 `Track_Adjustment()` 的子程序负责解析来自各个通道的信息流,并据此作出适当反应——无论是前进还是转向等基本运动单元。 #### 主循环结构搭建 最后,在主函数中不断重复以上两步流程即可完成整个自动寻路过程。 ```c void main(){ while(1){ unsigned char sensors_status = Read_Track_Sensors(); Track_Adjustment(sensors_status); delay_ms(5); // 延迟一段时间防止抖动影响准确性 } } ``` 这段核心框架持续监测周围环境的变化趋势并通过实时更新内部决策机制引导载体沿着预定路径稳定移动。
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值