ESP32, IOT物聯網

【IOT物聯網應用-ESP32】第二十篇:ESP32和iPhone手機的BLE藍牙進行數據通訊

實驗說明:

第十九篇已經跟各位介紹過ESP32與Android的藍牙相互數據傳輸,在本篇將會示範ESP32與iPhone手機的BLE(Bluetooth Low Energy低功耗藍牙)進行資料傳送與接收。

 

材料:

  • ESP32-E DevKit
  • USB 傳輸線
  • iPhone手機或平板

▼ 購買IoT物聯網學習教材:

ESP32 物聯網應用學習套件 ESP32CAM IoT物聯網學習教材 適用Arduino

 

相關知識:

低功耗藍牙(Bluetooth Low Energy,BLE)是藍牙技術聯盟(SIG)所製定的無線個人區域網路技術規範,與傳統藍牙(Bluetooth)不同的是,它以省電、低功耗的特性為人所知,是IoT 近年十分熱門的協定之一。在應用 BLE 藍芽前,必須瞭解的兩個協議:GAP(通用訪問協議)、GATT(通用屬性協議)。簡單來說就是分別負責連線前資料廣播和連線後的資料傳輸。

GAP(Generic Access Profile):

主要用來控制裝置連線(connection)和廣播(advertising),GAP 使你的裝置被其他裝置可見,並決定了你的裝置是否可以或者怎樣與互動裝置進行通訊。GAP 給裝置角色定義,其中主要的兩個是:

  • 外圍裝置(Peripheral):也可以稱作「從模式-Slave」或是「服務端」。外圍裝置就是非常小或者簡單的低功耗裝置,用來提供資料,並連線到一個更加相對強大的中心裝置,例如小米手環。
  • 中心裝置(Central):也可以稱作「主模式-Master」或是「客戶端」。中心裝置相對比較強大,用來連線其他外圍裝置。例如手機等。

GATT 的全名是 Generic Attribute Profile:

GATT 定義兩個 BLE 裝置通過叫做 Service 和 Characteristic 的東西進行通訊。一旦兩個裝置建立起了連線,GATT 就開始起作用了,這也意味著,你必需完成前面的 GAP 協議。GATT 通訊的雙方是 C/S 關係。外設作為 GATT 服務端(Server),它維持了 ATT 的查詢表以及 service 和 characteristic 的定義。中心裝置是 GATT 客戶端(Client),它向 Server 發起請求。需要注意的是,所有的通訊事件,都是由客戶端(也叫主裝置,Master)發起,並且接收服務端(也叫從裝置,Slave)的響應。

若需要了解更詳細的藍牙規範細節,可參考SIG網站:https://www.bluetooth.com/specifications/specs/

程式:

#include <BLEDevice.h> 
#include <BLEServer.h> 
#include <BLEUtils.h> 
#include <BLE2902.h> 
#include <String.h> 

BLECharacteristic *pCharacteristic;
bool deviceConnected = false;
uint8_t txValue = 0;
long lastMsg = 0;
String rxload="Test\n";

/*為BLE供應商定義指定的 UUID 編號*/
#define SERVICE_UUID           "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" 
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"

/*為BLE服務器編寫一個Callback函式來管理BLE的連接。*/
class MyServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {
      deviceConnected = true;
    };
    void onDisconnect(BLEServer* pServer) {
      deviceConnected = false;
    }
};

/*具有BLE功能的Callback函式。 
 *調用時,移動終端向 ESP32 發送數據時,會將其存儲到 reload 中。
 */
class MyCallbacks: public BLECharacteristicCallbacks {
    void onWrite(BLECharacteristic *pCharacteristic) {
      std::string rxValue = pCharacteristic->getValue();
      if (rxValue.length() > 0) {
        rxload="";
        for (int i = 0; i < rxValue.length(); i++){
          rxload +=(char)rxValue[i];
        }
      }
    }
};

/*創建BLE server流程:
 *1. Create a BLE Server
 *2. Create a BLE Service
 *3. Create a BLE Characteristic on the Service
 *4. Create a BLE Descriptor on the characteristic 
 *5. Start the service
 *6. Start advertising
 */
void setupBLE(String BLEName){
  const char *ble_name=BLEName.c_str();
  BLEDevice::init(ble_name);
  BLEServer *pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());
  BLEService *pService = pServer->createService(SERVICE_UUID); 
  pCharacteristic= pService->createCharacteristic(CHARACTERISTIC_UUID_TX,BLECharacteristic::PROPERTY_NOTIFY);
  pCharacteristic->addDescriptor(new BLE2902());
  BLECharacteristic *pCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_RX,BLECharacteristic::PROPERTY_WRITE);
  pCharacteristic->setCallbacks(new MyCallbacks()); 
  pService->start();
  pServer->getAdvertising()->start();
  Serial.println("Waiting a client connection to notify...");
}

void setup() {
  Serial.begin(115200);
  setupBLE("ESP32_BLE"); //初始化BLE並為其命名,藍牙顯示名稱可自行更改
}

/*當手機通過BLE藍牙向ESP32發送訊息時,會通過ESP32的序列視窗顯示出來; 
 *經由ESP32的序列視窗發送訊息後,會通過BLE藍牙發送到手機。
 */
void loop() {
  long now = millis();
  if (now - lastMsg > 100) {
    if (deviceConnected&&rxload.length()>0) {
        Serial.println(rxload);
        rxload="";
    }
    if(Serial.available()>0){
        String str=Serial.readString();
        const char *newValue=str.c_str();
        pCharacteristic->setValue(newValue);
        pCharacteristic->notify();
    }
    lastMsg = now;
  }
}

 

程式說明:

將範例程式編譯並上傳程式碼到ESP32開發板後,接著我們開始設定手機端的部分。

▼首先,請至iPhone App Store 下載並安裝『lightblue』

 

▼請先開啟iPhone手機藍牙,再將剛剛安裝完成的Lightblue APP開啟。在掃描頁面,向下滑動刷新手機搜索的藍牙名稱,選擇ESP32_BT進行配對連線。

點擊”Notify”。進入頁面後請點擊「Listen for notification」讓它先進入監聽模式(這個很重要!),然後在右上的框中可以選擇適當的數據格式。例如,HEX 表示十六進制,UTF-8-String 表示字符,Binary 表示二進制等。請選擇UTF-8-String數據格式。

 

接下來在ESP32的序列視窗發送訊息後,我們即可在手機視窗內接收到ESP32傳來的文字訊息。注意鮑率需要設定在115200

 

▼點擊”Write”。在右上的框中可以選擇UTF-8-String數據格式。

 

▼在手機端點擊「Write new value」,接著輸入文字後並按鍵盤處的Done送出資料,我們即可在ESP32的序列視窗內接收到手機傳來的文字訊息。

 

 

相關文章