手把手教你做蓝牙小车(二)

第5节 BTChat

本节开始介绍Arduino蓝牙模块,配合Android应用,实现一个蓝牙聊天应用。

5.1 什么是蓝牙

简单说就是一种不同设备之间点对点通讯的技术。
有大篇大篇的蓝牙各种协议,各种规范。。。
本课程只讲用到的内容,不展开更多内容了。

5.2 SDP

Service Discovery Protocol,简称SDP,是允许设备发现其他设备所支持服务的协议。
蓝牙协议给每个服务分配一个UUID,用来区分各种服务。
SDP的UUID是00001101-0000-1000-8000-00805F9B34FB.

5.3 Android蓝牙应用

Android提供了一个叫BluetoothChat的蓝牙实例
这里是相关介绍
https://developer.android.com/samples/BluetoothChat/index.html
右上角有个Download,点击下载到一个Eclipse下的Android工程。

这个应用程序是针对Android系统的聊天应用,需要修改其UUID才能和Arduoni蓝牙模块聊天。
或者你也可以直接下载我在安豆网共享的apk。

5.4 Arduino实现蓝牙

Arduino把蓝牙封装成了一个串口。
我们只需要把蓝牙芯片连接到特定的串口,之后就可以当做一个串口来处理了。

5.5 Arduino模块连接

再复习一下Serial硬件定义
Uno示例

USB接口和0、1引脚是Serial对象

Mega示例

USB接口和0、1引脚是Serial对象。
14、15引脚是Serial3对象。
16、17引脚是Serial2对象。
18、19引脚是Serial1对象。

如果用Uno开发蓝牙应用,只能电脑连接USB口,蓝牙也连接0、1引脚。
两者同时连接会导致USB口不能烧写代码。
必须要拔下蓝牙连线,才能烧写代码。
然后再接上蓝牙连线,才能调试蓝牙。
简直是一场噩梦。
这是我在本文开头推荐选用Mega开发板的理由之一。

用Mega就简单了,它提供了4个串口,我们用Serial以外的其他口就没有上边的冲突了。
下图是我的连接方式

蓝牙模块的VCC,GND引脚分别连接Mega的正负引脚。
蓝牙模块的TX引脚连接Mega的RX3引脚,RX引脚连接Mega的TX3引脚。
现在,USB口是Serial对象,蓝牙是Serial3对象。


/*******************************************************************/
* 版权声明
* 本教程只在CSDN和安豆网发布,其他网站出现本教程均属侵权。
/*******************************************************************/


5.6 手机和Arduino连接

Arduino按上一节的线路连接,并用USB线连接到电脑。
打开蓝牙,安装BTChat.apk到手机,打开应用,参考下图。

5.5 Arduino代码修改

因为要使用Serial和Serial3,所以两个串口都需要初始化

void setup() {
  Serial.begin(9600);
  Serial3.begin(9600);
}

Serial3.available()函数检查蓝牙串口是否有数据输入。
Serial3.read()读取蓝牙串口的输入内容。
Serial.print(Serial3.read())将上一步读取到的内容输出到PC端的串口监视器。

void loop() {
  while (Serial3.available()) {
    Serial.print(Serial3.read());
  }
}

再加一段相反方向读取输出的代码

void loop() {
  while (Serial3.available()) {
    Serial.print(Serial3.read());
  }

  while (Serial.available()) {
    Serial3.print(Serial.read());
  }
}

试试看吧,手机和Arduino可以简单通讯了。

5.6 BluetoothChat的bug

通过串口监视器输入一个很长的字符串,比如“abcdefghijklmnopqrstuvwxyz1234567890”。

手机显示的数据是这样子的,显然不是我们希望的结果。

我们看看Android这边是怎么收数据的。
收数据的相关代码在
BluetoothChat\Application\src\main\java\com\example\android\bluetoothchat\BluetoothChatService.java文件,ConnectedThread类的run()函数中。

一开始运行run函数,先申请一块内存。

...
byte[] buffer = new byte[1024];
...

收取数据代码段不断循环。

...
while (true) {
...

读取串口数据到buffer中

...
bytes = mmInStream.read(buffer);
...

把收到的数据发送给Fragment,在界面显示内容。

...
mHandler.obtainMessage(Constants.MESSAGE_READ, bytes, -1, buffer)
                    .sendToTarget();
...

这是run()函数相关代码

public void run() {
    Log.i(TAG, "BEGIN mConnectedThread");
    byte[] buffer = new byte[1024];
    int bytes;

    // Keep listening to the InputStream while connected
    while (true) {
        try {
            // Read from the InputStream
            bytes = mmInStream.read(buffer);

            // Send the obtained bytes to the UI Activity
            mHandler.obtainMessage(Constants.MESSAGE_READ, bytes, -1, buffer)
                    .sendToTarget();
...

这个例子中,Android这边先收到‘a’,发送给界面显示。
又收到‘bcdefghij’,继续发送给界面显示。
一直到最后收到‘567890’。
一切看起来都挺完美。
但,问题出在几次收数据共用一个buffer,而界面显示是异步处理。前一次界面还没有更新,后一次新的数据已经收到了。这时候界面就错误的显示了后一次的数据。

本教程以Arduino为主,所以Android的代码简单修改,能用就行了。
把申请内存的代码挪到while循环内。

byte[] buffer = new byte[1024];

修改后的代码。

public void run() {
    Log.i(TAG, "BEGIN mConnectedThread");
    int bytes;

    // Keep listening to the InputStream while connected
    while (true) {
        byte[] buffer = new byte[1024];
        try {
            // Read from the InputStream
            bytes = mmInStream.read(buffer);

            // Send the obtained bytes to the UI Activity
            mHandler.obtainMessage(Constants.MESSAGE_READ, bytes, -1, buffer)
                    .sendToTarget();
...

/*******************************************************************/
* 版权声明
* 本教程只在CSDN安豆网发布,其他网站出现本教程均属侵权。

*另外,我们还推出了Arduino智能硬件相关的教程,您可以在我们的网店跟我学Arduino编程中购买相关硬件。同时也感谢大家对我们这些码农的支持。

*最后再次感谢各位读者对安豆的支持,谢谢:)
/*******************************************************************/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值