1.循迹小车
1循迹模块的使用
TCRT5000传感器的红外发射二极管不断发射红外线 当发射出的红外线没有被反射回来或被反射回来但强度不够大时, 红外接收管一直处于关断状态,此时模块的输出端为高电平,指示二极管一直处于熄灭状态 被检测物体出现在检测范围内时,红外线被反射回来且强度足够大,红外接收管饱和, 此时模块的输出端为低电平,指示二极管被点亮
1.2 循迹小车原理
由于黑色具有较强的吸收能力,当循迹模块发射的红外线照射到黑线时,红外线将会被黑线吸收,导致 循迹模块上光敏三极管处于关闭状态,此时模块上一个LED熄灭。在没有检测到黑线时,模块上两个LED 常亮
循迹模块安装在小车车头两侧 下方小车两个模块都能反射回来红外,输出低电平,灯亮,直走 上方小车左模块遇到黑线,红外被吸收,左模块输出高电平,右模块输出低电平,左转,反之右转
1.3代码-循迹小车不调速
main.c
void main()
{
// 没反射回来,D0输出高电平,灭灯 都反射回来亮灯
// Timer0Init();
// Timer1Init();
// UartInit();
while(1){
if(LeftTarce == 0 && RightTarce == 0){
goForward();
}
if(LeftTarce == 0 && RightTarce == 1){
goRight();
}
if(LeftFollow == 1 && RightTarce == 0){
goLeft();
}
if(LeftTarce == 1 && RightTarce == 1){
stop();
}
}
}
1.4代码-循迹小车调速
main.c
#include "reg52.h"
#include "motor.h"
#include "delay.h"
#include "config.h"
#include "time.h"
extern int speedLeft;
extern int speedRight;
void main()
{
// 没反射回来,D0输出高电平,灭灯
Timer0Init();
Timer1Init();
// UartInit();
while(1){
if(LeftTarce == 0 && RightTarce == 0){
//都反射回来,没遇到黑色,直走
speedLeft = 70;
speedRight = 70;
}
if(LeftTarce == 0 && RightTarce == 1){
//右侧遇到黑色,需要右转
speedLeft = 80;
speedRight = 10;
}
if(LeftTarce == 1 && RightTarce == 0){
//左侧遇到黑色,需要右转
speedLeft = 10;
speedRight = 80;
}
if(LeftTarce == 1 && RightTarce == 1){
//都遇到黑色
speedLeft = 0;
speedRight = 0;
}
}
}
motoc.c
#include "reg52.h"
#include "config.h"
void goForwardLeft()
{
LeftCon1A = 0;
LeftCon1B = 1;
}
void goForwardRight()
{
RightCon1A = 0;
RightCon1B = 1;
}
void stopLeft()
{
LeftCon1A = 0;
LeftCon1B = 0;
}
void stopRight()
{
RightCon1A = 0;
RightCon1B = 0;
}
void goBack()
{
RightCon1A = 1;
RightCon1B = 0;
LeftCon1A = 1;
LeftCon1B = 0;
}
void goForward()
{
RightCon1A = 0;
RightCon1B = 1;
LeftCon1A = 0;
LeftCon1B = 1;
}
void goRight()
{
RightCon1A = 0;
RightCon1B = 0;
LeftCon1A = 0;
LeftCon1B = 1;
}
void goLeft()
{
RightCon1A = 0;
RightCon1B = 1;
LeftCon1A = 0;
LeftCon1B = 0;
}
void stop()
{
RightCon1A = 0;
RightCon1B = 0;
LeftCon1A = 0;
LeftCon1B = 0;
}
time.c
#include "reg52.h"
#include "motor.h"
sfr AUXR = 0x8e;
int cntLeft = 0;
int cntRight = 0;
int speedLeft;
int speedRight;
void Timer0Init(void) //500微秒@11.0592MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0x33; //设置定时初值
TH0 = 0xFE; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
EA = 1;
ET0 = 1;
}
void Timer1Init(void) //500微秒@11.0592MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x20; //设置定时器模式
TL1 = 0x33; //设置定时初值
TH1 = 0xFE; //设置定时初值
TF1 = 0; //清除TF0标志
TR1 = 1; //定时器0开始计时
EA = 1;
ET1 = 1;
}
void Time0Init() interrupt 1
{
cntLeft++; //统计爆表的次数
//重新给初值
TL0 = 0x33;
TH0 = 0xFE;
if(cntLeft < speedLeft){
goForwardLeft();
}else{
stopLeft();
}
if(cntLeft == 80){
cntLeft = 0;
}
}
void Time1Init() interrupt 3
{
cntRight++; //统计爆表的次数
//重新给初值
TL1 = 0x33;
TH1 = 0xFE;
if(cntRight < speedRight){
goForwardRight();
}else{
stopRight();
}
if(cntRight == 80){
cntRight = 0;
}
}
2. 跟随小车
2.1红外壁障模块分析
原理和寻线是一样的,寻线红外观朝下,跟随朝前
2.2跟随小车的原理
左边跟随模块能返回红外,输出低电平,右边不能返回,输出高电平,说明物体在左边,需要左转 右边跟随模块能返回红外,输出低电平,左边不能返回,输出高电平,说明物体在右边,需要右转
2.3代码-跟随小车
void main()
{
//左边跟随模块能返回红外,输出低电平,右边不能返回,输出高电平,说明物体在左边,需要左转
//右边跟随模块能返回红外,输出低电平,左边不能返回,输出高电平,说明物体在右边,需要右转
while(1){
if(LeftFollow == 0 && RightFollow == 0){
goForward();
}
if(LeftFollow == 0 && RightFollow == 1){
goLeft();
}
if(LeftFollow == 1 && RightFollow == 0){
goRight();
}
if(LeftFollow == 1 && RightFollow == 1){
stop();
}
}
}
3. 摇头测距小车
3.1上代码-疯狂摇头
#include "reg52.h"
#include "hc04.h"
#include "delay.h"
#include "sg90.h"
void main()
{
Time0Init();
Time1Init();
//舵机的初始位置
sgMiddle();
Delay300ms();
Delay300ms();
while(1){
sgLeft();
Delay300ms();
sgMiddle();
Delay300ms();
sgRight();
Delay300ms();
sgMiddle();
Delay300ms();
}
}
#include "reg52.h"
#include "delay.h"
sbit sg90_con = P1^1;
int jd;
int cnt = 0;
void Time0Init()
{
//1. 配置定时器0工作模式位16位计时
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01;
//2. 给初值,定一个0.5出来
TL0=0x33;
TH0=0xFE;
//3. 开始计时
TR0 = 1;
TF0 = 0;
//4. 打开定时器0中断
ET0 = 1;
//5. 打开总中断EA
EA = 1;
}
void sgMiddle()
{
//中间位置
jd = 3; //90度 1.5ms高电平
cnt = 0;
}
void sgLeft()
{
//左边位置
jd = 5; //135度 1.5ms高电平
cnt = 0;
}
void sgRight()
{
//右边位置
jd = 1; //0度
cnt = 0;
}
void Time0Handler() interrupt 1
{
cnt++; //统计爆表的次数. cnt=1的时候,报表了1
//重新给初值
TL0=0x33;
TH0=0xFE;
//控制PWM波
if(cnt < jd){
sg90_con = 1;
}else{
sg90_con = 0;
}
if(cnt == 40){//爆表40次,经过了20ms
cnt = 0; //当100次表示1s,重新让cnt从0开始,计算下一次的1s
sg90_con = 1;
}
}
3.2 添加电机,实现测距摇头,“懂得避障”
main.c
void main()
{
char dir;
double disMiddle;
double disLeft;
double disRight;
Time0Init();
Time1Init();
sgMiddle();
Delay300ms();
Delay300ms();
dir = MIDDLE;
while(1){
disMiddle = get_distance();
if(disMiddle > 20){
//前进
goForward();
}
else if(disMiddle < 7){
goBack();
Delay150ms();
stop();
}
else{
sgRight();
Delay300ms();
disRight = get_distance();
sgMiddle();
Delay300ms();
disMiddle = get_distance();
sgLeft();
Delay300ms();
dir = LEFT;
disLeft = get_distance();
if(disRight < disLeft){
goLeft();
Delay200ms();
stop();
}
if(disRight > disLeft){
goRight();
Delay200ms();
stop();
}
}
if(dir != MIDDLE){
sgMiddle();
dir = MIDDLE;
Delay300ms();
}
}
}