从零开始DIY一辆蓝牙遥控小车
关键词:遥控小车;Arduino;直流电机;L298N电机驱动板;串口蓝牙模块
一、简介
本项目使用Arduino实现了一个最小功能的蓝牙遥控小车
整车效果图
电路原理图
制作流程主要分为四个部分:1.组装小车;2.烧写代码;3.调试蓝牙;4.整车测试
其中,前三个部分的耦合性很低,每个部分可以独立操作和调试
二、实现过程
1. 组装小车
所需环境:十字螺丝刀×1
车身零件全家福
1.1 电机绕线及固定
直流电机
本项目使用直流电机(即常见的玩具四驱车的马达)作为小车的驱动装置,直流电机的特点是:只要电机的两极有电势差,电机就可以运转,反接则逆转,两极电势差为零时停止运转。
电极绕线
这款直流电机没有预先引出导线,所以需要我们手工连接导线:
首先,把杜邦线裸露出铜线的一段塞入电机铜电极的小孔中;
然后把探出的那部分铜线弯折一下,用指尖压住弯折处两段的铜线,旋转几圈,让两段铜线缠绕在一起;
这样保证了铜线和电极的充分接触,省去了焊接的麻烦。
注:没有要求电极和不同颜色导线的对应关系,可以随意连接。
测试电机
把两个电机和4根杜邦线连接完毕之后就可以对电机进行简单的测试:只要把杜邦线的两头接触18650锂电池的两极即可,可以观察到电机开始快速转动,如果调换电池的电极,会发现电机发生反转。
固定电机
把两个固定电机用的插销插到车底盘上对应的空槽中,然后将长螺丝穿过,用手轻轻旋上螺母
固定电机
1.2 固定驱动板和万向轮
L298N工作原理
由上文的内容可知,直流电机只要一极接高电平,一极接低电平即可转动,大家也知道Arduino的数字输出引脚可以直接输出高电平或低电平,但我们一般不直接将Arduino连接到直流电机上,因为Arduino板的电流负载是有限的,直接连接电极容易引发电流过载,导致Arduino板被烧坏,所以我们选用L298N这块转接驱动板,作为Arduino和电机之间的桥梁
针脚对应关系如下图,其中in1 ~ in4对应OUT1~OUT4,我们将Arduino的数字输出针脚接到in1 ~ in4上,即可将对应的高低电平信号映射到OUT1~OUT4的接线柱上,从而控制电机
L298N除了有转换信号的功能外,内部还有稳压模块,可以接受7 ~ 12V的输入,然后转换出一个5V的输出,分别对应这下部的3个接线柱,我们之后会将18650电池组的正极接到 7 ~ 12V输入的接线柱上,负极接地,然后用L298N提供的5V输出和接地作为正负极来为Arduino板供电
L298N针脚对应关系图
固定驱动板和接线
固定驱动板的方法很简单,我们只用两组螺丝螺母,固定到下图所示的位置,注意螺丝不要扭太紧
固定驱动板
把杜邦线固定到接线柱上
使用螺母固定好L298N之后,需要将电极引出的杜邦线的针脚固定到L298N的接线柱上,方法是先用螺丝刀松开接线柱内的螺丝,然后塞入杜邦线的针脚,最后再用螺丝上紧,如下图
将杜邦线固定到接线柱上
这部分完成
1.3 装配18650电池盒和电源开关
18650锂电池
18650型锂电是电子产品中比较常用的可充电锂电池,单节电压一般为3.7V,常在充电宝或笔记本电脑的电池中作为电芯使用。其型号的定义法则为:如18650型,即指电池的直径为18mm,长度为65mm,0代表是圆柱体型的电池。*
选用原因
由于Arduino UNO的标准输入电压为5 ~ 9V,L298N驱动板的输入电压为7 ~ 12V,所以本项目选用了两节18650锂电池串联(串联后总电压为7.4V)的方式作为小车的电源,同时给Arduino和电机驱动板供电
安装电池盒,连接开关
安装电池盒和开关
给船型开关的两个引脚缠线,这部分需要耐心些,注意两个引脚的导线不要接触到一起,否则开关就会失效
这部分需要耐心些
最后用一个螺丝螺母的组合穿过底板(注意穿过的孔的位置)固定电池盒和用于支撑Arduino的铜柱(用螺母固定),还要在L298N的接线柱上增添两条用于给Arduino供电的杜邦线,安装的时候注意牢固
注意孔的位置
1.4 固定Arduino,连接剩余杜邦线
固定Arduino,根据原理图连线
然后可以用一个螺丝固定Arduino到车身上,并根据电路原理图连接从L298N给Arduino供电的杜邦线
连接供电线路
连接给L298N的信号线
1.5 通电调试
无程序测试电机方法
可以用Arduino板上固定的3.3V和GND输出测试L298N
用Arduino固定的3.3V和GND输出测试L298N
按照原理图连线
2. 烧写代码
2.1 使用Arduino IDE向开发板上传代码
连接Arduino和PC机,使用Arduino IDE打开本项目的代码文件,在【工具】菜单中选择所需要上传的端口,然后点击上传
2.2 使用Arduino IDE串口工具进行调试
底部状态栏显示上传成功后,保持Arduino和PC机连接的状态,点击右上角的串口监视器,出现一个小程序框
上传成功后,打开串口监视器
串口监视器程序框的顶部是一个输入栏,在这里我们可可以对上传到板上的程序进行测试,在输入栏输入“w”后,点击【发送】按钮,会发现文本框里可以从Arduino得到相应的反馈(这是在源代码中设置的),然后还可以依次测试发送“a”、“d”、“s”、“x”这几种消息,如均正常,则程序无误。
使用了键盘的W、A、S、D、X键位的布局来与前进、左转、右转、停止和后退这几个概念做对应
在串口监视器中测试
2.3 连接车身调试
如果小车车身安装好了,这时可以把Arduino和小车车上的引脚按照原理图连接好,然后还通过上一个步骤的方法,在PC机上用串口监视器给Arduino发送消息,观察轮胎的运转情况,看是否按照程序的描述运转,如果不能,可能是在电机的引脚或者连线的时候出现偏差,解决方法有三种:
修改源代码中控制轮的变量与数字引脚的对应关系
修改Arduino到L298N信号线的连线
修改L298N和电机之间的连线
每种方法都可以解决小车不能按照规定接受消息的方式运转的问题,请同学们自由选择
烧录代码和测试
校正轮胎转动方向
3. 调试蓝牙
关于HC-05和调试
HC-05是一个串口蓝牙通信模块,内部的芯片上封装了蓝牙通信协议以及用于调试的AT指令集,功能是:可以通过蓝牙接受数据,再从串口通信协议从针脚发送出去,也可以从串口接受消息,再经过芯片用蓝牙发送出去,相当于通信无线到有线通信的一个桥梁。
AT指令是应用于终端设备与PC应用之间的连接与通信的指令。AT即Attention。每个AT命令行中只能包含一条AT指令;对于AT指令的发送,除AT两个字符外,最多可以接收1056个字符的长度(包括最后的空字符)
我们将蓝牙模块(HC-05)通过转换器(TTL转USB)连接到电脑上, 在电脑上使用串口调试软件(CoolTerm)向蓝牙模块发送特定的AT指令来对蓝牙模块的一些参数,比如设备名称、配对码、主从角色等等。
3.1 将 串口蓝牙模块(HC-05) 与PC相连接
使用 USB转TTL模块 连接 HC-05,连线如下图
连线:GND--GND;5V--5V;RX--TX;TX--RX
要按住RST键连接USB,才能进入AT调试模式
按住蓝牙模块上的RST键,插入PC机的USB口,松开RST键,进入AT指令调试模式,标志是蓝牙模块上的红色指示灯慢速闪烁
如果不按住RST键直接连接USB口的话,红色指示灯会快速闪烁,标志进入蓝牙连接模式
3.2 打开CoolTerm,建立串口通信连接
将蓝牙模块连接到PC上后,查看设备管理器,打开CoolTerm软件,点击【Options】图标进入选项设置,【Port】选项选择设备管理器中CH340对应的端口(根据电脑的不同,不一定是COM5),【Baudrate】修改为 38400,然后点击底部的【OK】确定
进入设置,修改端口和波特率
设置完成后,点击软件上方的【Connect】图标
3.3 使用AT指令调整蓝牙模块的参数
【Connect】成功后,依次点选菜单栏上的【Connection】→【Send String】,会出现一个消息发送框,通过这个可以向蓝牙模块发送AT指令,如下图:
输入“AT+回车”
注意,使用AT指令的时候一定要回车到第二行再点击【Send】发送
AT指令集
分别输入如下指令,查看设备的当前状况
“AT”:回复“OK”,说明设备正常。
“AT+UART”:查看设备的串口通信参数,本实验模块蓝牙模式的波特率为9600
“AT+ADDR”:查看设备的蓝牙地址
“AT+ROLE”:查看设备的主从转台,“0”为从模式,“1”为主模式
“AT+PSWD”:查看设备当前的配对码,默认是1234
“AT+NAME”:查看设备当前的名称,默认是 HC-05
“AT+RESET”:重启设备
用AT指令配置设备
发送完上述AT指令查看完设备信息后,需要根据你的情况修改一些设备信息,方法是,在相应的AT指令后加“=”号,输入要修改的信息即可,本项目主要修改信息如下例
“AT+ROLE=0”:设置蓝牙设备为从模式
“AT+PSWD=123456”:修改配对码为123456,用户自定义
“AT+NAME=Carduino”:修改名称为Carduino,用户自定义
“AT+UART=9600,0,0”:修改蓝牙工作状态波特率为9600,无停止位和校验位
注意!每次都要回车到第二行再点击“Send”
由于硬件存在一定的缺陷,HC-05蓝牙模块在设置【NAME】参数时会有些问题,可能需要多设置几次
如果改名不成功,请使用“AT+ADDR”查询蓝牙设备地址,在手机上根据搜索到的设备地址来连接蓝牙模块
3.4 下载安装BlueSPP软件,设置按键消息
BlueSPP是一个手机端的蓝牙串口通讯通信工具,可以连接蓝牙设备,通过串行通讯协议发送消息
打开APP
进入BlueSPP
连接设备
点右上角图标搜索设备
连接
输入事先配置的配对码
APP首页可以在聊天窗口中向设备发送消息
可以发送消息
右滑,进入自定义键盘页面,每个按钮的“名称”可定义,按钮对应的“按下”,“松开”事件都可配置成发送特定消息
配置按钮“前进”
配置按钮“左转”
配置按钮“后退”
配置结束
按键名称 按下发送 松开发送
前进 w
后退 x s
左转 a w
右转 d w
停止 s
上表为笔者的配置,大家可以根据自己的控制习惯进行设置
4. 整车测试
终于到激动人心的最终环节了
4.1 给Arduino连接蓝牙模块
连接蓝牙
4.2 使用独立电源测试
打开开关,L298N、Arduino、和HC-05蓝牙模块上的能正常闪烁,就可以在手机端用BlueSPP连接蓝牙,让小车下地开始真正的遥控测试了
三、参考代码
char serial_data; // 将从串口读入的消息存储在该变量中
int wheel_R_1 = 5; // 右轮in1对应Arduino 5号引脚
int wheel_R_2 = 6; // 右轮in2对应Arduino 6号引脚
int wheel_L_1 = 9; // 左轮in1对应Arduino 9号引脚
int wheel_L_2 = 10; // 左轮in2对应Arduino 10号引脚
void setup(){
// 配置所有控制轮的引脚为输出
pinMode(wheel_L_1, OUTPUT);
pinMode(wheel_L_2, OUTPUT);
pinMode(wheel_R_1, OUTPUT);
pinMode(wheel_R_2, OUTPUT);
// 配置串口波特率
Serial.begin(9600);
}
void loop(){
if(Serial.available()){
// 将从串口读入的消息存储在该变量中
serial_data = Serial.read();
// 按照 w a s d x 在键盘上的布局来控制车
// 如果接收到 w ,直行
if( serial_data == 'w' ){
move_ahead( );
Serial.println("The car is moving ahead!");
}
// 如果接收到 x ,后退
else if( serial_data == 'x'){
move_backwards( );
Serial.println("The car is moving backwards!");
}
// 如果接收到 a ,左转
else if( serial_data == 'a'){
turn_left( );
Serial.println("The car is turning left!");
}
// 如果接收到 d ,右转
else if( serial_data == 'd'){
turn_right( );
Serial.println("The car is turning right!");
}
// 如果接收到 s ,停止
else if( serial_data == 's'){
stop();
Serial.println("The car is stopping!");
}
}
}
// 定义直行函数
void move_ahead(){
digitalWrite( wheel_L_1, HIGH);
digitalWrite( wheel_L_2, LOW);
digitalWrite( wheel_R_1, HIGH);
digitalWrite( wheel_R_2, LOW);
}
// 定义后退函数
void move_backwards(){
digitalWrite( wheel_L_1, LOW);
digitalWrite( wheel_L_2, HIGH);
digitalWrite( wheel_R_1, LOW);
digitalWrite( wheel_R_2, HIGH);
}
// 定义左转函数
void turn_left(){
digitalWrite( wheel_L_1, LOW);
digitalWrite( wheel_L_2, LOW);
digitalWrite( wheel_R_1, HIGH);
digitalWrite( wheel_R_2, LOW);
}
// 定义右转函数
void turn_right(){
digitalWrite( wheel_L_1, HIGH);
digitalWrite( wheel_L_2, LOW);
digitalWrite( wheel_R_1, LOW);
digitalWrite( wheel_R_2, LOW);
}
void stop(){
digitalWrite( wheel_L_1, LOW);
digitalWrite( wheel_L_2, LOW);
digitalWrite( wheel_R_1, LOW);
digitalWrite( wheel_R_2, LOW);
}