ESP32蓝牙和BLE简述和基本使用方法

文章目录

  • ESP32蓝牙和BLE简述和基本使用方法
      • 经典蓝牙串口通信
    • 低功耗蓝牙 BLE (常用)
      • BLE 服务器和客户端通信

经典蓝牙串口通信

#include "BluetoothSerial.h"   //引入蓝牙函数库
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif                               //判断蓝牙是否启用
const int led =  2;
BluetoothSerial SerialBT;         //定义一个自拟的蓝牙串口通信名称
void setup()
{pinMode(led,OUTPUT);digitalWrite(led,LOW);SerialBT.begin("ESP32_Blue");   //启动蓝牙串口并设置蓝牙的名称Serial.begin(115200);
}void loop()
{if(SerialBT.available())   //判断蓝牙串口是否收到数据{char res = SerialBT.read();   //将收到的数据读取出来,下面分别处理if(res == 'A'){digitalWrite(led,LOW);Serial.println("Get OFF");}else if(res == 'B'){digitalWrite(led,HIGH);Serial.println("Get ON");}}delay(10);
}

该程序效果如下

  • ESP32完成初始化后生成一个蓝牙信号

  • 手机通过蓝牙串口发送字符 B ,LED点亮

  • 手机通过蓝牙串口发送字符 A ,LED熄灭

低功耗蓝牙 BLE (常用)

  • BLE GATT协议

GATT全称Generic Attribute Profile, GATT 代表通用属性,它定义了暴露给连接的BLE设备的分层数据结构。这意味着,GATT 定义了两个BLE设备,发送和接收标准通讯的方式。了解此层次结构很重要,因为这样可以,更轻松地了解如何使用BLE和编写应用程序。
下图为BLE的基本结构,需要记清楚

  • 低功耗特性
    特征始终归服务所有,它是层次结构(值)中包含实际数据的地方。特征始终具有两个属性:特征声明(提供有关数据的元数据)和特征值。
    此外,特征值后面可以跟描述符,这进一步扩展了特征声明中包含的元数据。
    这些属性描述了如何与特征值交互。基本上,它包含可以与特征一起使用的操作和过程:
    广播
    阅读
    写无响应

    通知
    表示
    经过身份验证的签名写入扩展属性

  • 用户名
    每个服务,特征,描述符都有一个UUID(通用唯一标识符)。UUID是唯一的128位(16 byte)数字
    在线UUID生成

  • 创建 BLE 服务器代码流程

    1,创建一个BLE服务器。在这种情况下,ESP32充当BLE服务器。

    2,创建BLE服务。

    3,在服务上创建BLE特性。

    4,在特征上创建一个BLE描述符。

    5,启动服务。

    6,开始广播,以便其他设备可以找到它。

  • 代码示例

//此程序通过BLE广播,其他设备接受广播,手机通过nRF Connet软件连接,
//手机下发字符 1 点亮LED,字符 0 关闭LED#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <BLEService.h>
#include <BLECharacteristic.h>
#define SERVICE_UUID "b408e1a0-3d8a-11ed-b878-0242ac120002"         //服务UUID
#define CHARACTERISTIC_UUID "dfd84064-3d8a-11ed-b878-0242ac120002"  //特征UUID
#define CONTROL_UUID "de045162-3d97-11ed-b878-0242ac120002"         //控制特征UUIDconst int led = 2;
char state = 48;BLECharacteristic controlCharacteristic(CONTROL_UUID, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE);//设置服务器所需要的配置
void setup() {Serial.begin(115200);BLEDevice::init("BLE_HWD");                                   //创建设备BLEServer *pServer = BLEDevice::createServer();               //设置为服务器BLEService *pService = pServer->createService(SERVICE_UUID);  //使用上面的服务UUID创建服务// 添加一个带有对象名(官方UUID)的特征,不带对象,这个特征不会改变BLECharacteristic *nameCharacteristic = pService->createCharacteristic(BLEUUID((uint16_t)0x2A00), BLECharacteristic::PROPERTY_READ);nameCharacteristic->setValue("LED");                  //显示特征名pService->addCharacteristic(&controlCharacteristic);  //增加一个控制LED的特性controlCharacteristic.setValue(&state);//设置特征, 使用上面的特征UUID,需要将特征的属性作为参数传递。此情况下是读或写BLECharacteristic *pCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID,BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE);pCharacteristic->setValue("Hello HWD!!!");  //创建完特征后,可以使用setValue()方法为其在此赋值//此值可以是其他传感器的值pService->start();//下面是启动服务和广播,以便其他BLE设备找到此 BLE 设备BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();  //BLE广播pAdvertising->addServiceUUID(SERVICE_UUID);                  //广播添加服务 UUIDpAdvertising->setScanResponse(true);                         //广播扫描响应pAdvertising->setMinPreferred(0x06);                         //广播设置最小首选pAdvertising->setMinPreferred(0x12);                         //广播设置最小首选BLEDevice::startAdvertising();                               //BLE 设备启动广播,特征已经定义,可以在手机中读取它pinMode(led, OUTPUT);digitalWrite(led, LOW);Serial.println("Characteristic defined! Now you can read it in your phone!");  //提示消息
}void loop() {std::string controlValue = controlCharacteristic.getValue();  //字符串控件获取特征值if (controlValue[0] != state) {state = controlValue[0];if (state == 48) {digitalWrite(led, LOW);} else if (state == 49) {digitalWrite(led, HIGH);}}
}

