第4节 蓝牙传输

智能硬件基本上都需要和手机相连,然后让手机控制这些硬件的工作。相连的方式不外乎以下三种,

  1. 数据线有线连接,通过一根数据线把智能硬件和手机连接起来。采用这种方式,需要一个特殊的带USB HOST功能的扩展板;

  2. WIFI连接,智能硬件和手机都连接到同一个WIFI路由器上,让彼此通过WIFI网络传输数据。采用这种方式需要一个WIFI模块;

  3. 蓝牙连接,智能硬件和手机通过蓝牙相连。采用这种方式需要一个蓝牙模块。通常情况下智能硬件等待其他设备的介入,而手机端会主动寻找可以连接的蓝牙设备,主动发起连接请求;

Arduino可以通过以上三种方式的任何一种实现与手机的连接。这里我们将选择蓝牙连接。

选择使用蓝牙连接的主要原因是,Arduino蓝牙模块的价格相对便宜,实现的成本低,而且编程很简单。

4.1 通信接口

Arduino开发板会提供一个至多个用于通信用的串口接口。开发板与任何通信模块的数据交换都是通过这些串口来完成的。

  1. UNO的串口硬件位置

    USB接口和0、1引脚都是对应着串口-Serial

  2. MEGA的串口硬件位置

    MEGA有多个串口,
    USB接口和0、1引脚对应着串口-Serial
    18、19引脚对应着串口1-Serial1
    16、17引脚对应着串口2-Serial2
    14、15引脚对应着串口3-Serial3

每一个串口都由一个输入引脚(RX)和输出引脚(TX)组成。硬件接收和发送数据的功能,就是通过对应的引脚实现的。

4.1.1 引脚的连接

在外接的通信模块中,至少也要有4个引脚接入开发板:输出TX、输入RX、电源VC、接地GND。有的通信模块可能还有额外的引脚作为额外的控制通道,但以上4个引脚是一定会有的。

当开发板与外接通信模块进行连接的时候,要按照如下的方式进行,

开发板引脚连接外接通信模块引脚
电源VC<—>电源VC
接地GND<—>接地GND
输出TX<—>输入RX
输入RX<—>输出TX

*注意开发板和外接通信模块相连的时候后,是TX连着RX,一个发送,另一个当然就是接收了;并且VC/GND不和TX/RX不能接反了,不然会烧毁蓝牙模块。
电源的两根线不能接到数据发送的两个的引脚上,否则会烧毁蓝牙模块
电源的两根线不能接到数据发送的两个的引脚上,否则会烧毁蓝牙模块
电源的两根线不能接到数据发送的两个的引脚上,否则会烧毁蓝牙模块

如此一来,开发板和外接的通信模块就可以通过串口来进行通信了。

在实际的操作当中,我们还是会使用到扩展板来进行引脚的连接。

4.1.2 数据的读写

在进行读写之前,要判断一下串口是否可用,

if(Serial.available())
{
    //这里面对串口操作才会有意义
}

当我们想在代码中使用这些串口读取数据的时候,可以,

  1. 读一个字节,

    //通过UNO或MEGA的Serial读数据,
    //读一个字节
    int data = Serial.read();
    
    //通过MEGA的Serial2读数据,
    //读一个字节
    int data = Serial2.read();
  2. 读到数组缓冲区-buffer中,

    //通过UNO或MEGA的Serial读数据,
    //读到的数据放在buffer的空间当中,
    //返回值nRead表示成功读取到的字节数
    int length = 128;
    char * buffer = new char[length];
    int nRead = Serial.readBytes(buffer, length)
    
    //通过MEGA的Serial2读数据,
    //读到的数据放在buffer的空间当中,
    //返回值nRead表示成功读取到的字节数
    int length = 128;
    char * buffer = new char(length);
    int nRead = Serial2.readBytes(buffer, length)

当我们想在代码中使用这些串口发送数据的时候,可以,

  1. 发送一个byte,

    //通过UNO或MEGA的Serial发数据
    Serial.write('A');
    
    //通过MEGA的Serial2发数据
    Serial2.write('A');
  2. 发送一个缓冲区的内容,

    //通过UNO或MEGA的Serial发数据
    //result表示发送成功的byte数
    uint8_t data[] = "hello arduino";
    int len = sizeof(data);
    int result = Serial.write(data, len);
    
    //通过MEGA的Serial2发数据
    //result表示发送成功的byte数
    uint8_t data[] = "hello arduino";
    int len = sizeof(data);
    int result = Serial2.write(data, len);

4.2 蓝牙模块

蓝牙模块与Arduino开发板之间就是通过串口进行数据传输的。

