探索循迹小车的原理与实现

目录

一、循迹模块使用

二、接线方式

三、循迹小车原理

四、代码实现


一、循迹模块使用

1、TCRT5000传感器的红外发射二极管不断发射红外线,当发出的红外线没有被反射回来或被反射回来但强度不太够时,红外接收管一直处于关断状态,此时模块的输出为高电平指示二极管一直处于熄灭状态,被检测物体出现在检测范围内时,红外线被反射回来且强度足够大,红外接收管饱和,此时模块的输出端为低电平,指示二极管被点亮

总之一句话:没反射回来,D0输出高电平,灭灯

二、接线方式

VCC:接上官一号正极(3-5V)

GND:接上官一号负极

D0:TTL开关信号输出0、1

A0:模拟信号输出(不同距离输出不同的电压,此脚一般可以不接)

三、循迹小车原理

由于黑色具有较强的吸收能力,当循迹模块发射的红外线照射到黑线时,红外线将会被黑线吸收,导致循迹模块上光敏二

0.极管处于关闭状态,此时模块上一个LED熄灭,在没有检测到黑线时,模块上两个LED常亮

总结就是一句话:有感应到黑线,D0输出高电平,灭灯

循迹模块安装在小车车头两侧

下方小车两个模块都能反射回来红外,输出低电平,灯亮,直走

上方小车左循迹模块遇到黑线,红外被吸收,左模块输出高电平,右模块输出低电平,左转,反之右转 

总结:两个小绿灯都亮,那左右两边的车轮就都转动,只亮一个小绿灯的说明这侧遇到了黑线,红外被吸收,红外没有被反射回来,输出高电平,所以就不转动了。

四、代码实现

main.c

#include "motor.h"
#include "delay.h"
#include "uart.h"
#include "time.h"
#include "reg52.h"

extern char speedLeft;   //此变量/函数是在别处定义的,要在此处引用
extern char speedRight;

sbit leftSensor  = P2^7;
sbit rightSensor = P2^6;

void main()
{
	Time0Init();   //定时器0初始化
	Time1Init();   //定时器1初始化
	UartInit();    //串口初始化

	while(1){
		
		if(leftSensor == 0 && rightSensor == 0 ){
			//直走
			speedLeft = 40;   
			speedRight = 40;
		}
		if(leftSensor == 1 && rightSensor == 0 ){
			//左转
			speedLeft = 10;   
			speedRight = 40;
			
		}
		if(leftSensor == 0 && rightSensor == 1 ){
			//右转
			speedLeft = 40;
			speedRight = 10;
			
		}
		if(leftSensor == 1 && rightSensor == 1){
			//停止
			speedLeft = 0;
			speedRight = 0;
		}		
	}
}

motor.c

#include "reg52.h"


sbit RightCon1A = P3^2;
sbit RightCon1B = P3^3;

sbit LeftCon1A = P3^4;
sbit LeftCon1B = P3^5;

void goForWardLeft(){     //小车左前进

	LeftCon1A = 1;
	LeftCon1B = 0;
}

void goForWardRight(){    //小车右前进
	
	
	RightCon1A = 1;
	RightCon1B = 0; 
}

void stopLeft(){          //小车左停止

	LeftCon1A = 0;
	LeftCon1B = 0;
}

void stopRight(){         //小车右停止
	 
	RightCon1A = 0;
	RightCon1B = 0; 
}

void goForWard(){         //小车前转

	LeftCon1A = 1;
	LeftCon1B = 0;
	RightCon1A = 1;
	RightCon1B = 0; 

}

void goBack(){           //小车后转
	
	LeftCon1A = 0;
	LeftCon1B = 1;
	RightCon1A = 0;
	RightCon1B = 1; 
}

void goLeft(){   //小车左转
	
	LeftCon1A = 0;
	LeftCon1B = 0;
	RightCon1A = 1;
	RightCon1B = 0; 
}



void goRight(){   //小车右转
	
	LeftCon1A = 1;
	LeftCon1B = 0;
	RightCon1A = 0;
	RightCon1B = 0; 
}


void stop(){   //小车停止
	
	LeftCon1A = 0;
	LeftCon1B = 0;
	RightCon1A = 0;
	RightCon1B = 0; 
}

motor.h

void goForWard();
void goBack();
void goLeft();
void goRight();
void stop();
void goForWardLeft();
void goForWardRight();
void stopLeft();
void stopRight();

delay.c


#include "intrins.h"

