关键原理:寻迹小车跟随黑线行驶,在小车头两边各自安装一个红外模块,利用的车头的红外传感器(TCRT5000)遇到深色物体无法正常返回信号的特性,有返回信号时红外模块输出高电平指示灯不亮,无信号返回输出低电平指示灯亮起。
TCRT5000 模块如下图
下面是自己的代码
关键子程序trackcar.c
#include "reg52.h"
#include "motor.h"
sbit LeftSersor =P2^6;
sbit RightSersor =P2^7;
void TrackCar()
{
//左边探测器和右边探测器都返回信号,保持直线。
if (LeftSersor==0&&RightSersor==0)
{
ForWard();
}
//如果左边有黑线,右边没有黑线,左转。
else if(LeftSersor==1&&RightSersor==0)
{
RightWard();
}
//如果左边没有黑线,右边有黑线,右转。
else if(LeftSersor==0&&RightSersor==1)
{
LeftWard();
}
//如果两边都是黑线停止
else if(LeftSersor==1&&RightSersor==1)
{
Stop();
}
}
主程序中还添加了一个发送数据控制小车的功能
main.c
//该程序中新增了两个红外模块,这两个模块安装在车头,模块探测方向是在地面,利用红外模块遇到黑色输出低电平的特性,设计出令小车跟随黑线的程序。
#include "motor.h"
#include "reg52.h"
#include "Usart_Init.h"
#include "delay.h"
#include "intrins.h"
#include "string.h"
#include "follow.h"
#include "trackcar.h"
#define bufferlen 12
char buffer[12];
void uart_Init()//串口初始化
{
SCON=0X50;//设置串口的寄存器工作模式
TMOD &=0X0F;//定时器1的工作模式
TMOD |=0X2F;
TH1=0XFD;//设置波特率9600
TL1=TH1;
TR1=1;//定时器开始计时
EA=1;//总中断
ES=1;//串口中断
}
void main ()
{
//串口的初始化设置
uart_Init();
//开启中断
interrupt_START();
// InitTimer0();
// Timer1Init();
//LeftSpeed=33;
//RightSpeed=40;
while(1)
{
TrackCar();
}
}
//由模块Tx发出的有两种指令,1,AT功能设置指令的反馈 2,服务器串口发送的数据传到WiFi模块,再由模块发给单片机
void uart_Interrupt () interrupt 4 //中段函数。每次接收到WiFi模块发过来的数据进入中断
{
static int i=0; //只在开始的时候执行一次
if (RI)//当串口中断事件为接收到数据
{
RI=0;
if(i==12)//不超过十二个字符
{
i=0;
}
buffer[i++]=SBUF;//全局变量接收WiFi模块Tx发送过来的数据
if(buffer[i-1]=='M')//第一个数据M
{
buffer[0] =buffer[i-1];//buffer[i-1]才是刚才接收的数据
i=1;
}
if (buffer[1]=='F') //当接受的数据为“MF”
{
ForWard();
Delay500ms() ;
memset(buffer, '\0', bufferlen);
}
if (buffer[1]=='B')//当接受的数据为“MB”
{
BackWard();
Delay500ms() ;
memset(buffer, '\0', bufferlen);
}
if (buffer[1]=='L')//当接受的数据为“ML”
{
LeftWard();
Delay200ms();;
memset(buffer, '\0', bufferlen);
}
if (buffer[1]=='R')//当接受的数据为“MR”
{
RightWard();
Delay200ms();;
memset(buffer, '\0', bufferlen);
}
}
}
下面是电机的子程序,因为电机的速度太快,程序中用了软件延时的方式控制PWM,比较粗暴,比较高级的办法是用T0和T2
分别控制左右轮,T1继续用于串口。
motor.c
//通过软件延时控制电机PWM,减少电机的供电时间
#include "reg52.h"
#include "intrins.h"
#include "delay.h"
//管脚配置
//右轮
sbit RightA=P3^3;
sbit RightB=P3^2;
//左轮
sbit LeftA=P3^4;
sbit LeftB=P3^5;
void ForWard()//前进
{
RightA=0;
RightB=0;
LeftA=0;
LeftB=0;
Delay50ms();
Delay50ms();
RightA=1;
RightB=0;
LeftA=1;
LeftB=0;
Delay50ms();
}
void BackWard()//后退
{
RightA=0;
RightB=1;
LeftA=0;
LeftB=1;
}
void LeftWard()//左转
{
RightA=0;
RightB=0;
LeftA=0;
LeftB=0;
Delay50ms();
Delay50ms();
RightA=1;
RightB=0;
LeftA=0;
LeftB=0;
Delay50ms();
}
void RightWard()
{
RightA=0;
RightB=0;
LeftA=0;
LeftB=0;
Delay50ms();
Delay50ms();
RightA=0;
RightB=0;
LeftA=1;
LeftB=0;
Delay50ms();
}
void Stop()
{
RightA=0;
RightB=0;
LeftA=0;
LeftB=0;
}
下面是软件延时子程序
delay.c
# include "intrins.h"
void Delay100ms() //@11.0592MHz
{
unsigned char i, j;
i = 180;
j = 73;
do
{
while (--j);
} while (--i);
}
void Delay2000ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
i = 15;
j = 2;
k = 235;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Delay500ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
i = 4;
j = 129;
k = 119;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Delay200ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
i = 2;
j = 103;
k = 147;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
头文件:
trackcar.h
void TrackCar();
motor.h
void ForWard();
void BackWard();
void LeftWard();
void RightWard();
void Stop();
delay.h
void Delay2000ms();
void Delay50ms();
void Delay200ms();
void Delay100ms();