用arduino制作蓝牙遥控小车

更新时间:2024-07-10 13:38:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

·1·

现如今是智能手机的天下,很多手机性能已经能够媲美PC了,那么用智能机遥控一台小车自然不在话下了。这里我们用arduino uno开发板配合HC-05蓝牙透传模块制作一辆手机控制的小车,使小车能够发射激光,控制舵机,测量距离并回传到手机,体验一下无线操控的乐趣吧。

首先,手头准备好以下材料:

图10.1 arduino uno板一块 图10.2 arduino sensor sheild v5.0传感器扩展板,带蓝牙直插接口,方便

组装模块

图10.3 L9110电机驱动板一块

(注意:这种是两路电机驱动板,相对于L298N更为小巧,但不支持pwm调速,如果需要驱动四个电机需要两块,这里我们就用两轮驱动)

图10.4 HC-05主从一体蓝牙透传模块 图10.5 超声波测距模块

· 2·

图10.6 普通模拟舵机 图10.7 小车轮胎(带直流电机) 图10.8 激光灯

首先,我们来简单了解一下HC-05蓝牙模块的引脚。

图10.9 HC-05的引脚图示 表10.1 HC-05的引脚定义 1 2 3 4 5 6 VCC GND TXD RXD KEY LED 电源(3.3v~5v) 接地 模块串口发送脚,接uno的RX引脚。 模块串口接收脚,接uno的TX引脚。 用于进入AT指令状态,可直接悬空不做设置。 配对状态输出;配对成功输出高电平,未配对则输出低电平。 这里我们只需要连接1、2、3、4引脚,5、6悬空即可。

模块上电后指示灯快闪则表示模块等待配对,用手机搜索蓝牙能搜索到“H-C-2010-06-01”,默认初始密码为1234,连接后指示灯慢闪开始工作。

注意此模块不需任何程序,与arduino直接连接就能用。

为了使小车能够进入避障模式自动工作,我们使用了US100超声波测距模块,下面简单介绍一下此模块。

·3·

正面图 背面图

图10.10 US100超声波测距模块

此模块分串口工作模式和电平触发工作模式。串口模式下向模块发送0x55,则返回探测到的距离,发送0x50则返回当前温度。电平模式下通过向Triq引脚发送一个大于10us的高电平,模块开始测距,超声波在空中传播的时间就是Echo引脚高电平持续的时间,所以通过检测Echo引脚的高电平持续时间,由公式:(检测的时间*340m/s)/2得出距离。

注意:由于Arduino Uno只有一个串口,所以超声波模块和蓝牙模块共用一个串口时易发生冲突,所以我们在这里采用电平触发模式。

我们可以使用舵机l连续的摆动摇动一面小红旗,也可以在舵机上加一个小毛刷让小车能够边走边扫地,那么下面就简单介绍一下普通模拟舵机的控制原理。

图10.11 模拟舵机

图为市面上常见的模拟舵机,之所以称为模拟舵机,是因为它是通过输入pwm波这种模拟量来控制角度的。舵机每20ms接收一次信号脉冲,高电平范围在0.5ms~2.5ms内舵机响应。

Arduino自带舵机函数库,通过调头文件,我们可以直接引用以下几个常用函数:

1、attach(接口)——设定舵机的接口,uno上只有带‘#’号的引脚具备pwm输出功能

2、write(角度)——用于设定舵机旋转角度的语句,模拟舵机可设定的角度范围是0°到180°,数码舵机角度不受限制。

3、read()——用于读取舵机角度的语句,可理解为读取最后一条write()命令中的值。

· 4·

4、attached()——判断舵机参数是否已发送到舵机所在接口。

5、detach()——使舵机与其接口分离,该接口可继续被用作PWM接口。 下面我们开始编写程:

#include //舵机库头文件 //*****************************************************************************

#define SERVO 3 //定义3引脚接一个舵机

/******************************************************************************

********电机模块引脚定义,电机1的转动方向取决于A1 B1引脚 ***** ********的状态,其中(A1,B1)赋值(1,0)为正转,赋值(0,1) ***** ********为反转,赋值(1,1)或(0,0)则不转 ***** ******************************************************************************/

#define INT_A1 9 #define INT_B1 8 #define INT_A2 11 #define INT_B2 10