void Delay1000ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	_nop_();
	i = 8;
	j = 1;
	k = 243;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void Delay10ms()		//@11.0592MHz
{
	unsigned char i, j;

	i = 18;
	j = 235;
	do
	{
		while (--j);
	} while (--i);
}

delay.h

void Delay1000ms();
void Delay10ms();

uart.c——串口初始化文件

#include "reg52.h"
#include "motor.h"
#include "string.h"
#include "delay.h"
#define SIZE 12

sfr AUXR = 0x8E;
char cmd;
char buffer[SIZE];

void UartInit(void)		//9600bps@11.0592MHz
{
	AUXR = 0x01;   //降低时钟对外界的辐射
	SCON = 0x50;   //串行口寄存器工作模式选择方式1,RNE=1,为串行允许接收状态
	
	TMOD &= 0x0F;  //定时器1工作方式位8位自动重装
	TMOD |= 0x20;
	
	TH1 = 0xFD; 
	TL1 = 0xFD;   //9600波特率的初值
	TR1 = 1;      //启动定时器
	
	EA = 1;       //总中断寄存器,开启总中断
	ES = 1;       //开启串口中断
	
}



void	Uart_Handler()	interrupt 4
{
	
	char tmp;
	static int i = 0;   //静态变量,被初始化一次
	if(RI == 1){        //中断处理函数中,对于接收中断的响应  
		RI = 0;           //清除接收中断标志位
		tmp = SBUF;
		if(tmp == 'M'){
			i = 0;
		}
		buffer[i++] = tmp;
	
		if(buffer[0] == 'M'){
			switch(buffer[1]){
				
				case '1':
					goForWard();
					Delay10ms();
					break;
				case '2':
					goBack();
					Delay10ms();
					break;
				case '3':
					goLeft();
					Delay10ms();
					break;
				case '4':
					goRight();
					Delay10ms();
					break;
				default:
					stop();
					break;
			}
			
		}
		if(i == 12) {
			i = 0;
			memset(buffer,'\0',SIZE);
		}
	}
}

uart.h

void UartInit(void);

time.c——初始化定时器及定时器开启中断文件


#include "motor.h"
#include "reg52.h"

char speedLeft;
char cntLeft = 0;


char speedRight;
char cntRight = 0;

void Time1Init(){

	//1、配置定时器0工作模式位16位计时
	TMOD &= 0x0F;
	TMOD |= 0x1 << 4;
	//2、给定时器一个初值,每个周期都等于0.5ms
	TL1 = 0x33;
	TH1 = 0xFE;
	//3、定时器开始计时
	TR1 = 1;
	TF1 = 0;
	
	//4、打开中断定时器1
	ET1 = 1;
	//5、设置总中断定时器
	EA = 1;
	
}

void Time0Init(){

	//1、配置定时器0工作模式位16位计时
	TMOD = 0x01;
	//2、给定时器一个初值,每个周期都等于0.5ms
	TL0 = 0x33;
	TH0 = 0xFE;
	//3、定时器开始计时
	TR0 = 1;
	TF0 = 0;
	
	//4、打开中断定时器
	ET0 = 1;
	//5、设置总中断定时器
	EA = 1;
	
}

void Time1Handler() interrupt 3   //定时器0的中断号为 interrupt 1
{
	
	cntRight ++;           //统计爆表的次数
	//给定时器重新定义初值,每个周期都等于0.5ms
	TL1 = 0x33;      
	TH1 = 0xFE;
	//控制PWM波形
	if(cntRight < speedRight){
		//右前进
		goForWardRight();
		
	}else{
		//右停止
		stopRight();
		
	}
	
	if(cntRight == 40){   //要爆表40次,经过了20ms
			cntRight = 0;      //当100次表示1s,重新让cnt从0开始,计算下一次的1s
			
	}
}


void Time0Handler() interrupt 1   //定时器0的中断号为 interrupt 1
{
	
	cntLeft ++;           //统计爆表的次数
	//给定时器重新定义初值,每个周期都等于0.5ms
	TL0 = 0x33;      
	TH0 = 0xFE;
	//控制PWM波形
	if(cntLeft < speedLeft){
		//左前进
		goForWardLeft();
		
	}else{
		//左停止
		stopLeft();
		
	}
	
	if(cntLeft == 40){   //要爆表40次,经过了20ms
			cntLeft = 0;      //当100次表示1s,重新让cnt从0开始,计算下一次的1s
			
	}
}

time.h

void Time0Init();
void Time1Init();

物联沃分享整理
物联沃-IOTWORD物联网 » 探索循迹小车的原理与实现

发表评论