51红外寻迹小车(一)

笔记 专栏收录该内容
3 篇文章 0 订阅

系统原理∶在汽车行红外光在具有不同颜色的物体表面的不同反射特性不断向地面发射红外光。当红外光与白纸地板相遇时会发生漫反射反射光被安装在车内的接收器接收,如果遇到黑线就会变成红色外部光被吸收,车内的接收器不能接收红外线。单片机根据是否接收到反射的红外光来确定黑线的位置和汽车的行驶路线。
在这里插入图片描述
在这里插入图片描述
(我买的材料还没回来这是网课上的)
电机驱动模块:L298N双路电机驱动板
寻迹模块:红外对管避障传感器 通过电位器调节红外发射管的功率,将红外线发射出去,接收管接收经过地面反射回来的红外线,由于黑色会吸收较多的红外线,从而使接收管接收到的红外线减少,使接受管输出端产生电平信号的变化(据说在红外对管的外面加设热缩管可提高红外对管的灵敏度)在这里插入图片描述
电源模块:锂电池
除此之外还有控制模块,发射模块和接收模块在这里插入图片描述
软件流程图还在学习中
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

祖传代码(知乎 木子子)
#include <reg52.h>

//传感器各引脚定义,其实我把middle的传感器拔下来了(对我的车子来说不要中间的这个传感器跑的更好),所以之后middle会默认一直为1
sbit left1 = P0^0;
sbit left2 = P0^1;
sbit middle = P0^2;
sbit right1 = P0^3;
sbit right2 = P1^0;

//电机驱动模块各引脚定义,zh:正,fu:负
sbit leftzh = P3^4;
sbit leftfu = P3^5;
sbit rightzh = P3^3;
sbit rightfu = P3^2;

//电机全速前进定义
#define unint unsigned int
#define Left_moto_go {leftzh=1,leftfu=0;}
#define Right_moto_go {rightzh=1,rightfu=0;}

//PWM和push值以及临时变量定义
unint pwm_value_left = 0;
unint pwm_value_right = 0;
unint push_value_left = 0;
unint push_value_right = 0;
unint num = 0;

//延时函数定义,延时x毫秒
void delay(unint xms){
unint i,j;
for(i=xms;i>0;i–)
for(j=110;j>0;j–)
;
}

//全速前进函数定义,最大速度20
void run(void){
push_value_left=0;
push_value_right=0;
Left_moto_go;
Right_moto_go;
}

//普通前进函数定义,普通速度15
void run_usual(void){
rightfu=0;
leftfu=0;
push_value_left=15;
push_value_right=15;
}

//全部停止函数定义,两边急刹
void stop(void){
push_value_left=0;
push_value_right=0;
leftzh=1;
leftfu=1;
rightzh=1;
rightfu=1;
}

//左直角转弯函数,两轮相对反转,这样转弯急快
void left_90(void){
push_value_left=0;
push_value_right=0;
leftzh=0;
leftfu=1;
rightzh=1;
rightfu=0;
}

//右直角转弯函数
void right_90(void){
push_value_left=0;
push_value_right=0;
leftzh=1;
leftfu=0;
rightzh=0;
rightfu=1;
}

//左转函数定义,一个轮子待机,一个轮子速度10。首先rightfu=0是为了防止电机的奇怪反转。实时证明转弯的时候还是直接停一个电机反应的更加灵敏一些,所以左边的value就给的0.
void turn_left(void){
rightfu=0;
push_value_left=0;
push_value_right=10;
leftzh=0;
leftfu=0;
}

//右转函数定义
void turn_right(void){
leftfu=0;
push_value_right=0;
push_value_left=10;
rightzh=0;
rightfu=0;
}

//左轮PWM函数定义,实现波形调制,原理很简单的
void pwm_left(void){
if(push_value_left!=0){
if(pwm_value_left<push_value_left)
leftzh=1;
else
leftzh=0;
if(pwm_value_left>20)
pwm_value_left=0;
}
}