/****************************************************************************

*****US100超声波测距模块引脚定义,拔去短路帽后为电平触发模式, ***** *****只需要在Trig/TX管脚输入一个10US以上的高电平,系统便可发出8个 ***** *****40KHZ的超声波脉冲,然后检测回波信号。当检测到回波信号后, 模块 ***** *****还要进行温度值的测量,然后根据当前温度对测距结果进行校正, ***** *****将校正后的结果通过Echo/RX管脚输出。 ***** *****在此模式下,模块将距离值转化为340m/s时的时间值的2倍, ***** *****通过Echo端输出一高电平,可根据此高电平的持续时间来计算距离值。 ***** *****即距离值为:(高电平时间*340m/s)/2。 ***** *****************************************************************************/

#define Triq 5 #define Echo 4

#define LASER 6 //定义激光灯在12引脚 #define LASER_ON digitalWrite(LASER,1) //简化程序,方便操作 #define LASER_OFF digitalWrite(LASER,0) Servo myservo; //定义舵机名称 float distance; //定义测量的距离值 byte BT_COM; //定义蓝牙接收到的参数值 byte BT_PWM=75; //定义输入舵机的角度值 byte LASER_Flag; //判断激光开关的标志值 /***************初始化*******************/

void setup() {

pinMode(Triq,OUTPUT); //设置Triq引脚为输出模式 pinMode(Echo,INPUT); //设置Echo引脚为输入模式

·5·

pinMode(LASER,OUTPUT); //设置激光灯引脚为输出模式 myservo.attach(3); //在引脚3上添加一个舵机 Serial.begin(38400); //蓝牙模块的默认传输速率 }

/**************主函数*******************/

void loop() {

if(Serial.available()) //判断串口是否接收到数据 {

BT_COM=Serial.read(); //读蓝牙串口的数据 switch(BT_COM) //数据选择 {

case'a': forward(); //发送’a’,小车前进 break; case'b': turnright(); //发送’b’,小车右转 break; case'c': backup(); //发送’c’,小车后退 break; case'd': turnleft(); //发送’d’,小车左转 break; case'e': stopcar(); //发送’e’,小车停止 break; case'f': BT_SERVO_REDUCE(); //发送’f’,舵机左转 break; case'g': BT_SERVO_ADD(); //发送’g’,舵机右转 break; case'h': BiZhang(); //发送’h’,小车进入避障模式自动工作 break;

case'i': MY_DISTANCE(); //发送’i’,小车测距并返回给手机距离值 break; case'j': if(LASER_Flag==0)LASER_ON_SWITCH(); else if(LASER_Flag==1)LASER_OFF_SWITCH();

break; //发送’j’,先判断当前激光灯是否亮起,若 //亮起则关闭激光灯,若不亮则打开激光灯 } } }

/***********************************************************************

**********舵机转动函数,由于蓝牙每次接收的是字符,无法直接给 *********** **********舵机输入的pwm值赋值,所以通过下面两个舵机的左右转向*********** **********函数使舵机连续转动。再通过停止命令结束转动,从而使 *********** **********舵机转动到任意角度 ***********

· 6·

***********************************************************************/

void BT_SERVO_REDUCE() //舵机左转

{

while(!Serial.available()) //若无指令到来,则循环执行本条程序 {

BT_PWM-=2;

if(BT_PWM<5)BT_PWM=5; //设置最角度值

myservo.write(BT_PWM); //给舵机输送当前角度值 delay(50); //延时50ms } }

void BT_SERVO_ADD() //舵机右转 {

while(!Serial.available()) //原理同上 {

BT_PWM+=2;

if(BT_PWM>150)BT_PWM=150; myservo.write(BT_PWM); delay(50); } }

/***********激光灯开关函数*************/

void LASER_ON_SWITCH() //打开激光灯 {

LASER_Flag=1; //先判断当前激光灯状态,1则当前关 // 闭,0则当前打开 while(!Serial.available()) {

LASER_ON; //打开激光灯

} }

void LASER_OFF_SWITCH() //关闭激光灯,原理同上 {

LASER_Flag=0;

while(!Serial.available()) {

LASER_OFF; } }

