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

  • 37
    点赞
  • 316
    收藏
    觉得还不错? 一键收藏
  • 19
    评论
以下是c51红外循迹避障小车代码: ```c //头文件 #include <reg52.h> #include <intrins.h> #include "delay.h" #include "lcd1602.h" #include "ir.h" #include "motor.h" #include "ultrasonic.h" //宏定义 #define uchar unsigned char #define uint unsigned int //函数声明 void init(); void display(); //全局变量 uchar mode = 0; //模式选择 uchar speed = 50; //小车速度 uchar distance = 0; //超声波距离 //主函数 void main() { init(); //初始化 while(1) { display(); //显示信息 switch(mode) { case 0: //循迹模式 if(ir() == 0x1c) //左1右1 left_forward(speed); else if(ir() == 0x18) //左0右1 left_forward(speed/2), right_stop(); else if(ir() == 0x1e) //左1右0 left_stop(), right_forward(speed/2); else if(ir() == 0x0c) //左0右0 left_backward(speed/2), right_forward(speed/2); else if(ir() == 0x1d) //左1右2 left_forward(speed/2), right_backward(speed); else if(ir() == 0x19) //左2右1 left_backward(speed), right_forward(speed/2); else if(ir() == 0x1f) //左2右2 left_stop(), right_stop(); break; case 1: //避障模式 if(ultrasonic() < 30) //前方有障碍物 left_backward(speed), right_forward(speed), delay_ms(500); else //前方无障碍物 left_forward(speed), right_forward(speed); break; } } } //初始化函数 void init() { lcd_init(); //LCD1602初始化 ir_init(); //红外循迹初始化 motor_init(); //电机初始化 ultrasonic_init(); //超声波初始化 } //显示函数 void display() { lcd_write_string(0, 0, "Mode: "); lcd_write_string(6, 0, mode == 0 ? "Track" : "Avoid"); lcd_write_string(0, 1, "Speed: "); lcd_write_data(speed/10 + '0'); lcd_write_data(speed%10 + '0'); lcd_write_string(6, 1, "Dist: "); distance = ultrasonic(); lcd_write_data(distance/10 + '0'); lcd_write_data(distance%10 + '0'); } --相关问题--:

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值