BLE 服务器和客户端通信

下面程序实现了客户端不断从服务器读取模拟传感器的值并显示出来
程序模拟了电压电流和功率信息的传递

服务器端代码

#include "Arduino.h"
#include "BLEDevice.h"              //BLE驱动库
#include "BLEServer.h"              //BLE蓝牙服务器库
#include "BLEUtils.h"               //BLE实用程序库
#include "BLE2902.h"                //特征添加描述符库
#include <BLECharacteristic.h>      //BLE特征函数库float Volt = 220.00;    //电压值设置为220V
float Current = 20.00;  //电流值设置为20A
float Power = 4400.00;  //功率设置位4400W
//可通过外接传感器改变这些值#define bleServerName "BLE_HWD_SER"  //BLE服务器的名称
#define SERVICE_UUID "f9da736b-dc49-4b7d-a023-8ecee2e72741"  //服务的UUIDBLECharacteristic V_Characteristics("308a35f8-3e7b-11ed-b878-0242ac120002",BLECharacteristic::PROPERTY_NOTIFY);  //电压的特征值
BLEDescriptor V_Descriptor(BLEUUID((uint16_t)0x2901));  //电压描述符
BLECharacteristic I_Characteristics("92ddd762-3e7d-11ed-b878-0242ac120002",BLECharacteristic::PROPERTY_NOTIFY);  //电流的特征值
BLEDescriptor I_Descriptor(BLEUUID((uint16_t)0x2902));  //电流描述符
BLECharacteristic W_Characteristics("92ddd762-3e7d-11ed-b878-0242ac120002",BLECharacteristic::PROPERTY_NOTIFY);  //功率的特征值
BLEDescriptor W_Descriptor(BLEUUID((uint16_t)0x2903));  //功率描述符bool connected_state = false;   //创建设备连接标识符 class MyServerCallbacks:public BLEServerCallbacks   //创建连接和断开调用类
{void Connected(BLEServer *pServer)//开始连接函数{connected_state = true;   //设备正确连接}void Disconnected(BLEServer *pServer)//断开连接函数{connected_state = false;  //设备连接错误}};void setup()
{BLEDevice::init(bleServerName);  //创建BLE并设置名称BLEServer *pServer = BLEDevice::createServer();  //创建BLE服务器pServer->setCallbacks(new MyServerCallbacks());  //设置连接和断开调用类BLEService *pService = pServer->createService(SERVICE_UUID); //创建BLE服务//创建 BLE 特征和描述符pService->addCharacteristic(&V_Characteristics); //创建电压特征V_Descriptor.setValue("Volt");  //创建电压描述符V_Characteristics.addDescriptor(new BLE2902());  //给电压特征添加描述符pService->addCharacteristic(&I_Characteristics); //创建电流特征I_Descriptor.setValue("Current");  //创建电流描述符I_Characteristics.addDescriptor(new BLE2902());  //给电流特征添加描述符pService->addCharacteristic(&W_Characteristics); //创建功耗特征W_Descriptor.setValue("Power");  //创建功耗描述符W_Characteristics.addDescriptor(new BLE2902());  //给功耗特征添加描述符pService->start();  //启动服务pServer->getAdvertising()->start();   //开始广播
}void loop()
{if(connected_state)   //有设备连接{static char V_Value[8];  //定义局部静态变量 char型存放电压值字符串dtostrf(Volt,6,2,V_Value);  //将浮点数转化为char型字符串 char Volt_Value[8] = {'2','2','0','.','0','0'}V_Characteristics.setValue(V_Value);  //设置电压的特征值V_Characteristics.notify();   //发送特征值通知static char I_Value[8];  //定义局部静态变量 char型存放电流值字符串dtostrf(Current,6,2,I_Value);  I_Characteristics.setValue(I_Value);  //设置电流的特征值I_Characteristics.notify();   //发送特征值通知static char W_Value[8];  //定义局部静态变量 char型存放功率值字符串dtostrf(Power,6,2,W_Value);  W_Characteristics.setValue(W_Value);  //设置功率的特征值W_Characteristics.notify();   //发送特征值通知}
}

客户端代码

#include <Arduino.h>
#include <BLEDevice.h>
#include <BLECharacteristic.h>
#include <BLEServer.h>
#include<BLEService.h>
//引入头文件
#define bleServer "BLE_HWD_SER"
static BLEUUID ServiceUUID("f9da736b-dc49-4b7d-a023-8ecee2e72741");           //服务的UUID
static BLEUUID V_CharacteristicUUID("308a35f8-3e7b-11ed-b878-0242ac120002");  //电压特征UUID
static BLEUUID I_CharacteristicUUID("92ddd762-3e7d-11ed-b878-0242ac120002");  //电流特征UUID
static BLEUUID W_CharacteristicUUID("6b74077b-607f-4078-b179-4afeb03c34b7");  //功率特征UUID
static boolean doconnect = false;   //连接标识
static boolean connected = false;   //启动标识
static BLEAddress *pServerAddress;  //BLE服务器地址,外围设备的地址,地址在扫描过程中找到
static BLERemoteCharacteristic *V_Characteristic;  //需要读写的特征的指针
static BLERemoteCharacteristic *I_Characteristic;  //需要读写的特征的指针
static BLERemoteCharacteristic *W_Characteristic;  //需要读写的特征的指针
const uint8_t notificationON[] = {0x1, 0x0};   //激活打开
const uint8_t notificationOFF[] = {0x0,0x0};   //通知关闭char *V_value;  //存储电压值
char *I_value;  //存储电流值
char *W_value;  //存储功率值
boolean newV_value = false; //新电压值是否可用标志位
boolean newI_value = false; //新电流值是否可用标志位
boolean newW_value = false; //新功率值是否可用标志位//当BLE服务器发送带有通知属性的新电压读数 回调函数
static void V_NotifyCallback(BLERemoteCharacteristic* pBLERemoteCharacteristic,uint8_t* pData, size_t length, bool isNotify)
{V_value = (char*)pData;   //用于存储新的电压值newV_value = true;        //将新电压值判断置为 真
}//当BLE服务器发送带有通知属性的新电流读数 回调函数
static void I_NotifyCallback(BLERemoteCharacteristic* pBLERemoteCharacteristic,uint8_t* pData, size_t length, bool isNotify)
{I_value = (char*)pData;   //用于存储新的电流值newI_value = true;        //将新电流值判断置为 真
}//当BLE服务器发送带有通知属性的新功率读数 回调函数
static void W_NotifyCallback(BLERemoteCharacteristic* pBLERemoteCharacteristic,uint8_t* pData, size_t length, bool isNotify)
{W_value = (char*)pData;   //用于存储新的功率值newW_value = true;        //将新功率值判断置为 真
}bool connectToServer(BLEAddress pAddress)
{BLEClient *pClint = BLEDevice::createClient();  //BLE创建客户端pClint->connect(pAddress);  //连接到服务器BLERemoteService *pRemoteService = pClint->getService(ServiceUUID);   //在远程BLE服务器中获取我们所需要的服务器的引用if(pRemoteService == nullptr){return false;}V_Characteristic = pRemoteService->getCharacteristic(V_CharacteristicUUID);  //获取远程BLE服务器服务中的特征属性I_Characteristic = pRemoteService->getCharacteristic(I_CharacteristicUUID);  //获取远程BLE服务器服务中的特征属性W_Characteristic = pRemoteService->getCharacteristic(W_CharacteristicUUID);  //获取远程BLE服务器服务中的特征属性if(V_Characteristic == nullptr || I_Characteristic == nullptr || W_Characteristic == nullptr){return false;   //如果未找到特征,返回false;}//为特征分配各自的调用函数V_Characteristic->registerForNotify(V_NotifyCallback);  //特征注册通知I_Characteristic->registerForNotify(I_NotifyCallback);  //特征注册通知W_Characteristic->registerForNotify(W_NotifyCallback);  //特征注册通知return true;
}class MyAdvertisedDeviceCallbacks:public BLEAdvertisedDeviceCallbacks  //当接收到另一个设备的广播时,调用广播
{void onResult(BLEAdvertisedDevice advertiseDevice)   //BLE广播函数{if(advertiseDevice.getName() == bleServer)  //检查名字是否匹配{advertiseDevice.getScan()->stop();  //停止扫描,我们已经扫描到了需要的BLE服务器pServerAddress = new BLEAddress(advertiseDevice.getAddress());   //BLE广播地址是需要的doconnect = true;  //设置指示器,已经准备好连接Serial.println("Found Correctly!!");}}
};void UARTprint()    //串口输出信息函数
{Serial.print("V_value: ");Serial.print(V_value);Serial.print("V,  ");Serial.print("I_value: ");Serial.print(I_value);Serial.print("A,   ");Serial.print("W_value: ");Serial.print(W_value);Serial.println("W");
}/****************************************************************************/
void setup() {// put your setup code here, to run once:Serial.begin(115200);BLEDevice::init("");    //初始化BLE客户端设备BLEScan *pBLEScan = BLEDevice::getScan();   //检索扫描器并设置调用//pBLEScan->setAdvertisedDeviceCallbacks(new );  //设置广播并调用"广播类"pBLEScan->setActiveScan(true);  //设置为主动扫描pBLEScan->start(30);    //扫描运行30秒
}void loop() {// put your main code here, to run repeatedly:if(doconnect == true) //如果doconnect为真,说明已经扫描到了需要的BLE服务器{if(connectToServer(*pServerAddress))  //找到服务器之后连接到服务器地址{Serial.println("Now Connected");V_Characteristic->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t*)notificationON,2,true);//启动电压特征通知属性I_Characteristic->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t*)notificationON,2,true);//启动电流特征通知属性W_Characteristic->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t*)notificationON,2,true);//启动功率特征通知属性connected = true;  //一旦连接到BLE服务器,将连接标志设置为真}else{Serial.println("Can't connect,Please turn on again");}doconnect = false;  //将连接标志设置为假}if(newV_value && newI_value && newW_value)  //如果有新的度数可用,串口输出信息{newV_value = false;newI_value = false;newW_value = false;   //重新设置为假UARTprint();  //调用自定义串口信息输出函数}delay(1000);
}

接到BLE服务器,将连接标志设置为真
}
else
{
Serial.println(“Can’t connect,Please turn on again”);
}
doconnect = false; //将连接标志设置为假
}
if(newV_value && newI_value && newW_value) //如果有新的度数可用,串口输出信息
{
newV_value = false;
newI_value = false;
newW_value = false; //重新设置为假
UARTprint(); //调用自定义串口信息输出函数
}
delay(1000);
}

