ESP32藍(lán)牙和BLE簡述和基本使用方法
經(jīng)典藍(lán)牙串口通信
#include "BluetoothSerial.h" //引入藍(lán)牙函數(shù)庫
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif //判斷藍(lán)牙是否啟用
const int led = 2;
BluetoothSerial SerialBT; //定義一個自擬的藍(lán)牙串口通信名稱
void setup()
{
pinMode(led,OUTPUT);
digitalWrite(led,LOW);
SerialBT.begin("ESP32_Blue"); //啟動藍(lán)牙串口并設(shè)置藍(lán)牙的名稱
Serial.begin(115200);
}
void loop()
{
if(SerialBT.available()) //判斷藍(lán)牙串口是否收到數(shù)據(jù)
{
char res = SerialBT.read(); //將收到的數(shù)據(jù)讀取出來,下面分別處理
if(res == 'A')
{
digitalWrite(led,LOW);
Serial.println("Get OFF");
}
else if(res == 'B')
{
digitalWrite(led,HIGH);
Serial.println("Get ON");
}
}
delay(10);
}
該程序效果如下
-
ESP32完成初始化后生成一個藍(lán)牙信號
-
-
手機(jī)通過藍(lán)牙串口發(fā)送字符 B ,LED點亮
-
手機(jī)通過藍(lán)牙串口發(fā)送字符 A ,LED熄滅
低功耗藍(lán)牙 BLE (常用)
- BLE GATT協(xié)議
GATT全稱Generic Attribute Profile, GATT 代表通用屬性,它定義了暴露給連接的BLE設(shè)備的分層數(shù)據(jù)結(jié)構(gòu)。這意味著,GATT 定義了兩個BLE設(shè)備,發(fā)送和接收標(biāo)準(zhǔn)通訊的方式。了解此層次結(jié)構(gòu)很重要,因為這樣可以,更輕松地了解如何使用BLE和編寫應(yīng)用程序。
下圖為BLE的基本結(jié)構(gòu),需要記清楚
-
低功耗特性
特征始終歸服務(wù)所有,它是層次結(jié)構(gòu)(值)中包含實際數(shù)據(jù)的地方。特征始終具有兩個屬性:特征聲明(提供有關(guān)數(shù)據(jù)的元數(shù)據(jù))和特征值。
此外,特征值后面可以跟描述符,這進(jìn)一步擴(kuò)展了特征聲明中包含的元數(shù)據(jù)。
這些屬性描述了如何與特征值交互。基本上,它包含可以與特征一起使用的操作和過程:
廣播
閱讀
寫無響應(yīng)
寫
通知
表示
經(jīng)過身份驗證的簽名寫入擴(kuò)展屬性 -
用戶名
每個服務(wù),特征,描述符都有一個UUID(通用唯一標(biāo)識符)。UUID是唯一的128位(16 byte)數(shù)字
在線UUID生成 -
創(chuàng)建 BLE 服務(wù)器代碼流程
1,創(chuàng)建一個BLE服務(wù)器。在這種情況下,ESP32充當(dāng)BLE服務(wù)器。
2,創(chuàng)建BLE服務(wù)。
3,在服務(wù)上創(chuàng)建BLE特性。
4,在特征上創(chuàng)建一個BLE描述符。
5,啟動服務(wù)。
6,開始廣播,以便其他設(shè)備可以找到它。
-
代碼示例
//此程序通過BLE廣播,其他設(shè)備接受廣播,手機(jī)通過nRF Connet軟件連接,
//手機(jī)下發(fā)字符 1 點亮LED,字符 0 關(guān)閉LED
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <BLEService.h>
#include <BLECharacteristic.h>
#define SERVICE_UUID "b408e1a0-3d8a-11ed-b878-0242ac120002" //服務(wù)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);
//設(shè)置服務(wù)器所需要的配置
void setup() {
Serial.begin(115200);
BLEDevice::init("BLE_HWD"); //創(chuàng)建設(shè)備
BLEServer *pServer = BLEDevice::createServer(); //設(shè)置為服務(wù)器
BLEService *pService = pServer->createService(SERVICE_UUID); //使用上面的服務(wù)UUID創(chuàng)建服務(wù)
// 添加一個帶有對象名(官方UUID)的特征,不帶對象,這個特征不會改變
BLECharacteristic *nameCharacteristic = pService->createCharacteristic(BLEUUID((uint16_t)0x2A00), BLECharacteristic::PROPERTY_READ);
nameCharacteristic->setValue("LED"); //顯示特征名
pService->addCharacteristic(&controlCharacteristic); //增加一個控制LED的特性
controlCharacteristic.setValue(&state);
//設(shè)置特征, 使用上面的特征UUID,需要將特征的屬性作為參數(shù)傳遞。此情況下是讀或?qū)?/span>
BLECharacteristic *pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE);
pCharacteristic->setValue("Hello HWD!!!"); //創(chuàng)建完特征后,可以使用setValue()方法為其在此賦值
//此值可以是其他傳感器的值
pService->start();
//下面是啟動服務(wù)和廣播,以便其他BLE設(shè)備找到此 BLE 設(shè)備
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising(); //BLE廣播
pAdvertising->addServiceUUID(SERVICE_UUID); //廣播添加服務(wù) UUID
pAdvertising->setScanResponse(true); //廣播掃描響應(yīng)
pAdvertising->setMinPreferred(0x06); //廣播設(shè)置最小首選
pAdvertising->setMinPreferred(0x12); //廣播設(shè)置最小首選
BLEDevice::startAdvertising(); //BLE 設(shè)備啟動廣播,特征已經(jīng)定義,可以在手機(jī)中讀取它
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 服務(wù)器和客戶端通信
下面程序?qū)崿F(xiàn)了客戶端不斷從服務(wù)器讀取模擬傳感器的值并顯示出來
程序模擬了電壓電流和功率信息的傳遞
服務(wù)器端代碼
#include "Arduino.h"
#include "BLEDevice.h" //BLE驅(qū)動庫
#include "BLEServer.h" //BLE藍(lán)牙服務(wù)器庫
#include "BLEUtils.h" //BLE實用程序庫
#include "BLE2902.h" //特征添加描述符庫
#include <BLECharacteristic.h> //BLE特征函數(shù)庫
float Volt = 220.00; //電壓值設(shè)置為220V
float Current = 20.00; //電流值設(shè)置為20A
float Power = 4400.00; //功率設(shè)置位4400W
//可通過外接傳感器改變這些值
#define bleServerName "BLE_HWD_SER" //BLE服務(wù)器的名稱
#define SERVICE_UUID "f9da736b-dc49-4b7d-a023-8ecee2e72741" //服務(wù)的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; //創(chuàng)建設(shè)備連接標(biāo)識符
class MyServerCallbacks:public BLEServerCallbacks //創(chuàng)建連接和斷開調(diào)用類
{
void Connected(BLEServer *pServer)//開始連接函數(shù)
{
connected_state = true; //設(shè)備正確連接
}
void Disconnected(BLEServer *pServer)//斷開連接函數(shù)
{
connected_state = false; //設(shè)備連接錯誤
}
};
void setup()
{
BLEDevice::init(bleServerName); //創(chuàng)建BLE并設(shè)置名稱
BLEServer *pServer = BLEDevice::createServer(); //創(chuàng)建BLE服務(wù)器
pServer->setCallbacks(new MyServerCallbacks()); //設(shè)置連接和斷開調(diào)用類
BLEService *pService = pServer->createService(SERVICE_UUID); //創(chuàng)建BLE服務(wù)
//創(chuàng)建 BLE 特征和描述符
pService->addCharacteristic(&V_Characteristics); //創(chuàng)建電壓特征
V_Descriptor.setValue("Volt"); //創(chuàng)建電壓描述符
V_Characteristics.addDescriptor(new BLE2902()); //給電壓特征添加描述符
pService->addCharacteristic(&I_Characteristics); //創(chuàng)建電流特征
I_Descriptor.setValue("Current"); //創(chuàng)建電流描述符
I_Characteristics.addDescriptor(new BLE2902()); //給電流特征添加描述符
pService->addCharacteristic(&W_Characteristics); //創(chuàng)建功耗特征
W_Descriptor.setValue("Power"); //創(chuàng)建功耗描述符
W_Characteristics.addDescriptor(new BLE2902()); //給功耗特征添加描述符
pService->start(); //啟動服務(wù)
pServer->getAdvertising()->start(); //開始廣播
}
void loop()
{
if(connected_state) //有設(shè)備連接
{
static char V_Value[8]; //定義局部靜態(tài)變量 char型存放電壓值字符串
dtostrf(Volt,6,2,V_Value); //將浮點數(shù)轉(zhuǎn)化為char型字符串 char Volt_Value[8] = {'2','2','0','.','0','0'}
V_Characteristics.setValue(V_Value); //設(shè)置電壓的特征值
V_Characteristics.notify(); //發(fā)送特征值通知
static char I_Value[8]; //定義局部靜態(tài)變量 char型存放電流值字符串
dtostrf(Current,6,2,I_Value);
I_Characteristics.setValue(I_Value); //設(shè)置電流的特征值
I_Characteristics.notify(); //發(fā)送特征值通知
static char W_Value[8]; //定義局部靜態(tài)變量 char型存放功率值字符串
dtostrf(Power,6,2,W_Value);
W_Characteristics.setValue(W_Value); //設(shè)置功率的特征值
W_Characteristics.notify(); //發(fā)送特征值通知
}
}
客戶端代碼文章來源:http://www.zghlxwxcb.cn/news/detail-789410.html
#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"); //服務(wù)的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; //連接標(biāo)識
static boolean connected = false; //啟動標(biāo)識
static BLEAddress *pServerAddress; //BLE服務(wù)器地址,外圍設(shè)備的地址,地址在掃描過程中找到
static BLERemoteCharacteristic *V_Characteristic; //需要讀寫的特征的指針
static BLERemoteCharacteristic *I_Characteristic; //需要讀寫的特征的指針
static BLERemoteCharacteristic *W_Characteristic; //需要讀寫的特征的指針
const uint8_t notificationON[] = {0x1, 0x0}; //激活打開
const uint8_t notificationOFF[] = {0x0,0x0}; //通知關(guān)閉
char *V_value; //存儲電壓值
char *I_value; //存儲電流值
char *W_value; //存儲功率值
boolean newV_value = false; //新電壓值是否可用標(biāo)志位
boolean newI_value = false; //新電流值是否可用標(biāo)志位
boolean newW_value = false; //新功率值是否可用標(biāo)志位
//當(dāng)BLE服務(wù)器發(fā)送帶有通知屬性的新電壓讀數(shù) 回調(diào)函數(shù)
static void V_NotifyCallback(BLERemoteCharacteristic* pBLERemoteCharacteristic,uint8_t* pData, size_t length, bool isNotify)
{
V_value = (char*)pData; //用于存儲新的電壓值
newV_value = true; //將新電壓值判斷置為 真
}
//當(dāng)BLE服務(wù)器發(fā)送帶有通知屬性的新電流讀數(shù) 回調(diào)函數(shù)
static void I_NotifyCallback(BLERemoteCharacteristic* pBLERemoteCharacteristic,uint8_t* pData, size_t length, bool isNotify)
{
I_value = (char*)pData; //用于存儲新的電流值
newI_value = true; //將新電流值判斷置為 真
}
//當(dāng)BLE服務(wù)器發(fā)送帶有通知屬性的新功率讀數(shù) 回調(diào)函數(shù)
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創(chuàng)建客戶端
pClint->connect(pAddress); //連接到服務(wù)器
BLERemoteService *pRemoteService = pClint->getService(ServiceUUID); //在遠(yuǎn)程BLE服務(wù)器中獲取我們所需要的服務(wù)器的引用
if(pRemoteService == nullptr)
{
return false;
}
V_Characteristic = pRemoteService->getCharacteristic(V_CharacteristicUUID); //獲取遠(yuǎn)程BLE服務(wù)器服務(wù)中的特征屬性
I_Characteristic = pRemoteService->getCharacteristic(I_CharacteristicUUID); //獲取遠(yuǎn)程BLE服務(wù)器服務(wù)中的特征屬性
W_Characteristic = pRemoteService->getCharacteristic(W_CharacteristicUUID); //獲取遠(yuǎn)程BLE服務(wù)器服務(wù)中的特征屬性
if(V_Characteristic == nullptr || I_Characteristic == nullptr || W_Characteristic == nullptr)
{
return false; //如果未找到特征,返回false;
}
//為特征分配各自的調(diào)用函數(shù)
V_Characteristic->registerForNotify(V_NotifyCallback); //特征注冊通知
I_Characteristic->registerForNotify(I_NotifyCallback); //特征注冊通知
W_Characteristic->registerForNotify(W_NotifyCallback); //特征注冊通知
return true;
}
class MyAdvertisedDeviceCallbacks:public BLEAdvertisedDeviceCallbacks //當(dāng)接收到另一個設(shè)備的廣播時,調(diào)用廣播
{
void onResult(BLEAdvertisedDevice advertiseDevice) //BLE廣播函數(shù)
{
if(advertiseDevice.getName() == bleServer) //檢查名字是否匹配
{
advertiseDevice.getScan()->stop(); //停止掃描,我們已經(jīng)掃描到了需要的BLE服務(wù)器
pServerAddress = new BLEAddress(advertiseDevice.getAddress()); //BLE廣播地址是需要的
doconnect = true; //設(shè)置指示器,已經(jīng)準(zhǔn)備好連接
Serial.println("Found Correctly!!");
}
}
};
void UARTprint() //串口輸出信息函數(shù)
{
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客戶端設(shè)備
BLEScan *pBLEScan = BLEDevice::getScan(); //檢索掃描器并設(shè)置調(diào)用
//pBLEScan->setAdvertisedDeviceCallbacks(new ); //設(shè)置廣播并調(diào)用"廣播類"
pBLEScan->setActiveScan(true); //設(shè)置為主動掃描
pBLEScan->start(30); //掃描運(yùn)行30秒
}
void loop() {
// put your main code here, to run repeatedly:
if(doconnect == true) //如果doconnect為真,說明已經(jīng)掃描到了需要的BLE服務(wù)器
{
if(connectToServer(*pServerAddress)) //找到服務(wù)器之后連接到服務(wù)器地址
{
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服務(wù)器,將連接標(biāo)志設(shè)置為真
}
else
{
Serial.println("Can't connect,Please turn on again");
}
doconnect = false; //將連接標(biāo)志設(shè)置為假
}
if(newV_value && newI_value && newW_value) //如果有新的度數(shù)可用,串口輸出信息
{
newV_value = false;
newI_value = false;
newW_value = false; //重新設(shè)置為假
UARTprint(); //調(diào)用自定義串口信息輸出函數(shù)
}
delay(1000);
}
接到BLE服務(wù)器,將連接標(biāo)志設(shè)置為真
}
else
{
Serial.println(“Can’t connect,Please turn on again”);
}
doconnect = false; //將連接標(biāo)志設(shè)置為假
}
if(newV_value && newI_value && newW_value) //如果有新的度數(shù)可用,串口輸出信息
{
newV_value = false;
newI_value = false;
newW_value = false; //重新設(shè)置為假
UARTprint(); //調(diào)用自定義串口信息輸出函數(shù)
}
delay(1000);
}文章來源地址http://www.zghlxwxcb.cn/news/detail-789410.html
到了這里,關(guān)于ESP32經(jīng)典藍(lán)牙和BLE的使用 (基于Arduino)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!