51蓝牙红外循迹避障小车+代码

 设计背景:

本次设计主要是为了学校的一个电子竞赛才做的这一个小项目,这也是我刚学习51单片机以来做的第一个大制作。其实这个制作的原理很简单,但实际做出来却花了一些时间,下面就简单地给大家介绍一下我们的制作,也为各位网友作为一个参考。

使用到的模块:

51单片机  L298N电机驱动模块  红外传感器模块  hc05蓝牙模块  普通直流电机

实现的原理:

 电路设计:

成品展示:

 

 

 程序设计: 

L298N驱动直行转向程序,这里用的是定时器0作为PWM输出。关于L298N和定时器可以在网上查找资料,知道如何使用,这里就不给大家详细介绍了。

#include "xunji.h"
#include "reg52.h"

uchar PWMCnt1;
uchar PWMCnt2;
uchar cntPWM1;
uchar cntPWM2;

//uchar PWMA;
//uchar PWMB;

void Delay(int xms)		//@12.000MHz
{ while(xms--)
	{unsigned char i, j;

	i = 2;
	j = 239;
	do
	{
		while (--j);
	} while (--i);
 }
}
void Timer0_init()
{
	TMOD &=0xF0;
	TMOD |=0X01;//使用定时器0
	
	TH0 = 0xFF;
	TL0 = 0xA3;
	
	EA=1;//全局中断位
	ET0=1;//定时器0中断允许位
	TR0=1;//定时器0运行允许位
}
void turnright1()		   //右转
{
	IN1 = 0;	//右轮反转
	IN2 = 1;

	IN3 = 0;	//左轮正转
	IN4 = 1;
	cntPWM1 = 50;
	cntPWM2	= 45;
}

void turnRight2()		   //右转
{
	IN1 = 0;	//右轮反转
	IN2 = 1;

	IN3 = 0;	//左轮正转
	IN4 = 1;
	cntPWM1 = 45;
	cntPWM2	= 40;
}

void turnleft1()				//左转
{
	IN1 = 1;
	IN2 = 0;   	//右轮正转

	IN3 = 1;
	IN4 = 0;   	//左轮反转
	cntPWM1 = 45;
	cntPWM2	= 50;
}			  	

void turnLeft2()				//左转
{
	IN1 = 1;
	IN2 = 0;   	//右轮正转
 
	IN3 = 1;
	IN4 = 0;   	//左轮反转
	cntPWM1 = 40;
	cntPWM2	= 45;
}	
	
void forward()				 //前进
{
	IN1 = 1;
	IN2 = 0;   	//右轮正转

	IN3 = 0;   	//左轮正转
	IN4 = 1;

	cntPWM1 = 26;
	cntPWM2	= 25;
}

void backward()					 //后退
{
	IN1 = 0;	//右轮反转
	IN2 = 1;

	IN3 = 1;
	IN4 = 0;	//左轮反转
	cntPWM1 = 26;
	cntPWM2	= 25;
}

void Stop()					  //停止
{
	IN1 = 0;
	IN2 = 0;

	IN3 = 0;
	IN4 = 0;
}

void interrupttimer0() interrupt 1
{
	TH0 = (65536 - 50)/256;
	TL0 = (65536 - 50)%256;

	PWMCnt1++;
	PWMCnt2++;
	
	PWMCnt1%=100;
	PWMCnt2%=100;
	
	if(PWMCnt1<=cntPWM1)
	{
		ENA=1;
	}
	else
		ENA=0;
	
	if(PWMCnt2<=cntPWM2)
	{
		ENB=1;
	}
	else
		ENB=0;
	
//	
//	if(PWMA<=cntPWM1)
//	{
//		ENA=1;
//	}
//	else
//		ENA=0;
//	
//	if(PWMB<=cntPWM2)
//	{
//		ENB=1;
//	}
//	else
//		ENB=0;
}

循迹模块程序,这里利用是4个红外传感器返回的高低电平来判断黑线的位置,从而驱使小车的直行与转向。程序比较繁杂,其实有很多是多余的,还可以进行一些简化,不需要4个传感器都要判断是否输出高低,另外直行的程序最好放在前面,并且再加上else,这样的话,前面判断成功了就不用再去执行后面的程序,可以缩短cpu消耗的时间。

void XunJi()

