簡(jiǎn)介:
1.1藍(lán)牙分類
經(jīng)典藍(lán)牙我們一般說的是BT,低功耗藍(lán)牙我們一般說成BLE。當(dāng)設(shè)備支持藍(lán)牙4.0時(shí),還得進(jìn)一步確認(rèn)設(shè)備是支持BT單模、BLE單模還是BT和BLE都支持的雙模。
低功耗藍(lán)牙 (BLE): 支持藍(lán)牙協(xié)議4.0或更高的模塊。主打低功耗,多用于物聯(lián)網(wǎng)類型。
經(jīng)典藍(lán)牙( BT): 指支持藍(lán)牙協(xié)議在4.0以下的模塊。主打短距離數(shù)據(jù)高速傳輸,多用于藍(lán)牙耳機(jī)等。
經(jīng)典藍(lán)牙可再細(xì)分為:傳統(tǒng)藍(lán)牙和高速藍(lán)牙。
傳統(tǒng)藍(lán)牙: 2004年推出,藍(lán)牙2.0/2.1協(xié)議。
高速藍(lán)牙: 2009年推出,藍(lán)牙3.0協(xié)議,速率提高到約24Mbps,是傳統(tǒng)藍(lán)牙模塊的八倍。
雙模藍(lán)牙: 即兼容BLE和BT,如手機(jī),使用分時(shí)機(jī)制來達(dá)到同時(shí)與低功耗藍(lán)牙和經(jīng)典藍(lán)牙設(shè)備通信。
1.2藍(lán)牙技術(shù)
藍(lán)牙協(xié)議包括兩種技術(shù):Basic Rate(BR) 和 Low Energy(LE)。
Basic Rate又包括可選的EDR(Enhanced Data Rate) 技術(shù),以及 交替使用的(Alternate)的MAC(Media Access Control)層和PHY層擴(kuò)展(簡(jiǎn)稱AMP)。、
在藍(lán)牙4.0及后面規(guī)格中,SIG定義了四種藍(lán)牙技術(shù):BR,EDR,AMP和LE ,由于LE是2010年才提出的,比較新,所以人們把之前的BR/EDR/AMP技術(shù)稱之為經(jīng)典藍(lán)牙。
經(jīng)典藍(lán)牙( BT):
BR(Basic Rate): 藍(lán)牙基礎(chǔ)速率技術(shù)。
EDR(Enhanced Data Rate) : 藍(lán)牙增強(qiáng)速率技術(shù)。
AMP (Alternate MAC/PHYs): 藍(lán)牙核心系統(tǒng)的次要控制器,可切換的媒體訪問控制器(Media Access Controller)和物理層(Physical Layer)。
低功耗藍(lán)牙 (BLE):
LE(Low Energy): 藍(lán)牙低功耗技術(shù)。
注意:
EDR 是在 BR 技術(shù)基礎(chǔ)上升級(jí),所以兩者可以同時(shí)使用。但是AMP 技術(shù)是使用的802.11(WIFI)規(guī)范,所以和原有的技術(shù)差異過大,所以BR/EDR和AMP只能二選一進(jìn)行使用。
LE技術(shù)相比BR技術(shù),差異非常大,可以說就是兩種不同的技術(shù)。經(jīng)典藍(lán)牙和低功耗藍(lán)牙兩者物理層調(diào)制解調(diào)方式是不一樣的,所以低功耗藍(lán)牙設(shè)備和經(jīng)典藍(lán)牙設(shè)備兩者之間是不能相互通信的。

