基于51单片机的蓝牙跟随双模式智能小车

1. 功能介绍

智能小车有两种工作模式,分别是蓝牙避障,超声波跟随,其中模式的切换和小车的调速都是通过蓝牙完成。

2. 所需的材料

1,51单片机开发板x1

2,杜邦线(公对公,母对母,公对母)

3,L298N驱动模块

4,电池一枚,以作为电源(需要大于6v)

5,HC-05蓝牙模块

6,蓝牙小车底盘一个

7,面包板一个

8, 红外避障模块 * 4

9, 超声波模块(HC-SR04) * 1

10,stc89c516RD+(stc89c52不能够使用,定时器的个数不够)

3. 各个模块介绍

L298n

  1. 将左右马达分别接在A,B口,顺序无所谓,可以通过代码来调试。

  1. 将电源正极接到12v处,电源的负极街道GND,在引出5v为单片机供电。

  1. 5v输出使能的跳线帽一定要接上,A,B通道的使能与单片机连接(用于PWM)

红外避障模块

  1. 因为该模块对环境光有一定的感应能力,所以在使用时,尽量不要在阳光和强光下使用。

  1. 其有一个发射管和一个接受管,当遇到障碍物时,输出指示灯会亮起,并且输出接口输出低电平。

  1. 该模块检查距离为2~30cm,角度为35°,可以通过调节电位器来调节检测距离。

HC-05蓝牙模块

六个引脚,我们这里主要用其中的四个(GND,5V,RT,TX),其中RT,TX与单片机输入输出口反接,

我们主要是通过串口通信来实现信号的传递。

超声波模块(HC-R04)

该模块我们主要用于跟随模式,其采用Trig引脚触发,给至少10us的高电平脉冲信号

模块自动发送8个40kHz的方波,自动检测是否有信号返回

有信号返回,通过Echo引脚输出一个高电平脉冲,高电平脉冲持续的时间就是超声波从发射到反射返回的时间。距离=(高电平脉冲时间*340)/2

4. 蓝牙APP的开发

这里使用的是App Inventor进行开发,其主要原理是让手机向蓝牙模块发送一个单字节的数,单片机在通过这个信号进行相应的操作。

界面开发

这里要记得添加蓝牙客户端

逻辑开发

初始化

这一部分是比较通用的,大家可以直接抄写。

按钮的逻辑

这里要注意传输的信号与单片机程序里做出的反应要对应。

5. 代码

电机转动

这里主要是控制电机的的正反转和停止来实现小车的前进,后退,停止和左右转。

car.c

#include sbit IN1 = P1^3;
sbit IN2 = P1^2;
sbit IN3 = P1^1;
sbit IN4 = P1^0;void car_left_motor_forward()  //左电机向前
{IN3=0;IN4=1;
}
void car_left_motor_back()  //左电机向后
{IN3=1;IN4=0;
}
void car_right_motor_forward()  //右电机向前
{IN1=1;IN2=0;
}
void car_right_motor_back()  //右电机向后
{IN1=0;IN2=1;
}
void car_right_motor_stop()  //右电机停止
{IN1=1;IN2=1;
}void car_left_motor_stop()  //左电机停止
{IN4=1;IN3=1;
}

car.h

#ifndef __CAR_H__
#define __CAR_H__void car_left_motor_forward();      //左电机向前
void car_left_motor_back();         //左电机向后
void car_right_motor_forward();     //右电机向前
void car_right_motor_back();        //右电机向后
void car_right_motor_stop();        //右电机停止
void car_left_motor_stop();         //左电机停止
#endif

move.c

#include 
#include "car.h"
void move_go()                      //前进
{car_left_motor_forward();      //左电机向前car_right_motor_forward();     //右电机向前
}void move_back()                      //前退
{car_left_motor_back();      //左电机向后car_right_motor_back();     //右电机向后
}void move_left()                      //左转
{car_left_motor_stop();          //左电机停止car_right_motor_forward();     //右电机向前
}void move_right()                      //右转
{car_left_motor_forward();      //左电机向前car_right_motor_stop();     //右电机停止
}
void move_stop()
{car_right_motor_stop();     //右电机停止car_left_motor_stop();          //左电机停止
}
void move_back_left()                      //左转
{car_left_motor_stop();          //左电机停止car_right_motor_back();     //右电机向前
}
cvoid move_back_right()                      //右转
{car_left_motor_back();      //左电机向前car_right_motor_stop();     //右电机停止
}

