“学习esp32蓝牙模块:笔记与实践”

关于esp32蓝牙模块的使用——esp32学习笔记

关于esp32蓝牙模块的使用——esp32学习笔记

  • 关于esp32蓝牙模块的使用——esp32学习笔记
  • 零、前言
  • 一、经典蓝牙BT
  • 二、低功耗蓝牙BLE()
  • 0.前言
  • 1.首先我们来做一些准备工作
  • 2.创建一个BLE设备
  • 3.创建一个BLE服务
  • 4.创建一个BLE特征
  • 5.开始服务和广播
  • 6.接下来呢在loop函数中我们的蓝牙连接会对应三种状态:
  • 零、前言

    esp32自带蓝牙模块可以让我们进行蓝牙连接并进行数据交换

    一、经典蓝牙BT

    首先来编写代码,经典蓝牙的使用非常简单,首先声明使用了BluetoothSerial这个库,然后使用SerialBT.begin函数设置蓝牙的名字,再然后就是设置配对码,由于这里没有用到配对码,所以我将注释掉。当配对成功我们就使用printf函数打印出蓝牙配对成功。

    #include <Arduino.h>
    #include <BluetoothSerial.h>
    
    BluetoothSerial SerialBT;
    
    void setup()
    {
        Serial.begin(115200);
        SerialBT.begin("BAKUMAN"); // 如果没有参数传入则默认是蓝牙名称是: "ESP32"
        // SerialBT.setPin("1234");   // 蓝牙连接的配对码
        Serial.printf("BT initial ok and ready to pair. \r\n");
    }
    
    void loop()
    {
        if (Serial.available())
        {
            SerialBT.write(Serial.read());
        }
        if (SerialBT.available())
        {
            Serial.write(SerialBT.read());
        }
        delay(1);
    }
    

    再然后就是loop函数中:

    Serial.available()是串口中(演示中为电脑端)收到的信息,如果串口中有数据,就使用蓝牙发送出去。

    SerialBT.available()是蓝牙中(演示中为手机端)收到的信息,如果蓝牙中有数据,就发送给串口,串口就会打印出来。

    接下来就是演示的截图:

    串口发送信息:

    串口发送数据image-20211009160839765

    蓝牙发送数据:

    image-20211009160118260Screenshot_20211009_155717

    二、低功耗蓝牙BLE()

    0.前言

    UUID:ble的服务和characteristic是通过UUID来进行识别的。创建uuid可以使用这么一个网站:Online UUID Generator Tool

    notify:如果这个主机的一个特征值characteristic发生改变,就可以通过notify来告诉我们

    pCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_TX, BLECharacteristic::PROPERTY_NOTIFY); 
    //创建一个(读)特征值, 它是通知下发类型的特征值
    

    write:我们可以把特征值定为写入类型, 这样客户端可以给我们写入, 触发写入回调函数

    BLECharacteristic *pCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_RX, BLECharacteristic::PROPERTY_WRITE);
    //创建一个(写)特征, 它是写入类型的特征值
      pCharacteristic->setCallbacks(new MyCallbacks());  
    //为特征添加一个回调
    

    使用这个低功耗蓝牙有这么几个步骤:

    \1. 创建一个 BLE Server

    \2. 创建一个 BLE Service

    \3. 创建一个 BLE Characteristic

    \4. 创建一个 BLE Descriptor

    \5. 开始服务

    \6. 开始广播

    并且我们还需要使用BLEDevice,BLEServer,BLEUtils,BLE2902,common这几个库

    1.首先我们来做一些准备工作

    /*
        Video: https://www.youtube.com/watch?v=oCMOYS71NIU
        Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleNotify.cpp
        Ported to Arduino ESP32 by Evandro Copercini
    
       Create a BLE server that, once we receive a connection, will send periodic notifications.
       创建一个BLE服务器,一旦我们收到连接,将会周期性发送通知
    
       T使用步骤:
       1. 创建一个 BLE Server
       2. 创建一个 BLE Service
       3. 创建一个 BLE Characteristic
       4. 创建一个 BLE Descriptor
       5. 开始服务
       6. 开始广播
    
    
    */
    #include <Arduino.h>
    #include <BLEDevice.h>
    #include <BLEServer.h>
    #include <BLEUtils.h>
    #include <BLE2902.h>
    #include "common.h"
    
    uint8_t txValue = 0;                         //后面需要发送的值
    BLEServer *pServer = NULL;                   //BLEServer指针 pServer
    BLECharacteristic *pTxCharacteristic = NULL; //BLECharacteristic指针 pTxCharacteristic
    bool deviceConnected = false;                //本次连接状态
    bool oldDeviceConnected = false;             //上次连接状态
    
    // See the following for generating UUIDs: https://www.uuidgenerator.net/
    #define SERVICE_UUID "12a59900-17cc-11ec-9621-0242ac130002" // UART service UUID
    #define CHARACTERISTIC_UUID_RX "12a59e0a-17cc-11ec-9621-0242ac130002"
    #define CHARACTERISTIC_UUID_TX "12a5a148-17cc-11ec-9621-0242ac130002"//注意这里面是用
    
    class MyServerCallbacks : public BLEServerCallbacks
    {
        void onConnect(BLEServer *pServer)
        {
            deviceConnected = true;
        };
    
        void onDisconnect(BLEServer *pServer)
        {
            deviceConnected = false;
        }
    };
    
    class MyCallbacks : public BLECharacteristicCallbacks
    {
        void onWrite(BLECharacteristic *pCharacteristic)
        {
            std::string rxValue = pCharacteristic->getValue(); //接收信息
    
            if (rxValue.length() > 0)
            { //向串口输出收到的值
                Serial.print("RX: ");
                for (int i = 0; i < rxValue.length(); i++)
                    Serial.print(rxValue[i]);
                Serial.println();
            }
        }
    };
    
    

    2.创建一个BLE设备

    	BLEDevice::init(ble_name);
    

    3.创建一个BLE服务

        pServer = BLEDevice::createServer();
        pServer->setCallbacks(new MyServerCallbacks()); //设置回调
        BLEService *pService = pServer->createService(SERVICE_UUID);
    

    在这里面的回调函数就是上面代码串中的MyServerCallbacks

    4.创建一个BLE特征

    pTxCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_TX, BLECharacteristic::PROPERTY_NOTIFY);
    pTxCharacteristic->addDescriptor(new BLE2902());
    BLECharacteristic *pRxCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_RX, BLECharacteristic::PROPERTY_WRITE);
    pRxCharacteristic->setCallbacks(new MyCallbacks()); //设置回调
    

    这里创建了一个特征值,类型是通知。

    在后面使用createCharacteristic(CHARACTERISTIC_UUID_RX, BLECharacteristic::PROPERTY_WRITE)将rx收集到的信息写入,通过MyCallbacks再打印出来

    为了实现"串口",我们在这个服务下添加了两个特征值, 一个是TX. 一个是RX.另外还需注意三个uuid因该是相对应的值。

    5.开始服务和广播

        pService->start();                  // 开始服务
        pServer->getAdvertising()->start(); // 开始广播
        Serial.println(" 等待一个客户端连接,且发送通知... ");
    

    6.接下来呢在loop函数中我们的蓝牙连接会对应三种状态:

    (1)设备已经连接:

    if (deviceConnected){
            pTxCharacteristic->setValue(&txValue, 1); // 设置要发送的值为1
            pTxCharacteristic->notify();              // 广播
            txValue++;                                // 指针数值自加1
            delay(2000);                              // 如果有太多包要发送,蓝牙会堵塞
        }
    

    这里面测试的是不停发送数据,每发一次数值加一。

    此时

    class MyServerCallbacks : public BLEServerCallbacks
    {
        void onConnect(BLEServer *pServer)
        {
            deviceConnected = true;
        };
    
        void onDisconnect(BLEServer *pServer)
        {
            deviceConnected = false;
        }
    };
    

    通过这个回调可以说清楚这个蓝牙到底有没有连接,如果连接了通过

    pServer->setCallbacks(new MyServerCallbacks());
    

    这个MyServerCallbacks回调就可以返回连接状态。

    调式结果如图:

    ble串口:

    ble串口接收image-20211009210430190

    ble开始广播

    ble开始广播

    最后附上整段代码:

    /*
        Video: https://www.youtube.com/watch?v=oCMOYS71NIU
        Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleNotify.cpp
        Ported to Arduino ESP32 by Evandro Copercini
    
       Create a BLE server that, once we receive a connection, will send periodic notifications.
       创建一个BLE服务器,一旦我们收到连接,将会周期性发送通知
    
       T使用步骤:
       1. 创建一个 BLE Server
       2. 创建一个 BLE Service
       3. 创建一个 BLE Characteristic
       4. 创建一个 BLE Descriptor
       5. 开始服务
       6. 开始广播
    
    
    */
    #include <Arduino.h>
    #include <BLEDevice.h>
    #include <BLEServer.h>
    #include <BLEUtils.h>
    #include <BLE2902.h>
    #include "common.h"
    
    uint8_t txValue = 0;                         //后面需要发送的值
    BLEServer *pServer = NULL;                   //BLEServer指针 pServer
    BLECharacteristic *pTxCharacteristic = NULL; //BLECharacteristic指针 pTxCharacteristic
    bool deviceConnected = false;                //本次连接状态
    bool oldDeviceConnected = false;             //上次连接状态d
    // See the following for generating UUIDs: https://www.uuidgenerator.net/
    #define SERVICE_UUID "12a59900-17cc-11ec-9621-0242ac130002" // UART service UUID
    #define CHARACTERISTIC_UUID_RX "12a59e0a-17cc-11ec-9621-0242ac130002"
    #define CHARACTERISTIC_UUID_TX "12a5a148-17cc-11ec-9621-0242ac130002"
    
    class MyServerCallbacks : public BLEServerCallbacks
    {
        void onConnect(BLEServer *pServer)
        {
            deviceConnected = true;
        };
    
        void onDisconnect(BLEServer *pServer)
        {
            deviceConnected = false;
        }
    };
    
    class MyCallbacks : public BLECharacteristicCallbacks
    {
        void onWrite(BLECharacteristic *pCharacteristic)
        {
            std::string rxValue = pCharacteristic->getValue(); //接收信息
    
            if (rxValue.length() > 0)
            { //向串口输出收到的值
                Serial.print("RX: ");
                for (int i = 0; i < rxValue.length(); i++)
                    Serial.print(rxValue[i]);
                Serial.println();
            }
        }
    };
    
    void setup()
    {
        Serial.begin(115200);
    
        // 创建一个 BLE 设备
        BLEDevice::init("BAKUMAN");//在这里面是ble的名称
    
        // 创建一个 BLE 服务
        pServer = BLEDevice::createServer();
        pServer->setCallbacks(new MyServerCallbacks()); //设置回调
        BLEService *pService = pServer->createService(SERVICE_UUID);
    
        // 创建一个 BLE 特征
        pTxCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_TX, BLECharacteristic::PROPERTY_NOTIFY);
        pTxCharacteristic->addDescriptor(new BLE2902());
        BLECharacteristic *pRxCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_RX, BLECharacteristic::PROPERTY_WRITE);
        pRxCharacteristic->setCallbacks(new MyCallbacks()); //设置回调
    
        pService->start();                  // 开始服务
        pServer->getAdvertising()->start(); // 开始广播
        Serial.println(" 等待一个客户端连接,且发送通知... ");
    }
    
    void loop()
    {
        // deviceConnected 已连接
        if (deviceConnected)
        {
            pTxCharacteristic->setValue(&txValue, 1); // 设置要发送的值为1
            pTxCharacteristic->notify();              // 广播
            txValue++;                                // 指针数值自加1
            delay(2000);                              // 如果有太多包要发送,蓝牙会堵塞
        }
    
        // disconnecting  断开连接
        if (!deviceConnected && oldDeviceConnected)
        {
            delay(500);                  // 留时间给蓝牙缓冲
            pServer->startAdvertising(); // 重新广播
            Serial.println(" 开始广播 ");
            oldDeviceConnected = deviceConnected;
        }
    
        // connecting  正在连接
        if (deviceConnected && !oldDeviceConnected)
        {
            // do stuff here on connecting
            oldDeviceConnected = deviceConnected;
        }
    }
    
    物联沃分享整理
    物联沃-IOTWORD物联网 » “学习esp32蓝牙模块:笔记与实践”

    发表评论