ESP32 確實是一款功能強大的物聯網設備,內置了對藍牙和 WiFi 的支持。ESP32 是其前身 ESP8266 的高級版本,具有 RAM、ROM、GPIO 引腳等額外功能。ESP32 模塊支持經典藍牙和低功耗藍牙 (BLE),經典藍牙可用于傳輸歌曲或文件,BLE該選項可用于電池優化應用,如藍牙信標、健身手環、接近度廣告等。也可以將ESP32 用作串行藍牙,如用于簡單微控制器項目的 HC-05 或 HC-06 模塊。
在本教程中,我們將使用 ESP32 構建一個 BLE iBeacon,其中 ESP32 將充當服務器,智能手機將充當客戶端。
所需組件
硬件:
ESP32 開發板
微型 USB 數據線
軟件:
Arduino IDE
Android 應用程序:nRF Connect for Mobile(由 Nordic Semiconductor 提供)
有許多 BLE 掃描儀應用程序,其中一個我們在之前的項目“如何將 HM-10 BLE 模塊與 Arduino 一起使用”中使用過。這個 BLE 掃描儀應用程序提供了良好的圖形界面 (GUI),但缺乏額外的信息,所以在這個項目中,我們使用NRF Connect for Mobile 應用程序。
使用適用于 ESP32 iBeacon 的 nRF Connect Android 應用程序
1. 從 Google Play 商店下載 nRF Connect 應用程序并打開它。
2. 畫面如下。當找到設備時,此項目的有用選項將是“掃描”、“掃描儀”和“信息”。
“掃描”選項將用于查看所有可用的 iBeacon。要開始搜索 iBeacon,請下拉屏幕或轉到屏幕右上角的“掃描”選項。這將開始搜索可用的 iBeacons。
3.搜索iBeacon后,可以看到iBeacon的RSSI、UUID、Major和Minor。如果您將移動設備或 iBeacon 彼此遠離,RSSI 將發生變化。在此屏幕中,RSSI 為 (-37)。除此之外,還有一些詳細信息,例如虛擬公司名稱、設備類型、字節長度、ESP32 的本地名稱。這里是“ ESP32 as iBeacon ”。您可以在草圖中更改本地名稱。
4. 從iBeacon 拿走智能手機后,RSSI 值從-37 變為-58。如果您移動其中一臺設備,這些值將不斷變化。
RSSI 信號可接受值如下:
將 ESP32 編程為 BLE iBeacon
當您在 Arduino IDE 中安裝 ESP32 Board 時,可以使用 ESP32 BLE iBeacon 的示例程序。但是我們在本教程中稍微編輯了這個草圖,示例程序的完整編輯版本在本教程的末尾給出。
要打開 ESP32?BLE_iBeacon的示例程序,請按照以下步驟操作。
打開 Arduino IDE 并選擇“ESP32 Dev Module”。(如果您沒有找到此板,請檢查您是否安裝了 ESP32 板包)
轉到文件>示例>?ESP32 BLE Arduino?>?BLE_iBeacon
打開“BLE_iBeacon”草圖。
現在對本教程中的代碼進行了輕微修改。ESP32 名稱也將在此草圖中更新。因此,首先要包含必要的庫,這些庫將用于創建 BLE 服務器和 iBeacon。
?
#include "sys/time.h"
?
這是一個獲取當前系統時間的時間庫。這包含諸如tv_sec、gettimeofday() 等函數。有關更多信息,您可以訪問'?sys/time.h?'的官方 UNIX 版本。
然后包含 ESP32 BLE 庫,其中包含許多用于在不同配置中制作 ESP32 的函數,例如 BLE 客戶端或 BLE 服務器。
?
#include "BLEDevice.h" #include "BLEUtils.h" #include "BLEServer.h"
?
包含 iBeacon 庫,它將 ESP32 設置為 iBeacon。除此之外,ESP32還包含深度睡眠庫。該庫將用于在定義的時間段內以深度睡眠模式發送 ESP32。
?
#include "BLEBeacon.h" #include "esp_sleep.h"
?
定義 ESP32 的睡眠時間。在這里,ESP32 將進入深度睡眠 10 秒,它會做廣告,然后再次進入深度睡眠 10 秒。
?
#define GPIO_DEEP_SLEEP_DURATION 10
?
這里定義了RTC_DATA_ATTR。請注意,如果您使用 RTC_DATA_ATTR 屬性定義全局變量,該變量將被放入 RTC_SLOW_MEM 內存中。因此,聲明為 RTC_DATA_ATTR 的結構并在深度睡眠之前將動態內存復制到此結構有助于在喚醒后將其恢復到動態內存中。簡而言之,我們正在從動態內存中節省靜態內存中的時間,以便在深度睡眠后再次恢復它。這里定義了兩個變量。'?last?' 用于獲取 ESP32 進入深度睡眠的最后時間,并且bootcount用于計數重置次數。
?
RTC_DATA_ATTR 靜態 time_t 最后; RTC_DATA_ATTR 靜態 uint32_t 引導計數;
?
然后定義 BLE 廣告類型。定義如下。
?
BLEAdvertising *pAdvertising;
?
timeval被定義為訪問當前時間的結構。
?
現在構造timeval;
?
還定義了 UUID。可以從此鏈接生成 UUID 。
?
#define BEACON_UUID "87b99b2c-9XXd-11e9-bXX2-526XXXX64f64"
?
現在創建一個函數,該函數將包含 iBeacon 屬性,例如 UUID、Major、Minor 等。在此函數中,為 BLE 創建一個實例作為 iBeacon,并將 ESP32 的假制造商 ID、UUID、主要和次要設置為 iBeacon。
?
無效 setBeacon() { BLEBeacon oBeacon = BLEBeacon(); oBeacon.setManufacturerId(0x4C00); oBeacon.setProximityUUID(BLEUUID(BEACON_UUID)); oBeacon.setMajor((bootcount & 0xFFFF0000) >> 16); oBeacon.setMinor(bootcount & 0xFFFF);
?
將該標志設置為 0x04,以便它將在掃描儀中輸出BrEdrNotSupported。
?
oAdvertisementData.setFlags(0x04);
?
設置發布的廣告數據。
?
std::string strServiceData = "";
?
一個接一個地添加字符串進行廣告。
?
strServiceData += (char)26; // Len strServiceData += (char)0xFF; // 輸入 strServiceData += oBeacon.getData(); oAdvertisementData.addData(strServiceData);
?
通過發布數據開始廣告。
?
pAdvertising->setAdvertisementData(oAdvertisementData); pAdvertising->setScanResponseData(oScanResponseData);
?
以 115200 波特率啟動串行監視器并獲取時間。還要增加引導計數以存儲重置次數。
?
序列號.開始(115200); gettimeofday(&now, NULL); Serial.printf("啟動 ESP32 %d\n", bootcount++);
?
將當前時間存儲在靜態存儲器中。
?
最后 = now.tv_sec;
?
創建一個 BLE 設備并根據需要命名。這里 ESP32 被命名為“?ESP2 as iBeacon?”。請注意,名稱可以很長,但此版本的代碼已開始支持長名稱。
?
BLEDevice::init("ESP32 作為 iBeacon");
?
創建 BLE 服務器以進行廣告并開始廣告。
?
BLEServer *pServer = BLEDevice::createServer(); pAdvertising = BLEDevice::getAdvertising(); BLEDevice::startAdvertising();
?
然后將 ESP32 設置為 iBeacon 模式。
?
設置信標();
?
開始廣告然后停止廣告并進入深度睡眠 10 秒。
?
p廣告->開始(); pAdvertising->stop(); esp_deep_sleep(1000000LL * GPIO_DEEP_SLEEP_DURATION);
?
最后,使用 Micro USB 電纜將 ESP32 開發板與您的筆記本電腦連接,并使用 Arduino IDE 將代碼上傳到 ESP32。然后在您的智能手機中打開nRF Connect Android 應用程序并開始掃描。您會發現ESP32 作為 iBeacon廣播,如下圖所示:
#include “sys/time.h”
#include “BLEDevice.h”
#include “BLEUtils.h”
#include “BLEServer.h”
#include “BLEBeacon.h”
#include “esp_sleep.h”
#define GPIO_DEEP_SLEEP_DURATION 10 // 休眠 x 秒,然后喚醒
RTC_DATA_ATTR static time_t last;// 記住 RTC 內存中的上次啟動
RTC_DATA_ATTR static uint32_t bootcount; // 記住 RTC 內存中的啟動次數
// 有關生成 UUID,請參見以下內容:
// https://www.uuidgenerator.net/
BLEAdvertising *pAdvertising; // BLE 廣告類型
struct timeval now;
#define BEACON_UUID “87b99b2c-90fd-11e9-bc42-526af7764f64” // UUID 1 128 位(可以使用 linux 工具 uuidgen 或通過https://www.uuidgenerator.net/隨機數)
無效 setBeacon() {
BLEBeacon oBeacon = BLEBeacon();
oBeacon.setManufacturerId(0x4C00); // 假 Apple 0x004C LSB (ENDIAN_CHANGE_U16!)
oBeacon.setProximityUUID(BLEUUID(BEACON_UUID));
oBeacon.setMajor((bootcount & 0xFFFF0000) 》》 16);
oBeacon.setMinor(bootcount & 0xFFFF);
BLEAdvertisementData oAdvertisementData = BLEAdvertisementData();
BLEAdvertisementData oScanResponseData = BLEAdvertisementData();
oAdvertisementData.setFlags(0x04); // BR_EDR_NOT_SUPPORTED 0x04
std::string strServiceData = “”;
strServiceData += (char)26; // Len
strServiceData += (char)0xFF; //
輸入 strServiceData += oBeacon.getData();
oAdvertisementData.addData(strServiceData);
pAdvertising-》setAdvertisementData(oAdvertisementData);
pAdvertising-》setScanResponseData(oScanResponseData);
}
無效設置(){
序列號。開始(115200);
gettimeofday(&now, NULL);
Serial.printf(“啟動 ESP32 %d\n”, bootcount++);
Serial.printf(“深度睡眠(自上次重置以來的 %lds,自上次啟動以來的 %lds)\n”, now.tv_sec, now.tv_sec - last);
最后 = now.tv_sec;
// 創建 BLE 設備
BLEDevice::init(“ESP32 as iBeacon”);
// 創建 BLE 服務器
BLEServer *pServer = BLEDevice::createServer(); // 《-- 不再需要實例化 BLEServer,更少的閃存和內存使用
pAdvertising = BLEDevice::getAdvertising();
BLEDevice::startAdvertising();
設置信標();
// 開始廣告
pAdvertising-》start();
Serial.println(“廣告開始。..”);
延遲(100);
pAdvertising-》stop();
Serial.printf(“進入深度睡眠\n”);
esp_deep_sleep(1000000LL * GPIO_DEEP_SLEEP_DURATION);
Serial.printf(“處于深度睡眠中\n”);
}
無效循環(){
}
評論
查看更多