move.h

#ifndef __MOVE_H__
#define __MOVE_H__void move_go() ;                     //前进
void move_back();                      //后退
void move_left();                      //左转
void move_right();                      //右转
void move_stop();
void move_back_left();                      //左转
void move_back_right();                     //左转
#endifc

PWM调速

PWM调速主要使用到的是定时器0,通过控制L298N上ENL和ENR两对使能引脚,对电机进行控制。

timer_PWM.c

#include sbit ENL1 = P1^4;
sbit ENL2 = P1^5;
sbit ENR1 = P1^7;
sbit ENR2 = P1^6;
int count = 0;
int speed_left = 0;
int speed_right = 0;
void Timer0Init(void)		//定时器0初始化,100微秒@11.0592MHz
{TMOD &= 0xF0;		//设置定时器模式TL0 = 0xAE;		//设置定时初始值TH0 = 0xFB;		//设置定时初始值TF0 = 0;		//清除TF0标志TR0 = 1;		//定时器0开始计时ET0=1;EA=1;
}
void time() interrupt 1
{TL0 = 0xAE;		//设置定时初始值TH0 = 0xFB;		//设置定时初始值count++;count%=100;if(count>=speed_left){ENL1 = 0;ENL2 = 0;}else{ENL1 = 1;ENL2 = 1;}if(count>=speed_right){ENR1 = 0;ENR2 = 0;}else{ENR1 = 1;ENR2 = 1;}}

###timer_PWM.h

#ifndef __TIMER_PWM_H__
#define __TIMER_PWM_H__
extern int count;
extern int speed_left;
extern int speed_right;void Timer0Init(void);		//定时器0初始化,100微秒@11.0592MHz
void time(); #endif

蓝牙模块

  1. 模式的转换,主要是通过pattern变量的值来判断,其为1时表示为蓝牙避障模式,其为2时为超声波跟随模式。

  1. 蓝牙主要使用的是串口通信,我们要先对串口进行初始化,在通过SBUF接收到值进行响应。

bluetooth.c

#include 
#include "move.h"
#include "timer_PWM.h"
unsigned int key = 0;		//接受蓝牙数据
unsigned int pattern = 0;   //模式选择
unsigned int launch = 0;	//跟随停止和开始
void bluetooth_UartInit()		//9600bps@11.0592MHz
{PCON &= 0x7F;		//波特率不倍速SCON = 0x50;		//8位数据,可变波特率TMOD &= 0x0F;		//设置定时器模式TMOD |= 0x20;		//设置定时器模式TL1 = 0xFD;		//设置定时初始值TH1 = 0xFD;		//设置定时重载值ET1 = 0;		//禁止定时器%d中断TR1 = 1;		//定时器1开始计时ES=1;EA=1;
}
void bluetooth_move_take(unsigned int key)
{switch(key){case 1:if(pattern == 1){move_go();} break;        //前进case 2:if(pattern == 1){move_back();} break;      //后退    case 3:if(pattern == 1){move_left();}break;       //左转    case 4:if(pattern == 1){move_stop(); }break;      //停止case 5:if(pattern == 1){move_right(); }break;     //右转case 6:speed_left = 50;speed_right = 50;break;  //速度1case 7:speed_left = 100;speed_right = 100;break;//速度2  case 8:move_stop();pattern = 1; break;			//蓝牙避障模式case 9:launch = 0;move_stop();pattern = 2; break;		//超声波跟随模式	case 10:if(pattern == 2){launch = 1;move_stop();}break;						//开始跟随case 11:if(pattern == 2){launch = 0;move_stop();} break;						//停止跟随}
}
void bluetooth_uart_pass() interrupt 4
{if(RI==1){key = SBUF;if(key <= 5){move_stop();}bluetooth_move_take(key);RI = 0;}}

bluetooth.h

#ifndef __BLUETOOTH_H__
#define __BLUETOOTH_H__void bluetooth_UartInit();
void bluetooth_move_take(unsigned int key);
void bluetooth_uart_pass();
extern unsigned int key;
extern unsigned int pattern;
extern unsigned int launch;
#endif

红外避障

红外模块四个角各一个,当前面遇到障碍时,小车后退并停止,当后面遇到障碍时,小车向前行驶并停止。

sbit PIR1 = P0^0;
sbit PIR2 = P0^1;
sbit PIR3 = P0^2;
sbit PIR4 = P0^3;
void PIR_work()                 //红外避障模块
{if(PIR1 == 0 || PIR2 == 0){move_stop();move_back();Delay(150);move_stop();}if(PIR3 == 0 || PIR4 == 0){move_stop();move_go();Delay(150);move_stop();}
}

超声波模块

该模块使用的是定时器2,但其只用于计时,不触发中断。

当Echo接受到高电平时,定时器开启,高电平结束,定时器关闭。

UT.C

#include 
#include 
sbit Trig = P2^1;
sbit Echo = P2^0;
void Delay50ms()		//@11.0592MHz
{unsigned char i, j;i = 90;j = 163;do{while (--j);} while (--i);
}void Delay15us()		//@11.0592MHz
{unsigned char i;i = 4;while (--i);
}void Timer2_Init(void)        
{T2MOD = 0;    //初始化模式寄存器T2CON = 0;    //初始化控制寄存器TL2 = 0x00;    //设置定时初值TH2 = 0x00;    //设置定时初值TR2 = 0;        //定时器2关闭计时
}
int judge(float cm , float number)
{float n = cm - number;if(n <= 3 && n >= -3)     {return 1;          //停止   }else if(n < -3){return 2;			//后退   }else if(n > 3){return 3;			//前进    }return 1;
}
void Delay25ms()		//@11.0592MHz
{unsigned char i, j;i = 45;j = 208;do{while (--j);} while (--i);
}int UT_work()
{float number = 8;float s = 0;float cm = 0;int n = 0;Trig = 0;Echo = 0;Trig = 1;Delay15us();Trig = 0;		while(!Echo);	TR2 = 1;	while(Echo);TR2 = 0;			//关闭计时器s = (float)((TH2 * 256 + TL2) * 0.000001);cm = s * 340 / 2 * 100;		n =judge(cm , number);		cm = 0;s = 0;		TH2 = 0x00;TL2 = 0x00;			//清除定时器数值Delay25ms();return n;}// 

UT.H

#ifndef __UT_H__
#define __UT_H__
void Timer2_Init(void);
int judge(float cm , float number);
int UT_work();
#endif

跟随模式的红外转弯

该模式下,主要使用PIR1和PIR2前面两个红外避障模块。

PIR1和PIR2全部输出低电平或高电平时,则继续保持原来的运动。

PIR1为低电平时,PIR为高电平时,说明跟随物在小车左端,小车左转。

PIR1为高电平时,PIR为低电平时,说明跟随物在小车右端,小车右转。

sbit PIR1 = P0^0;
sbit PIR2 = P0^1;
void PIR_turn()			//红外拐弯
{if(PIR1 == 0 && PIR2 == 1)  //右拐{move_left();}if(PIR1 == 1 && PIR2 == 0)  //左拐{move_right();		}}

延迟函数

Delay.c

#include 
#include void Delay(unsigned int a)		//@11.0592MHz
{unsigned char i, j;while(a--){_nop_();i = 2;j = 199;do{while (--j);} while (--i);}	
}
void Delay10us()		//@11.0592MHz
{unsigned char i;i = 2;while (--i);
}

Delay.h

#ifndef __DELAY_H__
#define __DELAY_H__
void Delay(unsigned int a);
void Delay10us();
#endif

main.c

#include 
#include "car.h"
#include "move.h"
#include "DELAY.H"
#include "TIMER_PWM.H"
#include "bluetooth.h"sbit PIR1 = P0^0;
sbit PIR2 = P0^1;
sbit PIR3 = P0^2;
sbit PIR4 = P0^3;
void PIR_work()                 //红外避障模块
{if(PIR1 == 0 || PIR2 == 0){move_stop();move_back();Delay(150);move_stop();}if(PIR3 == 0 || PIR4 == 0){move_stop();move_go();Delay(150);move_stop();}
}
void PIR_turn()			//红外拐弯
{if(PIR1 == 0 && PIR2 == 1)  //右拐{move_left();}if(PIR1 == 1 && PIR2 == 0)  //左拐{move_right();		}}void main()
{int n = 0;Timer0Init();bluetooth_UartInit();Timer2_Init();speed_left=50;speed_right=50;while(1){if(pattern == 1){PIR_work();}if(pattern == 2){if(launch){PIR_turn();n = UT_work();switch(n){case 1:move_stop();break;case 2:move_back();break;case 3:move_go();break;}}}}
}

6. 成品展示

外观


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部