ESP32经典蓝牙和BLE的使用 (基于Arduino)

这篇具有很好参考价值的文章主要介绍了ESP32经典蓝牙和BLE的使用 (基于Arduino)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

ESP32蓝牙和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完成初始化后生成一个蓝牙信号

  • esp32经典蓝牙例子,单片机,嵌入式硬件

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

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

低功耗蓝牙 BLE (常用)

  • BLE GATT协议

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

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

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

  • 用户名
    每个服务,特征,描述符都有一个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"         //控制特征UUID

const 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);                  //广播添加服务 UUID
  pAdvertising->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"  //服务的UUID

BLECharacteristic 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);
}文章来源地址https://www.toymoban.com/news/detail-789410.html

到了这里,关于ESP32经典蓝牙和BLE的使用 (基于Arduino)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 006.合宙ESP32-C3+蓝牙调试器通过BLE发送接收数据教程

    006.合宙ESP32-C3+蓝牙调试器通过BLE发送接收数据教程

    在平衡小车制作过程中,需要对KP/KD/KSP/KSI等PID系数进行调试,而平衡小车无法通过USB等进行有线调试,而ESP32-C3自带蓝牙+WIFI,使用WIFI比较吃算力,故选择通过蓝牙进行调参,同时能够将Angle/Encoder/PWM等数据回传至手机端进行查看。 前期通过查找资料,发现合宙ESP32-C3自带蓝

    2024年02月03日
    浏览(10)
  • ESP32 Arduino学习篇 (三) 蓝牙

    ESP32 Arduino学习篇 (三) 蓝牙

    经典蓝牙我们一般说的是BT,低功耗蓝牙我们一般说成BLE。当设备支持蓝牙4.0时,还得进一步确认设备是支持BT单模、BLE单模还是BT和BLE都支持的双模。 低功耗蓝牙 (BLE): 支持蓝牙协议4.0或更高的模块。主打低功耗,多用于物联网类型。 经典蓝牙( BT): 指支持蓝牙协议在4.0以

    2024年02月03日
    浏览(8)
  • Arduino下 ESP32蓝牙与PC蓝牙数据传输

    Arduino下 ESP32蓝牙与PC蓝牙数据传输

    打开Arduino,选择“文件”—“示例”—“BluetoothSerial”—“SerialToSerialBT”: 然后选择开发板和端口,编译烧录,在下方发送框内输入要发送的信息 设置好上边的,打开电脑蓝牙,搜索新设备 连接ESP32test 在下方会看到已添加设备 再点击更多蓝牙选项、COM端口、选择ESP32tes

    2024年02月10日
    浏览(10)
  • ESP32用作经典蓝牙串口透传模块与手机进行串口通信

    ESP32用作经典蓝牙串口透传模块与手机进行串口通信

    ESP32-WROOM-32模组集成了双模蓝牙包括传统蓝牙(BR/EDR)、低功耗蓝牙(BLE)和 Wi-Fi,具有广泛的用途:Wi-Fi 支持极大范围的通信连接,也支持通过路由器直接连接互联网;而蓝牙可以让用户连接手机或者广播 Bluetooth LE Beacon 以便于信号检测。 蓝牙特性: • 支持标准 Class-1、

    2024年02月09日
    浏览(15)
  • 基于ESP32 蓝牙游戏手柄设计

    基于ESP32 蓝牙游戏手柄设计

    使用 ESP32 并通过 BLE 通信的 DIY 手持游戏手柄   硬件组件 esp32        ×    1     ws2812b        ×    6     操纵杆        ×    2     角度按钮    ×    2     按钮        ×    8     18560电池和电池座×    2     3路拨动开关    ×    1     TP4056带保

    2024年02月02日
    浏览(11)
  • 【ESP32】arduino中的ESP32实时系统FreeRTOS使用教程(一)

    【ESP32】arduino中的ESP32实时系统FreeRTOS使用教程(一)

    简单的本节略过,详细的可以看视频:单片机ESP32上的FREERTOS这个作者讲的挺好的,通俗易懂 FreeRTOS中的任务有运行态、就绪态、阻塞态、挂起态四种状态,在任何时候都只处于其中一种状态。任务状态之间的转换如下图所示: 每一个任务都会有一个任务优先级,其范围为

    2023年04月15日
    浏览(11)
  • 【ESP32之旅】ESP32C3 Arduino库使用方法

    【ESP32之旅】ESP32C3 Arduino库使用方法

    目前官方已经支持了ESP32C3 的部分功能,可以在其官方wiki中看到: 官方提供了两个版本的安装连接,release和Dev。其中Release为稳定发布版本,Dev版本则支持更多的新特性。 Stable release link: Development release link: 安装方法也非常简单,打开Arduino IDE 然后在 文件 - 首选项 : 在附加

    2024年02月02日
    浏览(14)
  • 基于 Arduino 库实现 ESP32 TCP Server 应用例程

    基于 Arduino 库实现 ESP32 TCP Server 应用例程

    ESP32 开启 WiFi Station 模式连接路由器 连上路由器后将获取到分配的 IP 地址 基于分配的 IP 地址创建 TCP Server 手机与 ESP32 连接同一路由器 查看 UART0 日志打印,获取 TCP Server 的 IP 地址 使用手机端 TCP 调试 APP 与 ESP32 创建的 TCP Server 建立连接

    2024年02月12日
    浏览(15)
  • ESP32 Arduino(十二)lvgl移植使用

    ESP32 Arduino(十二)lvgl移植使用

    LVGL全程LittleVGL,是一个轻量化的,开源的,用于嵌入式GUI设计的图形库。并且配合LVGL模拟器,可以在电脑对界面进行编辑显示,测试通过后再移植进嵌入式设备中,实现高效的项目开发。 SquareLine Studio 是LVGL官方推荐的UI设计平台,可以便捷地设计界面并一键生成代码导出。

    2024年02月12日
    浏览(6)
  • 【ESP32最全学习笔记(基础篇)——7.ESP32 ADC – 使用 Arduino IDE 读取模拟值】

    关于本教程: 1.ESP32简介                                                                 2.ESP32 Arduino 集成开发环境 3.VS 代码和 PlatformIO 4.ESP32 引脚 5.ESP32 输入输出 6.ESP32 脉宽调制 7.ESP32 模拟输入 ☑ 8.ESP32 中断定时器 9 .ESP32 深度睡眠 ESP32 网络

    2023年04月15日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包