Začínáme s ESP32 Bluetooth Low Energy (BLE)
- UPOZORNĚNÍ
- Následující článek byl již upraven pro jádro Arduino ESP32 verze 3.x.
V minulém článku věnovanému Bluetooth jsme si ukázali základní použití Bluetooth Classic v modulu ESP32. Dnes bychom se rádi podívali na tzv. Bluetooth Low Energy (BLE). Nejprve v rychlosti si trochu zopakujeme, co je BLE a k čemu se dá použít. Poté se podíváme na několik příkladů s modulem ESP32, který budeme programovat pomocí Arduino IDE. Nakonec bychom si měli z modulu ESP32 vytvořit jednoduchý BLE server, ale také i BLE skener, který předchozí server najde.
Co je Bluetooth Low Energy?
Bluetooth Low Energy alias BLE (dříve uváděný na trh jako Bluetooth Smart) je vysoce optimalizovaná verze klasického Bluetooth navržená speciálně pro bezdrátovou komunikaci s nízkou spotřebou. Primárním účelem BLE je přenos malého množství dat na krátkou vzdálenost (nízká šířka pásma). Na rozdíl od Bluetooth, které je vždy zapnuté, zůstává BLE v režimu spánku, ze kterého se probudí, jen když je zahájeno připojení. Díky tomu má velmi nízkou spotřebu energie. BLE spotřebuje přibližně 100× méně energie než Bluetooth (v závislosti na případu použití). BLE navíc podporuje nejen komunikaci typu point-to-point, ale také režim vysílání a síť typu Mesh.
Zjednodušeně řečeno, každé zařízení Mesh sítě je kromě své funkce zároveň routerem, který může přenášet informace od ostatních zařízení. To zvyšuje spolehlivost sítě a její dosah. Zatímco standardní BT vysílání dosáhne řádově deseti metrů, Bluetooth Low Energy desítek metrů, s pomocí síťového propojení Mesh se reálný dosah pohybuje ve stovkách metrů, pokud jsou pokryty zařízeními, schopnými předávat informace.
Díky svým vlastnostem je BLE vhodný pro aplikace, které potřebují vyměňovat malé objemy dat, například využití ve zdravotnictví, ve fitness náramcích, v zabezpečovací technice a obecně v domácí automatizaci.
BLE
S Bluetooth Low Energy existují dva typy zařízení: server a klient. Modul ESP32 pochopitelně může fungovat buď jako klient nebo jako server. Server inzeruje svou existenci, takže jej může najít jiná zařízení a obsahuje data, která může klient číst. Klient prohledá okolní zařízení, a když najde hledaný server, naváže spojení a naslouchá příchozím datům. Tomu se říká komunikace point-to-point (česky též tzv. dvoubodový spoj).
Jak již bylo zmíněno dříve, BLE také podporuje režim vysílání a Mesh síť:
- Režim vysílání: server přenáší data mnoha klientům, kteří jsou připojeni
- Mesh síť: všechna zařízení jsou připojena, jedná se o mnohonásobné připojení.
Sítě Mesh byly vyvinuty velmi nedávno, takže v tuto chvíli není mnoho příkladů implementovaných pro modul ESP32, ale budeme se snažit něco pro Vás najít a vyzkoušet. Pokud již nějaký tokový příklad máte, budeme vděčni, když se s námi o své zkušenosti podělíte.
GATT
GATT je zkratka pro Generic Attributes a definuje hierarchickou datovou strukturu, která je vystavena připojeným zařízením BLE. To znamená, že GATT definuje způsob, jakým dvě zařízení BLE odesílají a přijímají standardní zprávy. Pochopení této hierarchie je důležité, protože vám usnadní pochopení toho, jak používat BLE a psát své aplikace.
Služba BLE
Nejvyšší úrovní hierarchie je profil, který se skládá z jedné nebo více služeb. Zařízení BLE obvykle obsahuje více než jednu službu. Každá služba obsahuje alespoň jednu charakteristiku, případně může odkazovat i na jiné služby. Služba je jednoduše sbírka informací, jako jsou například údaje ze senzorů. Existují předdefinované služby pro několik typů dat definovaných SIG (Bluetooth Special Interest Group), jako jsou: stav baterie, krevní tlak, srdeční frekvence, hmotnost atd.
Charakteristika BLE
Charakteristiku vždy určuje daná služba a je to místo, kde jsou v hierarchii (hodnotě) obsažena skutečná data. Charakteristika má vždy dva atributy: deklaraci charakteristiky (která poskytuje metadata o datech) a hodnotu charakteristiky. Navíc za charakteristickou hodnotou mohou následovat deskriptory, které dále rozšiřují metadata obsažená v deklaraci charakteristiky. Vlastnosti popisují, jak může být charakteristická hodnota ovlivněna. V zásadě obsahuje operace a postupy, které lze použít s charakteristikou:
- Broadcast (Přenos)
- Read (Čtení)
- Write without response (Zápis bez odezvy)
- Write (Zápis)
- Notify (Oznámení)
- Indicate (Označení)
- Authenticated Signed Writes (Ověřený zápisy)
- Extended Properties (Rozšířené vlastnosti)
UUID
Každá služba, charakteristika a deskriptor mají UUID (Universally Unique Identifier). UUID je jedinečné 128bitové (16 bajtové) číslo.
Například:
55072829-
Existují zkrácené UUID pro všechny typy, služby a profily specifikované v SIG (Bluetooth Special Interest Group). Pokud však naše aplikace potřebuje vlastní UUID, můžeme jej vygenerovat pomocí této webové stránky generátoru UUID. Stručně řečeno, UUID se používá pro jednoznačnou identifikaci informací. Může například identifikovat konkrétní službu poskytovanou zařízením Bluetooth.
BLE a modul ESP32
ESP32 může fungovat jako BLE server nebo jako BLE klient. Původně externí knihovna ESP32_BLE_Arduino
, kterou budeme dále používat, je již součástí prostředí Arduino IDE, takže tuto knihovnu ani nemusíme do prostředí Arduino IDE dodatečně instalovat. K dispozici máme i několik ukázkových programů – pokud se na ně chcete podívat, přejděte ve svém prostředí Arduino IDE na Soubor > Příklady > ESP32 BLE Arduino.
- Poznámka:
- Chcete-li vidět příklady pro modul ESP32, musíte mít desku s ESP32 vybranou v nabídce Nástroje > Vývojová deska.
Modul ESP32 jako BLE Server
Při vytvoření BLE serveru by měly v kódu našeho programu následovat následující kroky:
- Vytvořit objekt BLE serveru.
- Vytvořit službu BLE.
- Vytvořit charakteristiku BLE pro službu.
- Vytvořit deskriptor BLE pro charakteristiku.
- Spustit službu.
- Začít se „inzerovat“, aby jej mohla najít jiná zařízení.
Nevypadá to jednoduše, co? Tak raději pro začátek použijeme něco již hotového a postupně si kód vysvětlíme. Pro náš účel použijeme základní ukázkový program BLE_server. Otevřeme prostředí Arduino IDE a přejděte na Soubor > Příklady > ESP32 BLE Arduino a vyberte příklad BLE_serveru.
Měl by se načíst následující kód:
/*
Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleServer.cpp
Ported to Arduino ESP32 by Evandro Copercini
updates by chegewara
*/
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
// See the following for generating UUIDs:
// https://www.uuidgenerator.net/
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
void setup() {
Serial.begin(115200);
Serial.println("Starting BLE work!");
BLEDevice::init("MyESP32"); // Long name works now
BLEServer *pServer = BLEDevice::createServer();
BLEService *pService = pServer->createService(SERVICE_UUID);
BLECharacteristic *pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE
);
pCharacteristic->setValue("Hello World says Neil");
pService->start();
// BLEAdvertising *pAdvertising = pServer->getAdvertising(); // this still is working for backward compatibility
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
pAdvertising->setScanResponse(true);
pAdvertising->setMinPreferred(0x06); // functions that help with iPhone connections issue
pAdvertising->setMinPreferred(0x12);
BLEDevice::startAdvertising();
Serial.println("Characteristic defined! Now you can read it in your phone!");
}
void loop() {
// put your main code here, to run repeatedly:
delay(2000);
}
Jak kód funguje
Pojďme se tedy podívat na to, jak tento ukázkový kód serveru BLE funguje.
Začíná importem knihoven nezbytných pro funkce BLE.
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
Poté musíte definovat UUID pro službu a charakteristiku.
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
UUID můžeme ponechat výchozí, nebo můžeme přejít na uuidgenerator.net a vytvořit náhodná UUID pro naše služby a vlastnosti.
V proceduře setup()
se kromě nastavení sériového portu vytvoří objekt zařízení BLE s názvem „MyESP32“. (Tento název si můžeme změnit na jakýkoli jiný).
// Create the BLE Device
BLEDevice::init("MyESP32");
Na následujícím řádku se zařízení BLE nastaví jako server.
BLEServer *pServer = BLEDevice::createServer();
Poté se vytvoří služba pro server BLE s dříve definovaným UUID.
BLEService *pService = pServer->createService(SERVICE_UUID);
V dalším kroku musíme nastavit charakteristiku pro tuto službu. Používáme UUID definovanou dříve a jako argumenty musíte předat vlastnosti charakteristiky. V tomto případě to jsou: ČTENÍ; a ZÁPIS.
BLECharacteristic *pCharacteristic =
pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE
);
Po vytvoření charakteristiky můžete nastavit její hodnotu pomocí metody setValue()
.
pCharacteristic->setValue("Hello World says Neil");
V tomto případě nastavujeme hodnotu na text „Hello World says Neil
“. Tento text opět můžeme změnit na svůj libovolný. V budoucích projektech může být tímto textem například čtení senzoru nebo stav LED.
Konečně můžete spustit službu a „inzerci“, takže ostatní zařízení BLE mohou toto zařízení BLE skenovat a najít.
BLEAdvertising *pAdvertising = pServer->getAdvertising();
pAdvertising->start();
Toto je jen jednoduchý příklad, jak vytvořit BLE server. V tomto kódu se nic nedělá, proto je hlavní smyčka loop()
prázdná, ale můžete přidat, co se má stát, když se připojí nový klient (pokyny najdete v příkladu BLE_notify).
Modul ESP32 jako BLE skener
Pokud jsme pochopili princip předchozího příkladu, mělo by být vytvoření BLE skeneru poměrně jednoduché. Abychom měli co skenovat, necháme předchozí program běžet na jednom modulu ESP32 a vezmeme další vývojovou deku s ESP32 a naprogramujeme ji jako BLE skener. V prostředí Arduino IDE přejděte na Soubor > Příklady > ESP32 BLE Arduino a vyberte příklad BLE_scan.
Měl by se načíst následující kód:
/*
Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleScan.cpp
Ported to Arduino ESP32 by Evandro Copercini
*/
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
int scanTime = 5; //In seconds
BLEScan *pBLEScan;
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
void onResult(BLEAdvertisedDevice advertisedDevice) {
Serial.printf("Advertised Device: %s \n", advertisedDevice.toString().c_str());
}
};
void setup() {
Serial.begin(115200);
Serial.println("Scanning...");
BLEDevice::init("");
pBLEScan = BLEDevice::getScan(); //create new scan
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
pBLEScan->setInterval(100);
pBLEScan->setWindow(99); //less or equal setInterval value
}
void loop() {
// put your main code here, to run repeatedly:
BLEScanResults *foundDevices = pBLEScan->start(scanTime, false);
Serial.print("Devices found: ");
Serial.println(foundDevices->getCount());
Serial.println("Scan done!");
pBLEScan->clearResults(); // delete results fromBLEScan buffer to release memory
delay(2000);
}
Tento kód inicializuje modul ESP32 jako zařízení BLE a vyhledá okolní zařízení. Vyzkoušíme ho tedy tak, že jej nahrajeme do druhého modulu ESP32. (Možná nebude od věci, dočasně odpojit druhý ESP32 od počítače, abychom si byli jisti, že nahráváme kód na správnou vývojovou desku s modulem ESP32. 😉).
Jakmile je kód nahrán a měli byste mít zapnuté dvě desky ESP32:
- Jednu vývojovou desku s modulem ESP32, která je naprogramována jako
BLE_server
, - Druhou vývojovou desku s programem
BLE_scan
.
Přejdeme na sériový monitor modulu ESP32 se spuštěným programem BLE_scan
, tento modul restartujeme (tlačítko EN, resp. RST). Po restartu počkáme několik sekund, než proběhne skenování BLE okolních zařízení.
Obrázek 5 – Vyhledávání BLE serveru na moduly ESP32 pomocí BLE skeneru na druhém ESP32
Po přeložení kódu, jeho nahrání do modulu ESP32 bychom měli v okně sériového monitoru vidět výstup podobný následujícímu obrázku.
Na obrázku č. 6 dokonce vidíme, že náš BLE skener nalezl nejen modul ESP32, na kterém běží BLE server, ale i fitness náramek, který byl v blízkosti. 😎
Testování BLE serveru na modulu ESP32 pomocí smartphonu
Většina moderních smartphonů dnes již BLE funkce podporuje, takže náš BLE server na modulu ESP32 by se měl dát chytrým telefonem naskenovat a prohlédnout si jeho služby a vlastnosti. K tomu využijeme bezplatnou aplikaci s názvem nRF Connect for Mobile od společnosti Nordic® Semiconductor. Tato aplikace je dostupná pro telefony jak s operačním systémem Android (odkaz na Google Play Store), tak systémem iOS (odkaz na App Store).
Přejdeme tedy do obchodu Google Play nebo App Store a vyhledáma a nainstalujeme aplikaci nRF Connect for Mobile.
Po spuštění aplikace nezapomeňte přejít do nastavení Bluetooth a povolit adaptér Bluetooth. Můžete jej také zviditelnit pro ostatní zařízení, abyste mohli později testovat další programy.
Jakmile je vše připraveno ve smartphonu, spustíme v modulu ESP32 program BLE_server
. V pravém horním rohu okna aplikace klikneme na tlačítko SCAN a mobil začne vyhledávat zařízení v okolí. Měli bychom mimo jiného najít i modul ESP32 s programem BLE server, pojmenovaný MyESP32.
U našeho ESP32 BLE serveru (MyESP32) klikneme na tlačítko CONNECT.
Jak můžete vidět na obrázku níže, ESP32 má službu s UUID, které jste definovali dříve. Pokud klepnete na službu (Unknown Service), popřípadě klepneme na nabídku Read characteristics (v menu tří teček v šedé listě), zobrazí se charakteristika s UUID, které jste také definovali.
Charakteristika má vlastnosti READ
a WRITE
a hodnota je hodnota, kterou jste dříve definovali v náčrtu serveru BLE. Takže vše funguje dobře.
Pro dnešek se asi shodneme, že už toho Bluetooth bylo dost! A příště se zase sejdeme u nějakého „bastlířsky přívětivějšího“ tématu. 🤓