{
	unsigned char flag = 0;
  
	if((left1 == 0)&&(left2 == 0)&&(right1 == 0)&&(right2 == 0))   //0 0 0 0
	  flag = 0;

	if((left1 == 0)&&(left2 == 0)&&(right1 == 0)&&(right2 == 1))   //0 0 0 1
		flag = 1;

	if((left1 == 0)&&(left2 == 0)&&(right1 == 1)&&(right2 == 0))   //0 0 1 0
		flag = 0;

	if((left1 == 0)&&(left2 == 0)&&(right1 == 1)&&(right2 == 1))   //0 0 1 1
		flag = 2;

	if((left1 == 0)&&(left2 == 1)&&(right1 == 0)&&(right2 == 0))   //0 1 0 0
		flag = 0;

	if((left1 == 0)&&(left2 == 1)&&(right1 == 0)&&(right2 == 1))   //0 1 0 1
		flag = 4;

	if((left1 == 0)&&(left2 == 1)&&(right1 == 1)&&(right2 == 0))   //0 1 1 0
		flag = 0;
	
	if((left1 == 0)&&(left2 == 1)&&(right1 == 1)&&(right2 == 1))    //0 1 1 1
		flag = 1;
	
	if((left1 == 1)&&(left2 == 0)&&(right1 == 0)&&(right2 == 0))   //1 0 0 0
		flag = 3;
	
	if((left1 == 1)&&(left2 == 0)&&(right1 == 0)&&(right2 == 1))   //1 0 0 1
		flag = 0;
	
	if((left1 == 1)&&(left2 == 0)&&(right1 == 1)&&(right2 == 0))   //1 0 1 0
		flag = 2;
	
	if((left1 == 1)&&(left2 == 0)&&(right1 == 1)&&(right2 == 1))   //1 0 1 1
		flag = 0;
	
	if((left1 == 1)&&(left2 == 1)&&(right1 == 0)&&(right2 == 0))   //1 1 0 0
		flag = 4;
	 
	if((left1 == 1)&&(left2 == 1)&&(right1 == 0)&&(right2 == 1))   //1 1 0 1
		flag = 0;

	if((left1 == 1)&&(left2 == 1)&&(right1 == 1)&&(right2 == 0))   //1 1 1 0
		flag = 3;
	
	if((left1 == 1)&&(left2 == 1)&&(right1 == 1)&&(right2 == 1))   //1 1 1 1
		flag = 6;
	
	switch(flag)
	
{
		case 0:forward();break;
	
		case 1:turnright1();break;
	
		case 2:turnright2();break;
	
		case 3:turnleft1();break;
	
		case 4:turnleft2();break;
	
		case 5:backward();break;
	
	  default:stop();break;
	}
}

避障模块程序,这里是利用的小车上边的3个红外传感器来识别前方障碍物,根据障碍物位置来做如何的转向,从而实现避障。

void bizhan()  //循迹+避障
{
	if((bizh1==1)&&(bizh2==1)&&(bizh3==1))
		XunJi();
	if((bizh1==0)||(bizh2==0)||(bizh3==0))
	{
		stop();
		Delay (500);
		turnright2();
		Delay (60); 
	}
}
	
void bizh()    //避障
{
	if((bizh1==1)&&(bizh2==1)&&(bizh3==1))
		forward();
	if((bizh1==0)&&(bizh2==1)&&(bizh3==1))
		turnleft2();
	if((bizh1==1)&&(bizh2==0)&&(bizh3==1))
		turnright2();
	if((bizh1==1)&&(bizh2==1)&&(bizh3==0))
		turnright2();
	if((bizh1==0)&&(bizh2==0)&&(bizh3==0))
	  turnleft2();
	if((bizh1==0)&&(bizh2==0)&&(bizh3==1))
		turnleft1();
	if((bizh1==1)&&(bizh2==0)&&(bizh3==0))
		turnright1();
}

蓝牙控制程序

#include "reg52.h"
#include "bluetooth.h"

uchar temp;

uchar speedA;
uchar speedB;

void uart_init()//这是对蓝牙串口进行初始化,不是定时器1
{
	TMOD &=0xF0;
	TMOD |=0x21;//定时器1采用方式2 8位初值自动重装
	SCON=0x50;
	
	TL1=0xFD;
	TH1=0xFD;
	
	PCON=0x00;//电源控制寄存位
	
	ES=1;//串口通信运行允许位
	TR1=1;//定时器1运行
}

//void sendbyte(uchar c)
//{
//	SBUF=c;//发送数据
//	
//	while(!TI);//没有发送完一直执行这个空语句
//	/*发送字节完成后TI 变成1,则需要最后把他置零;RI也一样*/
//	TI=0;//发送串口中断判断位
//}

void uart_interrupt() interrupt 4
{
	if(RI)//串口中断允许位
	{
		temp=SBUF;//取出数据
		RI=0;//取出数据后RI变为1,需要最后把他置零
		
	    quick();
		slow();
	}
}

void quick()//蓝牙加速
{
	speedA*=2;
	speedB*=2;
}

void slow()//蓝牙减速
{
	speedA%=2;
	speedB%=2;
}

小车的主程序

#include "reg52.h"
#include "xunji.h"
#include "bluetooth.h"

extern uchar temp;//用于切换模式和蓝牙指令

void start();

void main()
{
	Timer0_init();
	uart_init();
	
	while(1)
	{
		start();
	}
	
}

void start()
{
	switch(temp)
	{
		case 'e':bizhan();break;
		case 'f':forward1(); break;
		case 'a':quick();break;
		case 'b':backward2(); break;
		case 'c':slow();break;
		case 'r':turnleft(); break;
		case 'l':turnright(); break;
		case 's':stop(); break;
		case 'k':bizh();break;
		default :stop();break;//如果传输了一个这些之外的字母,则stop()
	}
}

最后

程序只是作为一个参考,真正调试还需要根据实际情况为准。比如PWM的调试,循迹模块程序的简化等。另外上边展示的主要是一些重要的模块程序,详细的可以点击下面的连接自己提取。最后,希望大家都能做出自己满意的小车。

链接:https://pan.baidu.com/s/11-6rN-bxYrJlRpDWrP0K4g 
提取码:armc

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>