基于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
将左右马达分别接在A,B口,顺序无所谓,可以通过代码来调试。
将电源正极接到12v处,电源的负极街道GND,在引出5v为单片机供电。
5v输出使能的跳线帽一定要接上,A,B通道的使能与单片机连接(用于PWM)
红外避障模块
因为该模块对环境光有一定的感应能力,所以在使用时,尽量不要在阳光和强光下使用。
其有一个发射管和一个接受管,当遇到障碍物时,输出指示灯会亮起,并且输出接口输出低电平。
该模块检查距离为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 蓝牙模块
模式的转换,主要是通过pattern变量的值来判断,其为1时表示为蓝牙避障模式,其为2时为超声波跟随模式。
蓝牙主要使用的是串口通信,我们要先对串口进行初始化,在通过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. 成品展示
外观
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
