无线耳机,健身带,蓝牙扬声器,入耳式耳机,手机,笔记本电脑…我们周围有很多蓝牙设备,并且其中大多数设备都是电池供电的。您是否曾经想过,当您将蓝牙设备连接至手机时,蓝牙如何自动了解所连接的设备是计算机,音频设备还是手机?对于某些设备,我们的手机甚至可能会在通知栏上自动显示所连接设备的电池百分比。所有这些如何独自发生?手机和蓝牙设备之间应该共享一些通用协议!
请保持好奇,当我们尝试使用流行的ESP32模块理解低功耗蓝牙(简称BLE)时,您将获得这些问题的答案。与ESP32中的经典蓝牙不同,BLE仅在激活通信后才运行,否则将保持睡眠模式,这使其成为电池供电应用程序的正确选择。BLE还可以形成网状网络并充当信标。通常BLE模块可以用作服务器或客户端,在这里我们将使用ESP32 BLE作为服务器。
为了便于理解,在这里我们将完整的ESP32蓝牙分为三个部分。
1. ESP32上的串行蓝牙从手机切换LED
2 。BLE服务器使用GATT服务将电池电量数据发送到手机
3. BLE客户端扫描BLE设备并充当信标。
我们已经讨论了第一篇文章;在本文中,我们将学习如何使ESP32 BLE用作服务器并使用GATT服务发送电池电量信息。出于测试目的,我们将通过BLE GATT服务将ESP32的硬编码值作为电池百分比发送到我们的手机,通过这种方式,我们的移动设备将假定ESP32是电池供电的蓝牙设备,正在尝试发送其电池百分比。在详细介绍之前,我们将了解与蓝牙低功耗相关的一些术语。
与BLE(蓝牙低功耗)相关的术语
BLE服务器:如前所述,可以将BLE编程为服务器或客户端。当作为服务器工作时,BLE只能提供数据,而不能启动连接。例如健身带。服务器只能在客户端请求时发送信息。
ESP32的BLE最常用于服务器。每个服务器中将包含一个或多个服务,并且类似地,每个服务将具有一个或多个与之关联的特性。特征内部可能有零个,一个或多个描述符。每个服务,特征或描述符都将具有自己的预定义唯一ID,称为UUID。
BLE客户端:客户端可以扫描连接并收听其他蓝牙设备。一个例子就是您的手机。请注意,大多数BLE硬件设备都可以充当服务器和客户端,而这是决定设备角色的软件。
外围设备/中央设备: 在BLE网络中,可能只有一个中央设备,但可以具有所需的许多外围设备。中央设备可以同时连接到所有外围设备,但是外围设备只能连接到中央设备,因此,没有两个外围设备可以彼此共享数据。中央设备的最佳示例将是我们的智能手机,而外围设备的最佳示例将是我们的蓝牙耳机或健身带。
BLE广告: BLE广告是一个令人讨厌的术语,它指示蓝牙设备对所有人可见,以便它可以配对并建立连接。它可以被视为一种单向通信。服务器在这里继续发布广告数据,希望服务器能够接收它。BLE信标是BLE的一种。
UUID(通用唯一标识符):由编程人员编程时,每个BLE蓝牙设备都会获得一个通用唯一标识符编号。您可以将该标识符视为代表BLE设备功能/角色的数字序列。同样,有两种类型的UUID。一个是服务UUID,另一个是特征UUID。
GATT服务: GATT代表通用属性配置文件;这定义了两个BLE设备应始终进行通信的标准方法。此属性(ATT)协议是预定义的,并且对于所有BLE设备都是通用的,因此,任何两个BLE设备都可以相互识别。因此,关贸总协定是我们先前问题的答案。
两个BLE设备应使用来回发送数据的技术由称为服务和特性的概念定义。
BLE服务/ BLE特性:服务UUID告诉我们BLE设备将执行哪种类型的服务,特性UUID告诉我们该服务将执行哪些参数或功能。因此,每个服务都将具有一个或多个特征。好的!程序员从哪里获得此UUID?每个UUID已经由GATT(通用属性配置文件)定义,您可以访问其网站并根据项目要求选择UUID。我知道它已经在我们头顶反弹了一点;让我们尝试通过一个例子来理解它。
让我们假设音频播放器的BLE设备。最初,当您将其与手机配对时,手机会将其识别为音频设备,并在状态栏上显示电池电量。因此,要使这种情况发生,音频播放器必须以某种方式告诉您的手机,它愿意共享电池电量以及电池中的电量百分比。这是通过使用UUID来完成的,有一个特定的UUID告诉BLE骰子将提供有关电池电量的详细信息,该UUID告诉服务类型称为服务UUID,同样,可能有很多参数需要为了完成一项服务而被交换,就像电池的值在该参数上一样,每个参数将具有自己的UUID,它们被称为特性UUID。特性执行的常见功能是读取,写入,通知和指示。
BLE描述符:描述符是特性内部存在的可选属性。描述符通常指定如何访问特征。
BLE信标:蓝牙信标更像是接近开关,当用户进入范围(近距离)时,它会执行一些预定义的操作。它一直在宣传自己的身份,因此随时可以配对。
BLE2902:我对此事仍持怀疑态度,但您可以将其视为客户端上的一个软件,该软件通知服务器打开或关闭通知,这将帮助我们节省电源
希望您有一个大概的主意,好处是我们不需要了解太多,因为尽管通过库已经为我们完成了所有手工工作。
准备硬件
该项目不需要任何硬件设置,但请确保您已在Arduino IDE上添加了ESP32板的详细信息,并尝试了最小样本闪烁程序来检查是否一切正常。您对如何执行操作持怀疑态度,您可以按照ESP32入门与Arduino教程进行操作。
同样为了测试BLE服务,我们将在手机上使用nRF android应用程序,该应用程序可以直接从PlayStore下载。Itunes Store中也为Iphone用户提供了该功能。如果您打算长时间使用BLE,则此应用程序确实可用于调试目的。
使用GATT服务对ESP32进行电池电量指示编程
到此时,我假设您对什么GATT服务以及如何使用服务和特征模型来实现它有了一个清晰的认识。现在,让我们深入研究该程序,以了解如何使用Arduino IDE在ESP32中实现它。在继续之前,我想利用这个空间感谢Andreas Spiess的视频BLE,这使我很清楚。
我们通过将所需的库导入到草图中来开始程序。为了希望使用ESP32的BLE功能,需要配置很多东西,这要感谢Neil Kolban为我们完成了艰苦的工作并提供了库。如果您想了解库的功能,可以参考github页面上的文档。
#包括
接下来,我们必须为我们的蓝牙设备定义服务器回调功能。在此之前,让我们了解一下什么是BLE中的回调函数。
BLE中的回调函数是什么?
当BLE作为服务器运行时,定义服务器回调函数很重要。有许多与BLE相关的回调类型,但简单起见,您可以将它们视为正在执行的确认,以确保已完成操作。服务器回调用于确保成功建立客户端与服务器之间的连接。
我们使用以下代码行执行服务器回调。
bool _BLEClientConnected = false; class MyServerCallbacks :public BLEServerCallbacks { void onConnect(BLEServer * pServer){_ BLEClientConnected = true; }; 无效的onDisconnect(BLEServer * pServer){_ BLEClientConnected = false; } };
在 void设置 功能内部,我们在115200启动串行通信以进行调试,然后通过 InitBLE 功能初始化Bluetooth设备。
void setup(){ Serial.begin(115200); Serial.println(“电池电量指示器-BLE”); InitBLE(); }
该 initBLE 是所有魔法发生的地方。我们必须在此处创建一个蓝牙服务器并使用电池电量服务。但是在此之前,我们必须定义用于读取电池电量的服务,特征和描述符的UUID。可以从Bluetooth GATT服务网站获取所有UUID。对于我们的情况,我们尝试使用Battery服务,并将其UUID定义为0X180F,如下所示。
接下来,我们需要了解与此服务关联的特征。要知道,只需单击“电池服务”,您便会进入“服务特性”页面,其中提到电池电量是特性的名称,它的取值范围是0到100。另外请注意,我们只能执行两次具有此特征的操作,一个是必须执行的“读取”操作,另一个是“可选”的“通知”操作。因此,我们必须将电池值发送给客户端(电话),这是强制性的;如果需要,我们可以通知电话有关可选的电池值。
但是,等等,我们仍然找不到“电池特性”的UUID值。为此,请进入“电池特性”页面并搜索“电池电量”名称,您会发现其UUID为0X2A19,其快照如下所示。
现在我们有了所有的值,让我们将其放入程序,如下所示。名称 BatterySerivce , BatteryLevelCharacteristic 和 BatteryLevelDescriptor 是用户定义的变量,用于引用我们在程序中使用的服务,特征和描述符。当值的大小为8位时,将使用描述符0X2901的值,有关详细信息,请参见“描述符描述”页面。
#定义电池服务BLEUUID((uint16_t)0x180F)
BLECharacteristic BatteryLevelCharacteristic(BLEUUID((uint16_t)0x2A19),BLECharacteristic :: PROPERTY_READ- BLECharacteristic :: PROPERTY_NOTIFY); BLEDescriptor BatteryLevelDescriptor(BLEUUID((uint16_t)0x2901));
回到 initBLE 函数。我们首先必须启动BLE服务器,并使其带有名称进行广告。在下面的线用于启动BLE作为服务器。我为BLe服务器指定的名称是“ BLE Battery”,但您可以选择自己的名称。
BLEDevice:: init(“ BLE电池”); //创建BLE服务器 BLEServer * pServer = BLEDevice:: createServer(); pServer-> setCallbacks(new MyServerCallbacks());
接下来,由于我们已经定义了UUID,因此我们必须启动GATT服务,我们可以使用下面的代码行简单地启动该服务。
//创建BLE服务 BLEService * pBattery = pServer-> createService(BatteryService);
服务启动后,我们可以将描述符与特征链接,并设置值。如下所示,还添加了BLE2902服务。
pBattery-> addCharacteristic(&BatteryLevelCharacteristic); BatteryLevelDescriptor.setValue(“百分比0-100”); BatteryLevelCharacteristic.addDescriptor(&BatteryLevelDescriptor); BatteryLevelCharacteristic.addDescriptor(new BLE2902());
终于一切都准备好了,现在剩下的就是要求ESP32做广告,以便像我们的手机这样的其他设备可以发现它并连接到它,当连接到客户端时,它应该启动电池服务,这可以通过以下几行。
pServer-> getAdvertising()-> addServiceUUID(BatteryService); pBattery-> start(); //开始广告 pServer-> getAdvertising()-> start();
到目前为止,就这么好了,最后一步是告诉描述符应发送给客户端(电话)的电池电量百分比值。如我们先前所读,此值可以从0 -100开始,为简单起见,我已经简单地将电池的值硬编码为57,然后每5秒递增一次,并在电池达到100时从0开始。如下所示。请注意,正在发送的值的格式为unit8_t。
uint8_t等级= 57; void loop(){ BatteryLevelCharacteristic.setValue(&level,1); BatteryLevelCharacteristic.notify(); 延迟(5000); 级别++; Serial.println(int(level)); 如果(int(level)== 100) level = 0; }
在ESP32 BLE上测试GATT服务
在页末给出了上面解释的完整代码。将代码上传到ESP32开发板。上传后,您的手机应该会发现一个名为“ BLE Battery”的蓝牙设备。
然后安装nRF android应用程序并打开它并连接到BLE Battery BLE设备。展开“电池服务”部分,您将找到以下屏幕。
如您所见,由于我们在程序中使用了UUID,因此应用程序已自动识别出BLE提供了电池服务并具有电池电量的特性。您还可以看到当前电量为67%的电池等待5秒钟,并且您还会注意到它的电量在增加。
关于使用BLE的最酷的事情是,现在任何与BLE兼容的应用都将认为您的ESP32是BLE设备,它会通知电池电量。为了进行测试,我使用了一个名为BatON的应用程序,该应用程序将ESP32识别为电池供电的蓝牙设备,并在手机上给出了这样的百分比通知
凉!!对?我还在下面的视频中展示了完整的工作原理。现在,您已经了解了如何在ESP32上使用BLE电池服务,还可以尝试其他非常有趣的GATT服务,例如脉搏频率,HID,心率等。