ESP32经典蓝牙和BLE的使用 (基于Arduino)相关推荐

  1. Android蓝牙开发—经典蓝牙和BLE(低功耗)蓝牙的区别

    找到一篇介紹BT与BLE使用差别的文章, 写的很清晰,看完基本明白了 ----------------------------------------------------------------- ...

  2. ESP32 (经典蓝牙 SPP)-蓝牙学习(9)

    提示:本博客作为学习笔记,有错误的地方希望指正   绪论:这里主要讲解一些关于ESP32的经典蓝牙,蓝牙是一个比较庞大的体系,需要又一些基础知识才可以更好的学习,这里有一些写的比较好的关于蓝牙的文章. ...

  3. ESP32 经典蓝牙 连接 Xbox ONE 手柄

    文章目录 软件架构 框架/framework: 组件/components: branch Bytheway Code 基于ESPIDF HID例程修改而来,使用经典蓝牙和Xbox ONE 手柄连接并 ...

  4. 蓝牙跳频算法分析【经典蓝牙 vs BLE 4.x vs BT 5.0 BLE部分】

    ---------------------------------------------------------------------------------------------------- ...

  5. Android 经典蓝牙与 BLE 蓝牙基础

    1. 蓝牙规范简介 蓝牙是一种无线技术标准,用来让固定与移动设备,在短距离间交换数据,以形成个人局域网(PAN).其使用短波特高频(UHF)无线电波,由 2.4 至 2.485 GHz 的 ISM 频 ...

  6. 经典蓝牙和BLE学习

    1.一些概念理解: 2.遇到的问题: (1)如何让设备作为BLE 设备被扫描到. 一些参考链接: 区别 active and passive scanning 蓝牙安全之Active Scanning ...

  7. esp32经典蓝牙和单片机连接,,,手机蓝牙作为主机

    步骤 1.编译AT固件,把金典蓝牙打开,默认不打开,烧录esp32: 2.按照 https://docs.espressif.com/projects/esp-at/zh_CN/latest/esp3 ...

  8. 蓝牙4.0、经典蓝牙、BT、BLE的关系与区别

    蓝牙3.0 比较老的标准了. 蓝牙4.0   蓝牙4.0标准是2012年推出的蓝牙标准,是蓝牙3.0的升级版本,相比3.0版本它更省电.成本更低,3毫秒低延迟.具有超长有效连接距离和AES-128加密 ...

  9. 我和蓝牙BT,BLE有一腿

    你好,很不幸,你被一个标题骗了进来,可能我以后还会骗你,我这篇文章主要是写蓝牙相关的,不会涉及技术细节,主要是总结一些概念,这些概念会帮助你了解蓝牙知识,帮助你在面试或者聊天的时候章显自己的技术优势, ...

