手机与Arduino蓝牙串口通讯实验及完整例程
安卓手机与Arduino之间采用蓝牙串口通讯,是很多智能装置和互动装置常用的控制方法,简单而有效,无需网络环境,很实用的技术。
实验采用Arduino UNO板,加了一块1602LCD屏做显示(因为只有一个串口,用来做蓝牙通讯,再用串口助手不方便,也不直观)。蓝牙模块使用十几元一个的HC-06。一个LED接在11脚作为演示。手机端做了一个简单的界面,有按键和滑动条。用按键控制LED点亮和熄灭,演示开关量控制。滑动条控制LED的亮度,演示模拟量控制(0-100范围)。LCD屏实时显示传送的数据。模块接线按标准接法,大家都玩过的,请参考各种教程或书籍。硬件图片如下。
<ignore_js_op>

关于蓝牙串口通讯的几个要点:
1. Arduino的串口,print()和println()函数都是用ASCII字符的方式传送数据,无论是int、float还是string,都自动转换成ASCII码传送。其中println()函数在传送的数据后面加了回车和换行符("\r"和"\n")。换行符正好可以作为结束符来让手机端识别。
2. 蓝牙串口是异步传输方式,每次Serial.read()只读一个字节,在一个loop()循环中可能收不全一条数据信息,必须要有一个全局变量来收集接收到的字符。如果要通讯可靠,使用结束符来确定收到了一条完整的信息,是非常必要的。手机端也是一样。
3. 例程中用的Serial.parseInt()函数,作用是在收到的字符流中,找到数字字符,并累积在一起,直到收到一个非数字字符时,将前面收到的数字字符转换成一个整数。如果要传送多个数值,中间用逗号等分隔符隔开即可。比如三个数值,”12,325,993“,后面加一个自定义的结束符,作为字符串发给Arduino。(例程中用字符"X”作为结束符。)这样接收数据完整而可靠。接收float可以用Serial.parseFloat()函数,用法一样。
安卓手机端可以用蓝牙串口助手APP。但是建议自己写一个简单的APP,才真正完整的知道怎么通讯。再说了,如果真的做一个产品或服务,总是要自己做手机端APP的,蓝牙串口助理不能当产品用。
Arduino完整例程如下。IDE 1.6.3编译通过,运行正常。欢迎大家修改使用,完全开源。例程内有详细注释。
|
/* 本例程演示从手机蓝牙串口接收指令,点亮或熄灭11脚的LED,或者调整亮度。
|
|
|
* 接收指令格式:“101X”点亮,“102X"熄灭,”000X"调整亮度。(000为0-100的整数,表示亮度值,X是结束符。)
|
|
|
* 串口是异步接收的,用parseInt()查找第一个有效整数,检测到结束符后开始处理。
|
|
|
* 接收数据显示在1602LCD屏上。
|
|
|
* 点亮或熄灭LED后,将收到数据回传给手机。用pringln()函数,数据后面加了"\r"和"\n"两个字符,可以用作结束符。
|
|
|
* 串口传送的是ASCII字符,数据格式可以自动转换。
|
|
|
*/
|
|
|
#include <Wire.h> // 包含LCD库。
|
|
|
#include <LiquidCrystal_I2C.h>
|
|
|
LiquidCrystal_I2C lcd(0x27,16,2); // 初始化LCD对象,地址为0x27,每行16个字符,共两行。
|
|
|
int p; // 定义整数型全局变量,保存接收的数据。
|
|
|
void setup() {
|
|
|
lcd.init(); // 初始化LCD。
|
|
|
lcd.backlight(); // 打开LCD背光。
|
|
|
Serial.begin(9600); // 打开串口(蓝牙)
|
|
|
pinMode(11,OUTPUT); // 定义11脚为输出。(数字或PWM)
|
|
|
}
|
|
|
void loop() {
|
|
|
while (Serial.available() > 0) { // 串口收到字符数大于零。
|
|
|
p = Serial.parseInt(); // 在串口数据流中查找一个有效整数。
|
|
|
if (Serial.read() == 'X') { // 收到结束符后开始处理数据。
|
|
|
lcd.clear(); // LCD清屏。
|
|
|
lcd.print(p); // LCD显示收到的数据(整数)。
|
|
|
switch (p) { // 判断数据内容。
|
|
|
case 101:
|
|
|
digitalWrite(11,HIGH); // 点亮LED。
|
|
|
Serial.println(p); // 回传数据。
|
|
|
break;
|
|
|
case 102:
|
|
|
digitalWrite(11,LOW); // 熄灭LED。
|
|
|
Serial.println(p); // 回传数据。
|
|
|
break;
|
|
|
default:
|
|
|
p = map(p,0,100,0,255); // 转换数据范围到PWM输出值。
|
|
|
analogWrite(11,p); // 调整LED亮度。(PWM)
|
|
|
}
|
|
|
}
|
|
|
}
}
|
机端编程用的是E4A中文安卓编程软件,简单省力。基本功能都是齐全的。现在版本是4.7
|
/* 本例程通过蓝牙串口发送指令给Arduino,点亮或熄灭LED,也可以通过滑块调整LED亮度.
|
|
|
* 手机界面上的按键1发送"101X",点亮LED,按键2发送"102X",熄灭LED.
|
|
|
* 拖动界面上的滑块后,发送0-100之间的整数,表示亮度值,后面加一个"X"为结束符..
|
|
|
* 接收Arduino传回的数据,收到"101X",滑块到最大位置.收到"102X",滑块的最小位置.
|
|
|
* 蓝牙串口接收是异步的,必须在收到数据事件中累积收到的ASCII字符,检测到结束符后再处理.
|
|
|
* Arduino的println()函数发出的数据后面会加上回车和换行符,可以作为结束符使用.
|
|
|
* 处理数据时或转换格式时,要去掉回车换行符.(字符长度要减2).
|
|
|
*/
|
|
|
变量 返回值 为 文本型 // 定义全局变量,保存接收数据.
|
|
|
|
|
|
事件 主窗口.创建完毕()
|
|
|
返回值 = ""
|
|
|
如果 蓝牙1.是否已开启() = 假 则 //开启手机蓝牙.
|
|
|
蓝牙1.开启蓝牙()
|
|
|
结束 如果
|
|
|
结束 事件
|
|
|
事件 蓝牙1.蓝牙设置完毕(设置结果 为 整数型)
|
|
|
判断 设置结果
|
|
|
分支 1 //蓝牙已开启.
|
|
|
弹出提示("蓝牙已开启")
|
|
|
蓝牙1.置可被发现() //置可被发现
|
|
|
分支 2 '蓝牙未开启
|
|
|
信息框("信息","蓝牙未被开启,程序将退出!","确定")
|
|
|
结束程序()
|
|
|
分支 3 //已置可被发现
|
|
|
弹出提示("蓝牙已设置为可被发现")
|
|
|
分支 4 //不可被发现
|
|
|
信息框("信息","蓝牙未被设置为可被发现,程序将退出!","确定")
|
|
|
结束程序()
|
|
|
结束 判断
|
|
|
蓝牙1.置工作模式(1) //置工作模式为串口通讯.
|
|
|
结束 事件
|
|
|
事件 按钮10.被单击()
|
|
|
蓝牙1.搜索设备() //搜索设备
|
|
|
弹出提示("正在搜索")
|
|
|
结束 事件
|
|
|
事件 蓝牙1.发现设备(设备名称 为 文本型,设备地址 为 文本型,是否已配对 为 逻辑型) //发现蓝牙设备.
|
|
|
列表框1.可视 = 真 //显示列表框.
|
|
|
列表框1.添加项目(设备名称 & "_" & 设备地址 & "_" & 是否已配对) //列表框显示搜索到的蓝牙设备.
|
|
|
结束 事件
|
|
|
事件 列表框1.表项被单击(项目索引 为 整数型) //单击列表框选择要通讯的设备.
|
|
|
变量 设备信息 为 文本型
|
|
|
变量 文本数组 为 文本型()
|
|
|
变量 设备地址 为 文本型
|
|
|
设备信息 = 列表框1.取项目内容(项目索引)
|
|
|
文本数组 = 分割文本(设备信息,"_") //可以自定义分隔符,不要与设备名称重复即可..
|
|
|
设备地址 = 文本数组(1)
|
|
|
弹出提示(设备地址)
|
|
|
蓝牙1.连接设备(设备地址) //连接设备
|
|
|
弹出提示("正在连接")
|
|
|
结束 事件
|
|
|
事件 蓝牙1.连接完毕(连接结果 为 逻辑型,设备名称 为 文本型,设备地址 为 文本型,连接模式 为 整数型)
|
|
|
如果 连接结果 = 真 则 //已连接设备,关闭列表框显示.
|
|
|
列表框1.可视 = 假
|
|
|
主窗口.标题 = "已连接:" & 设备名称
|
|
|
弹出提示("连接成功")
|
|
|
否则
|
|
|
弹出提示("连接失败") //连接失败,可以点击列表框再次连接.
|
|
|
结束 如果
|
|
|
结束 事件
|
|
|
事件 蓝牙1.收到数据(数据 为 字节型(),设备名称 为 文本型,设备地址 为 文本型) //收到串口数据
|
|
|
返回值 = 返回值 & 字节到文本(数据,"UTF8") //累积到文本变量中.
|
|
|
如果 取文本右边(返回值,1) = "\n" 则 //发现结束符后开始处理数据.
|
|
|
判断 取文本左边(返回值,取文本长度(返回值)-2) //去掉回车换行符,
|
|
|
分支 "101" //滑块到最大值.
|
|
|
水平滑块条1.位置 = 100
|
|
|
分支 "102" //滑块到最小值.
|
|
|
水平滑块条1.位置 = 0
|
|
|
结束 判断
|
|
|
返回值 = "" //清空接收字符串,等待下一次接收.
|
|
|
结束 如果
|
|
|
结束 事件
|
|
|
事件 按钮1.被单击()
|
|
|
蓝牙1.发送数据(文本到字节("101X","UTF8")) //按键1发送.
|
|
|
结束 事件
|
|
|
事件 按钮11.被单击() //结束按钮点击处理.
|
|
|
蓝牙1.发送数据(文本到字节("102X","UTF8")) //关掉LED.
|
|
|
蓝牙1.断开连接() //退出处理,释放资源,结束内部处理线程
|
|
|
结束程序()
|
|
|
结束 事件
|
|
|
事件 按钮2.被单击()
|
|
|
蓝牙1.发送数据(文本到字节("102X","UTF8")) //按键2发送.
|
|
|
结束 事件
|
|
|
事件 水平滑块条1.停止拖动() //滑块动作处理.
|
|
|
变量 数值 为 文本型
|
|
|
数值 = 整数到文本(水平滑块条1.位置) & "X" //添加结束符.
|
|
|
蓝牙1.发送数据(文本到字节(数值,"UTF8")) //发送滑块位置数据.
|
|
|
结束 事件
|
|
手机与Arduino蓝牙串口通讯实验及完整例程的更多相关文章
- Android蓝牙串口通讯【转】
本文转载自:http://blog.sina.com.cn/s/blog_631e3f2601012ixi.html Android蓝牙串口通讯 闲着无聊玩起了Android蓝牙模块与单片机蓝牙模块的 ...
- android 蓝牙串口通讯使用简介
需要的权限 <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-perm ...
- Android(十六 ) android 与蓝牙串口通讯
1.得到蓝牙适配器 BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 2.打开蓝牙 if (!mBl ...
- Android端简易蓝牙聊天通讯App(原创)
欢迎转载,但请注明出处!谢谢.http://www.cnblogs.com/weizhxa/p/5792775.html 最近公司在做一个蓝牙串口通讯的App,有一个固定的蓝牙设备,需要实现手机连接相 ...
- HC-07 蓝牙串口模块
http://www.wavesen.com/probig.asp?id=17 本模块为新推出的产品,各项功能和性能.及引脚封装,均兼容于HC-06. 为低成本需求的的客户推荐本产品.相比HC-06来 ...
- CC2530学习路线-基础实验-串口通讯发送字符串(4 未完待续)
目录 1. 前期预备知识 1.1 串口通讯电路图 1.2 实验相关寄存器 1.2 常用波特率设置 本章未完待续..... 原来写的文章已经丢失了,只能找到这一小部分,看什么时候有时间再补上. 1. 前 ...
- Android通过JNI实现与C语言的串口通讯操作蓝牙硬件模块
一直想写一份技术文档,但因为自感能力有限而无从下笔,近期做了个关于Android平台下实现与C语言的通讯来操作蓝牙模块的项目,中间碰到了很多问题,也在网上查了很多资料,在完毕主要功能后.也有一些人在网 ...
- Arduino 串口通讯参考笔记 - Serial 类库及相关函数介绍
声明: 本ID发布的所有文章及随笔均为原创,可随意转载,单转载文章必须注明作者 aiyauto 及包含原文出处地址 http://www.cnblogs.com/aiyauto/p/7071712.h ...
- Arduino蓝牙模块实现通信
蓝牙参数特点 1.蓝牙核心模块使用HC-06从模块,引出接口包括VCC,GND,TXD,RXD,预留LED状态输出脚,单片机可通过该脚状态判断蓝牙是否已经连接 2.led指示蓝牙连接状态,闪烁表示没有 ...
随机推荐
- 面试题之xml解析?
题目是:用java程序将xml中的数据保存到实体对象中,如何实现? xml如下: <?xml version="1.0" encoding="UTF-8" ...
- SQL中的Where,Group By,Order By和Having
说到SQL语句,大家最开始想到的就是他的查询语句: select * from tableName: 这是最简单的一种查询方式,不带有任何的条件. 当然在我们的实际应用中,这条语句也是很常用到的,当然 ...
- 彻底理解JavaScript中的this
this 是 JavaScript 语言的一个关键字. 它是函数运行时,在函数体内自动生成的一个对象,只能在函数体内使用. 函数的不同使用场合,this 有不同的值.总的来说,this 就是函数运行时 ...
- Windows下使用Tomcat
tomcat简介 Tomcat是一个开源.免费.轻量级的web服务器,只支持部分JavaEE规范(Servlet.JSP),适合部署中小型.并发访问量不大的web项目,是部署中小型Java Web项目 ...
- 0109 springboot的部署测试监控
springboot的部署测试监控 部署 基于maven 打包 JAR 打包方式一般采用的jar包,使用springboot的默认方式即可: 使用maven命令: mvn clean package ...
- duilib 之 List控件
List控件是我们常用到的控件,也是应用很广泛. 对LIST控件添加元素有两种方法,一种是直接在XML中写死元素,另一种是动态创建.另外,LIST的应用也分为两种,一种需要表头,另一种是不需要表头.对 ...
- linux下编译bochs-2.6.2
操作系统: Fedora19 内核: 3.12.9 Linux localhost.localdomain 3.12.9-201.fc19.i686 #1 SMP Wed Jan 29 16:02:1 ...
- ActorFramework教程对比及规划
牢骚太盛防肠断,风物长宜放眼量. 一.引子 昨天的文章,本来就是想写写ActorFramework的教程内容,结果写着写着偏了,变成了吐槽. 首先,声明一下,自己从未参加过任何LabVIEW培训班,也 ...
- Jinja2语法小记
jinja2模板语法小记 Jinja2模板中文文档 三种常见界定符 表达式 {{ ... }} 用于装载字符串.变量.函数调用等 语句 {% ... %} 用于装载控制语句,比如if判断.for循环等 ...
- Reference在Essay写作中的最佳占比是多少?
很多同学在写完Essay作业后 就觉得大功告成了 并不是很注重参考文献 导致查重率过高 面临抄袭.取消成绩. 甚至被退学的情况 或者在essay写作中勉强标出几处 非常随意的在后面列出 其实这是很不正 ...