而我們的esp32自帶藍(lán)牙模塊可以讓我們進(jìn)行藍(lán)牙連接并進(jìn)行數(shù)據(jù)交換
相關(guān)API:
一、經(jīng)典藍(lán)牙BT使用方法
經(jīng)典藍(lán)牙API
BluetoothSerial SerialBT :創(chuàng)建一個(gè)藍(lán)牙串口,命名為SerialBT
SerialBT.begin() :開啟藍(lán)牙
SerialBT.available() :返回藍(lán)牙串口緩沖區(qū)中當(dāng)前剩余的字符個(gè)數(shù)。
SerialBT.print() :藍(lán)牙串口發(fā)送的是字符,
SerialBT.write() :藍(lán)牙串口發(fā)送的字節(jié).
Serial.read() :返回藍(lán)牙串口接收的字符
程序示例代碼:
//This example code is in the Public Domain (or CC0 licensed, at your option.)
//By Evandro Copercini - 2018
//
//This example creates a bridge between Serial and Classical Bluetooth (SPP)
//and also demonstrate that SerialBT have the same functionalities of a normal Serial
#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
BluetoothSerial SerialBT;
void setup() {
Serial.begin(115200);
SerialBT.begin("ESP32test"); //Bluetooth device name
Serial.println("The device started, now you can pair it with bluetooth!");
}
void loop() {
if (Serial.available()) {
SerialBT.write(Serial.read());//將串口收到的數(shù)據(jù),再通過藍(lán)牙串口轉(zhuǎn)發(fā)出去
Serial.println("由SerialBT打印");
}
if (SerialBT.available()) {//將藍(lán)牙串口收到的數(shù)據(jù),再通過串口把信息發(fā)回給電腦
Serial.write(SerialBT.read());
Serial.println("由Serial打印");
}
delay(20);
}
二、低功耗藍(lán)牙BLE使用方法
簡(jiǎn)介:
BLE GATT協(xié)議
GATT全稱Generic Attribute Profile, GATT 代表通用屬性,它定義了暴露給連接的BLE設(shè)備的分層數(shù)據(jù)結(jié)構(gòu)。這意味著,GATT 定義了兩個(gè)BLE設(shè)備,發(fā)送和接收標(biāo)準(zhǔn)通訊的方式。了解此層次結(jié)構(gòu)很重要,因?yàn)檫@樣可以,更輕松地了解如何使用BLE和編寫應(yīng)用程序。
下圖為BLE的基本結(jié)構(gòu),需要記清楚