最新文章

  1. UML学习---交互
  2. mysql 子查询添加索引_mysql – 你能索引子查询吗?
  3. 解决MySQL报错ERROR 2002 (HY000)【转】
  4. 八.利用springAMQP实现异步消息队列的日志管理
  5. java中引导页面的,设计模式之模板模式引导篇
  6. php开发简易论坛教程,[php] 我的微型论坛的简单教程[已完成]第3/8页
  7. Spring(1)—初识
  8. JSP和Servlet相同点和不同点?
  9. MySql的基本操作以及以后开发经常使用的常用指令
  10. 端口冲突,可爱的8080
  11. 计算机组成原理强制类型转换规则,计算机组成原理——浮点数加减运算强制类型转换...
  12. 智能家居APP设计规格
  13. 如何在你朋友面前伪装黑客6(程序代码)
  14. 设计测试用例需要注意的点
  15. 【一】机器学习在网络空间安全研究中的应用
  16. oracle经典分数排名,力扣数据库题目: 分数排名(中等)
  17. 农村信用社答题小程序
  18. javaweb(基础二)
  19. 商业智能(BI)目前的五大趋势
  20. 【HTML】html基本标签-1(文字,列表,图片标签)

热门文章

  1. 2023最新8个电脑必装软件,新电脑装完好用又高效
  2. Lyft抢先一步IPO,滴滴该何去何从?
  3. i2cGPIO补丁工具使用说明
  4. 学php到企业一般都做什么,学电子商务可以干什么 毕业后一般做什么工作
  5. 支付宝花呗分期 错误ALIN10046
  6. revit常用土建插件的【一键成板】功能,批量成板
  7. 一款非常精美的HTML响应式动画效果博客幻灯片
  8. 20150909,微软9月9日发布12个安全补丁
  9. 21个终身受用的顶级思维(深度好文)
  10. Docker从入门到实战