我的ESP32学习(8)蓝牙的学习和扩展

    这篇文章分成三个部分,第一个部分是对经典蓝牙的使用,第二部分是学习网上的低功耗蓝牙和他们的具体实现方法,第三个部分对学习到的做一个反馈,我们自己写一个低功耗蓝牙的程序。

一、经典蓝牙:

先放结果:

 

 


 

代码:

#include <Arduino.h>
#include <BluetoothSerial.h>
#include "userconmmon.h"
BluetoothSerial SerialBLUE;

void BLUETOOTH_EVENT()
{
}
void setup()
{
    long lRetVal = -1;
    Serial.begin(115200);
    if(SerialBLUE.begin(SSID_NAME) )
    {Serial.print("BLETOOTH BUILDED;\r\n");}
    else
    {ERR_PRINT("ERROR_BLETOOTH_BEGIN\r\n");}
    SerialBLUE.setPin("1234");  
    Serial.printf("BLETOOTH READY TO PAIR. \r\n");
}
void loop()
{
    if (Serial.available())
    {
        SerialBLUE.write(Serial.read());
    }
    if (SerialBLUE.available())
    {
        Serial.write(SerialBLUE.read());
    }
    delay(1);
}

二、低功耗蓝牙

看了些b站up主的讲解,对比了下CSDN上大佬们的文章,我找到了一份特别适合拿来学习低功耗蓝牙的文章。

文章来源于b站up主“homepea”,视频链接:【ESP32超详细教程-使用VSCode(基于Arduino框架)-哔哩哔哩】 https://b23.tv/6WNLBpX

(up主说资源也是他参考着找的,这里我就不追溯了,先直接拿来学习(手动狗头))

up主给的让我们学习的代码如下:

/*
    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();
        }
    }
};

void setup()
{
    Serial.begin(115200);

    // 创建一个 BLE 设备
    BLEDevice::init("UART_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;
    }
}

话不多说,我们直接开始学习。

(1)首先看set up:

BLEDevice::init("UART_BLE"):这里的话我们只需要写我们自己蓝牙名字就好了。

	static void        init(std::string deviceName);   // Initialize the local BLE environment.

这是第二段:

    // 创建一个 BLE 服务
    pServer = BLEDevice::createServer();
    pServer->setCallbacks(new MyServerCallbacks()); //设置回调
    BLEService *pService = pServer->createService(SERVICE_UUID);

 creatServer用于创建一个新服务器:

/**
 * @brief Create a new instance of a server.
 * @return A new instance of the server.
 */
/* STATIC */ BLEServer* BLEDevice::createServer() {
	log_v(">> createServer");
#ifndef CONFIG_GATTS_ENABLE  // Check that BLE GATTS is enabled in make menuconfig
	log_e("BLE GATTS is not enabled - CONFIG_GATTS_ENABLE not defined");
	abort();
#endif // CONFIG_GATTS_ENABLE
	m_pServer = new BLEServer();
	m_pServer->createApp(m_appId++);
	log_v("<< createServer");
	return m_pServer;
} // createServer
BLEServer::BLEServer() {
	m_appId            = ESP_GATT_IF_NONE;
	m_gatts_if         = ESP_GATT_IF_NONE;
	m_connectedCount   = 0;
	m_connId           = ESP_GATT_IF_NONE;
	m_pServerCallbacks = nullptr;
} // BLEServer
void BLEServer::createApp(uint16_t appId) {
	m_appId = appId;
	registerApp(appId);
} // createApp

建立好服务器后,设置回调: 

/**
 * @brief Set the server callbacks.
 *
 * As a %BLE server operates, it will generate server level events such as a new client connecting or a previous client
 * disconnecting.  This function can be called to register a callback handler that will be invoked when these
 * events are detected.
 *
 * @param [in] pCallbacks The callbacks to be invoked.
 */
void BLEServer::setCallbacks(BLEServerCallbacks* pCallbacks) {
	m_pServerCallbacks = pCallbacks;
} // setCallbacks

然乎利用UUID创建服务:

/**
 * @brief Create a %BLE Service.
 *
 * With a %BLE server, we can host one or more services.  Invoking this function causes the creation of a definition
 * of a new service.  Every service must have a unique UUID.
 * @param [in] uuid The UUID of the new service.
 * @return A reference to the new service object.
 */
BLEService* BLEServer::createService(const char* uuid) {
	return createService(BLEUUID(uuid));
}

这里这样写是因为GATT。 GATT是BLE通信规定,每个设备中存在许多service,包含很多个characteristic。(不准确)地说,ESP32是BLEDevice,建立一个BLEServer,每一个BLE服务器中有多个服务BLEservice,服务里又有许多BLECharacteristic,读写这些数据可以实现数据交换。

如果一个主机的特征值改变,发送通知notify告诉客户端,而这句话,就是在创建特征值的时候,将他规定成通知类型,这个特征值变化了,我就通知客户端。

 // 创建一个 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()); //设置回调

关于creatCharacteristic,他传递两个参数,分别是特征值的UUID和特征值的属性。

/**
 * @brief Create a new BLE Characteristic associated with this service.
 * @param [in] uuid - The UUID of the characteristic.
 * @param [in] properties - The properties of the characteristic.
 * @return The new BLE characteristic.
 */
BLECharacteristic* BLEService::createCharacteristic(const char* uuid, uint32_t properties) {
	return createCharacteristic(BLEUUID(uuid), properties);
}

 特征值的属性有以下几种:

 设置好属性后,将描述符与此特征值关联。传递参数是UUID描述符

/**
 * @brief Associate a descriptor with this characteristic.
 * @param [in] pDescriptor
 * @return N/A.
 */
void BLECharacteristic::addDescriptor(BLEDescriptor* pDescriptor) {
	log_v(">> addDescriptor(): Adding %s to %s", pDescriptor->toString().c_str(), toString().c_str());
	m_descriptorMap.setByUUID(pDescriptor->getUUID(), pDescriptor);
	log_v("<< addDescriptor()");
} // addDescriptor

然后这里的特征值有tx和rx,应该是模仿串口。tx代表一个transport, rx代表一个receive。

所以下面是创建了一个接受数据的特征值并回调。

然后就是启动服务,

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

这里用到了getAdvertising,它的作用是检索可用于服务器存在的广播对象。
返回值是广播对象。


/**
 * @brief Retrieve the advertising object that can be used to advertise the existence of the server.
 *
 * @return An advertising object.
 */
BLEAdvertising* BLEServer::getAdvertising() {
	return BLEDevice::getAdvertising();
}

(2)然后开始看loop的部分,

loop第一部分需要关注的是

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

这里的deviceConnected初始化时是false,在set up()中创建BLE服务的时候,如果满足连接会被设置成true。

这个Delay(2000) 正如注释所说,是用来避免堵塞。

到这里今天的学习就结束了,明天可能做一些外设什么的,或者继续推进低功耗蓝牙,再说吧,最近考试周需要复习,还是慢慢搞比较好。

 

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值