UUID:ble的服務(wù)和characteristic是通過UUID來進(jìn)行識(shí)別的。創(chuàng)建uuid可以使用這么一個(gè)網(wǎng)站:
Online UUID Generator Tool
notify:如果這個(gè)主機(jī)的一個(gè)特征值characteristic發(fā)生改變,就可以通過notify來告訴我們
創(chuàng)建 BLE 服務(wù)器代碼流程:
1,創(chuàng)建一個(gè)BLE服務(wù)器。在這種情況下,ESP32充當(dāng)BLE服務(wù)器。
2,創(chuàng)建BLE服務(wù)。
3,在服務(wù)上創(chuàng)建BLE特性。
4,在特征上創(chuàng)建一個(gè)BLE描述符。
5,啟動(dòng)服務(wù)。
6,開始廣播,以便其他設(shè)備可以找到它。
低功耗藍(lán)牙API:
創(chuàng)建一個(gè)BLE設(shè)備
BLEDevice::init(ble_name);
創(chuàng)建一個(gè)BLE服務(wù)
pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks()); //設(shè)置回調(diào)
BLEService *pService = pServer->createService(SERVICE_UUID);
創(chuàng)建一個(gè)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()); //設(shè)置回調(diào)
這里創(chuàng)建了一個(gè)特征值,類型是通知。
在后面使用createCharacteristic(CHARACTERISTIC_UUID_RX, BLECharacteristic::PROPERTY_WRITE)將rx收集到的信息寫入,通過MyCallbacks再打印出來
為了實(shí)現(xiàn)"串口",我們?cè)谶@個(gè)服務(wù)下添加了兩個(gè)特征值, 一個(gè)是TX. 一個(gè)是RX.另外還需注意三個(gè)uuid因該是相對(duì)應(yīng)的值。
開始服務(wù)和廣播
pService->start(); // 開始服務(wù)
pServer->getAdvertising()->start(); // 開始廣播
Serial.println(" 等待一個(gè)客戶端連接,且發(fā)送通知... ");
代碼示例
/*
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.
創(chuàng)建一個(gè)BLE服務(wù)器,一旦我們收到連接,將會(huì)周期性發(fā)送通知
T使用步驟:
1. 創(chuàng)建一個(gè) BLE Server
2. 創(chuàng)建一個(gè) BLE Service
3. 創(chuàng)建一個(gè) BLE Characteristic
4. 創(chuàng)建一個(gè) BLE Descriptor
5. 開始服務(wù)
6. 開始廣播
*/
#include <Arduino.h>
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#include "common.h"
uint8_t txValue = 0; //后面需要發(fā)送的值
BLEServer *pServer = NULL; //BLEServer指針 pServer
BLECharacteristic *pTxCharacteristic = NULL; //BLECharacteristic指針 pTxCharacteristic
bool deviceConnected = false; //本次連接狀態(tài)
bool oldDeviceConnected = false; //上次連接狀態(tài)d
// 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);
// 創(chuàng)建一個(gè) BLE 設(shè)備
BLEDevice::init("BAKUMAN");//在這里面是ble的名稱
// 創(chuàng)建一個(gè) BLE 服務(wù)
pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks()); //設(shè)置回調(diào)
BLEService *pService = pServer->createService(SERVICE_UUID);
// 創(chuàng)建一個(gè) 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()); //設(shè)置回調(diào)
pService->start(); // 開始服務(wù)
pServer->getAdvertising()->start(); // 開始廣播
Serial.println(" 等待一個(gè)客戶端連接,且發(fā)送通知... ");
}
void loop()
{
// deviceConnected 已連接
if (deviceConnected)
{
pTxCharacteristic->setValue(&txValue, 1); // 設(shè)置要發(fā)送的值為1
pTxCharacteristic->notify(); // 廣播
txValue++; // 指針數(shù)值自加1
delay(2000); // 如果有太多包要發(fā)送,藍(lán)牙會(huì)堵塞
}
// disconnecting 斷開連接
if (!deviceConnected && oldDeviceConnected)
{
delay(500); // 留時(shí)間給藍(lán)牙緩沖
pServer->startAdvertising(); // 重新廣播
Serial.println(" 開始廣播 ");
oldDeviceConnected = deviceConnected;
}
// connecting 正在連接
if (deviceConnected && !oldDeviceConnected)
{
// do stuff here on connecting
oldDeviceConnected = deviceConnected;
}
}
在loop函數(shù)中我們的藍(lán)牙連接會(huì)對(duì)應(yīng)三種狀態(tài):
這里講解一下當(dāng)設(shè)備連接時(shí)的情況:
if (deviceConnected){
pTxCharacteristic->setValue(&txValue, 1); // 設(shè)置要發(fā)送的值為1
pTxCharacteristic->notify(); // 廣播
txValue++; // 指針數(shù)值自加1
delay(2000); // 如果有太多包要發(fā)送,藍(lán)牙會(huì)堵塞
}
這里面測(cè)試的是不停發(fā)送數(shù)據(jù),每發(fā)一次數(shù)值加一。 此時(shí):
class MyServerCallbacks : public BLEServerCallbacks
{
void onConnect(BLEServer *pServer)
{
deviceConnected = true;
};
void onDisconnect(BLEServer *pServer)
{
deviceConnected = false;
}
};
通過這個(gè)回調(diào)可以說清楚這個(gè)藍(lán)牙到底有沒有連接,如果連接了通過 文章來源:http://www.zghlxwxcb.cn/news/detail-778018.html
pServer->setCallbacks(new MyServerCallbacks());
這個(gè)MyServerCallbacks回調(diào)就可以返回連接狀態(tài)。 文章來源地址http://www.zghlxwxcb.cn/news/detail-778018.html
到了這里,關(guān)于ESP32 Arduino學(xué)習(xí)篇 (三) 藍(lán)牙的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!