/************测距模块工作函数***********/ void MY_DISTANCE() {

·7·

digitalWrite(Triq,LOW); //先向Triq引脚输送一个大于10us的高电平 delayMicroseconds(2); digitalWrite(Triq,HIGH); delayMicroseconds(10);

distance=pulseIn(Echo,HIGH); //检测Echo高电平持续时间,返回单位是us distance=distance*0.018; //由时间转换成距离

Serial.print(\ //串口打印”distance=”这几个字符 Serial.print(distance); //串口打印测得的距离值 Serial.println(\ //串口打印单位cm

}

/************电机转向函数**************/

void turnleft() //通过给(A1,B1,A2,B2)引脚赋值(0,1,1,0),使小车左转 //赋0表示引脚低电平,赋1表示引脚高电平 {

digitalWrite(INT_A1,0); digitalWrite(INT_B1,1); digitalWrite(INT_A2,1); digitalWrite(INT_B2,0); }

void turnright() //通过给(A1,B1,A2,B2)引脚赋值(1,0,01),使小车右转 //赋0表示引脚低电平,赋1表示引脚高电平 {

digitalWrite(INT_A1,1); digitalWrite(INT_B1,0); digitalWrite(INT_A2,0); digitalWrite(INT_B2,1); }

void forward() //通过给(A1,B1,A2,B2)引脚赋值(0,1,0,1),使小车前进 //赋0表示引脚低电平,赋1表示引脚高电平 {

digitalWrite(INT_A1,0); digitalWrite(INT_B1,1); digitalWrite(INT_A2,0); digitalWrite(INT_B2,1); }

void backup() //通过给(A1,B1,A2,B2)引脚赋值(1,0,1,0),使小车后退 //赋0表示引脚低电平,赋1表示引脚高电平

· 8·

{

digitalWrite(INT_A1,1); digitalWrite(INT_B1,0); digitalWrite(INT_A2,1); digitalWrite(INT_B2,0); }

void stopcar() //通过给(A1,B1,A2,B2)引脚赋值(0,0,0,0),使小车停止 //赋0表示引脚低电平,赋1表示引脚高电平 {

digitalWrite(INT_A1,0); digitalWrite(INT_B1,0); digitalWrite(INT_A2,0); digitalWrite(INT_B2,0); }

/***注意赋值可能因为电机的连接方式不同而有所改动,具体可自己试验得出正确赋值***/

/****************避障模式****************/

void BiZhang() {

while(!Serial.available()) {

MY_DISTANCE(); //引用测距函数先测量距离

delay(50);

if(distance>20&&distance<40)turnleft(); //判断距离后指示小车转向或前进或后退 else if(distance<20)backup(); else if(distance>40)forward(); }

}

注意:

程序中多处用到了 while(!Serial.available())这条语句。为的是能够在下一条指令到底前能够循环运行本条指令动作,能够避免程序运行出错。

按照程序定义的引脚,插上各种模块,组装你的小车: 接下来,手机下载SPP蓝牙串口软件:

打开软件,向后滑动切换到“键盘”,软件提供了12个自定义按钮,长按按钮自定义按钮,名称写你要定义的按钮名称,选择发送“字符”,消息就是程序中定义的要发送的字符。如:名称:前进 消息:a。

·9·

图10.12 小车组装效果图 图10.13 SPP蓝牙串口软件

图10.14 自定义按钮界面 图10.15 按钮编辑器

定义完所有按钮之后,点击右上角的“连接”,搜索设备,注意此时蓝牙模块直接插在扩展板的“bluetooth”插槽内,上电后蓝牙指示灯处于快闪状态表明处于配对等待模式,等待片刻手机会搜索到蓝牙,默认名字为H-C-2010-06-01(注意:不同厂家生产的模块可能名字不同)

· 10·

图10.16 编辑好按钮图示 图10.17 搜索附近蓝牙设备

点击蓝牙名字,输入配对密码,默认为“1234”,需要提到的一点是,当点击“测距”按钮小车测量距离后,返回的距离值会显示在SPP软件的“终端”窗口内,向左滑动进入“终端”窗口,就能看到测量到的距离值啦!

图10.18 输入配对密码 图10.19 距离测量值回传演示 好了,到此为止你的手机蓝牙遥控小车就完工啦,享受无线操作的乐趣吧!

本文来源:https://www.bwwdw.com/article/d5t.html

Top