我们经常见到的蓝牙模块有HC-05 HC-06HC-06拥有4个引脚,输出TX、输入RX、电源VC、接地GND。还有一种形式的蓝牙模块,它就远不止4个引脚了。

我们安豆杂货铺提供的蓝牙模块,就是功能最为简单的HC-06蓝牙模块,它只能够被动的接收其它蓝牙模块发起的连接请求,连接时的配对密码默认是1234

4.2.1 蓝牙模块的硬件连接

这些蓝牙模块的连接非常简单。这里我们选择的器件有,

  • 1个MEGA开发板;
  • 1个HC蓝牙模块;
  • 4根连接线;

根据之前串口连接的原则,我们将蓝牙模块与Arduino开发板用插线连接起来。我们选择将蓝牙模块的RX TX连接到MEGA开发板的0和1引脚--使用Serial这个串口。

或者使用扩展板来连接蓝牙模块,这里我们使用HC-06举例,将HC-06连接到MEGA扩展板的Serial接口上,

扩展板引脚连接蓝牙模块引脚
0组V(电源VC)<—>电源VC
0组G(接地GND)<—>接地GND
1组S(TX)<—>输入RX
0组S(RX)<—>输出TX

当开发板通电(USB数据线连接上电脑)以后,蓝牙模块的指示灯就亮了。此时它就进入了工作状态:其他蓝牙设备就可以查找并连接这个外接的蓝牙模块了。

*注意:假如你使用的是UNO开发板,也可以按照上面的引脚进行连接,不过当D0 D1引脚被蓝牙设备占用的时候,是不能向UNO开发板部署代码的。因此每当你要部署代码的时候,需要将D0 D1引脚断开,部署完成后再重新连上。如果使用MEGA开发板,你就可以将蓝牙接到其它的串口上(MEGA有多个串口,而UNO只有一个),避免每次刷机都要重新连接硬件。所以我们建议你最好还是采用MEGA开发板。

4.2.2 蓝牙通信的实现

接下来,我们做个简单的程序:让蓝牙模块接受其他蓝牙设备发送过来的数据,每次收到该数据后,又把数据原封不动的回传给发送设备,

  1. setup()中,初始化好蓝牙设备的波特率,为9600,因为我们硬件连接的是Serial,所以就要初始化Serial

    void setup()
    {
        Serial.begin(9600);
    }
  2. loop()中,不停的尝试读取串口(蓝牙设备)收到的消息,一旦收到,就通过串口(蓝牙设备)把收到的内容原封不动的发送出去,

    void loop()
    {
        //如果可以读取数据
        if (Serial.available())
        {
            //创建读取数据用的缓存
            int length = 128;
            char * buffer = new char[length];
    
            //读取数据到buffer中
            int nReadSize = Serial.readBytes(buffer, length);
    
            //如果成功读取到数据,就原封不动的发回去
            if(nReadSize > 0)
            {
                Serial.write(buffer, nReadSize);
            }
    
            //删除分配的空间,避免内存泄漏
            delete buffer;
        } 
    }

4.2.3 结果验证

最后我们需要一个蓝牙设备上的应用程序,来连接这个正在工作的蓝牙模块,并向它发送数据。该应用收到蓝牙模块回传的消息后,能够向开发者展现出来。

这里可以使用我们另一篇文档《手把手教你做蓝牙聊天应用》开发的AnddleChat来连接设备、发送数据、显示接收的内容。

大家可以,

  1. 下载该部分对应的源码,编译后获取可执行的程序;

  2. 也可以使用编译好的APK文件,直接安装测试。

安装完成后,启动应用,根据提示打开蓝牙功能,搜索要连接的Arduino蓝牙模块,选择连接。这里选择搜索到的HC-06设备,

在文字输入框输入内容123456789,获取对方接收到后到回应,

可以看到,我们返回的数据分成了两条:1 23456789。说明Arduino开发板在读取蓝牙串口的数据时,Serial.readBytes()并没有一次把所有数据读完,而是分两次接收到的。

//读取数据到buffer中时,并没有一次将对方发送来的数据全部读完
int nReadSize = Serial.readBytes(buffer, length);

所以,假如Arduino开发板希望将对方发送来的数据接收完全之后,在整个发送回去,需要将每次读到的数据保存下来,直到没有新的数据接收,然后再统一一次性的全部发送返回。


至此,Arduino通过外接蓝牙模块接收和发送数据的功能就完整的实现了。


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

本系列课程使用到的Arduino开发板、扩展板以及其他相关的传感器,各位可以根据我们文章中介绍的硬件在淘宝网选购。
您也可以在我们的网店跟我学Arduino编程中购买,这些相关硬件都由我们为您把关购买,为大家节省选择的精力与时间。同时也感谢大家对我们这些码农的支持。

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

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

更多推荐