//右轮PWM函数定义
void pwm_right(void){
if(push_value_right!=0){
if(pwm_value_right<push_value_right)
rightzh=1;
else
rightzh=0;
if(pwm_value_right>20)
pwm_value_right=0;
}
}

//定时器函数用来生成PWM波形,隔1ms就从主函数里面跑出来执行中断里面的函数
void timer0() interrupt 1 using 2{
TH0=0XFC;
TL0=0X66;
pwm_value_left++;
pwm_value_right++;
pwm_left();
pwm_right();
}

//主函数
void main(void){
unint l1,l2,m,r1,r2;

//电机初始化,不然还是保留之前的电平可能会导致电机无故反转或者不工作
leftzh = 0;
leftfu = 0;
rightzh = 0;
rightfu = 0;

//按下单片机开关后延时一秒再开始启动
delay(500);
//全力冲,冲过黑线
run();
//保证在冲过黑线之后再开始下面的循环体,防止提前触发stop()函数导致单片机停止
delay(250);

//为定时器选择工作方式、装初值,实现1ms的定时
TMOD=0X01;
    TH0= 0XFC;
    TL0= 0X66;
    //从这里开始中断函数就要开始工作了,不管怎么样1ms之后就要执行一次中断函数里面的内容
    TR0= 1;
    ET0= 1;
    EA = 1;     

//进入死循环,让传感器在这里一直检测
while(1){

	//为单片机引脚赋变量
	l1=left1;
	l2=left2;
	m=middle;
	r1=right1;
	r2=right2;

	//中间亮,半速前进
	//把middle拔下来之后m一直为1,只是太懒了不想改程序。。。
	//传感器检测到黑线就会给单片机返回高电平,就是1了
	if(l1==0&&l2==0&&m==1&&r1==0&&r2==0){
		run_usual();
		num=0;
	}

	//最左边的传感器检测到黑线
	else if(l1==1&&l2==0&&m==1&&r1==0&&r2==0){
		turn_left();
		delay(20);
		num=0;				    
	}

	//左边两个传感器检测到黑线
	else if(l1==1&&l2==1&&m==1&&r1==0&&r2==0){
		left_90();
		delay(150);
		num=0;
	}

	else if(l1==0&&l2==1&&m==1&&r1==0&&r2==0){ 
		turn_left();
		delay(10);
		num=0;
	}
	
	else if(l1==0&&l2==0&&m==1&&r1==1&&r2==1){
		right_90();
		delay(150);
		num=0;
	}	

	
	else if(l1==0&&l2==0&&m==1&&r1==0&&r2==1){
		turn_right();
		delay(20);
		num=0;
	}

	
	else if(l1==0&&l2==0&&m==1&&r1==1&&r2==0){
		turn_right();
		delay(10);
		num=0;
	}

	//因为比赛的黑线比之前练习的黑线粗,所以就把如下的传感器状况当做要向左转90度的条件了
	else if(l1==1&&l2==1&&r1==1&&r2==0){
		left_90();
		delay(150);
		num=0;
	}

	//同上
	else if(l1==0&&l2==1&&r1==1&&r2==1){
		right_90();
		delay(150);
		num=0;
	}

	//最后冲过黑线,但是在检测到黑线的时候不能立刻停,而是要停在两线中间,所以延迟
	else if(l1==1&&l2==1&&r1==1&&r2==1){
		run();
		delay(300);
		stop();
		break;
	}

	
	//要是检测到除以上函数中的传感器状态超过两秒则判定小车跑到了大理石地板上(实验室地板),然后停机
	else{
		num++;
		delay(200);
		if(num==10)
			stop();
                    break;
	}
}
    //从上面的循环跳出来后进入此循环,若没有此循环可能造成从上面循环跳出来后单片机自动复位。
while(1);

}

  • 13
    点赞
  • 3
    评论
  • 33
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 游动-白 设计师:白松林 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值