Bluetooth LE: керуємо ESP32 з телефона без Wi-Fi
Робимо з ESP32 BLE-пристрій із сервісом UART: надсилаємо команди з телефона та отримуємо відповіді. Працює там, де немає роутера — у машині, на велосипеді, в гаражі.
Навіщо BLE
Wi-Fi потребує роутера, а Bluetooth Low Energy — лише телефона поруч. ESP32 має BLE «на борту», тож додаткові модулі не потрібні. Ми реалізуємо популярний сервіс Nordic UART Service (NUS) — для нього вже є готові застосунки-термінали, тож писати свій застосунок не доведеться.
Як це працює:
- телефон пише текст у характеристику RX → ESP32 виконує команду;
- ESP32 надсилає відповідь через характеристику TX зі сповіщенням (notify).
Що знадобиться
- ESP32 DevKit (вбудований світлодіод на GPIO 2 або свій LED + 330 Ом)
- Смартфон із застосунком:
- Android — Serial Bluetooth Terminal або nRF Connect;
- iOS — nRF Toolbox (режим UART) або Bluefruit Connect.
Бібліотека BLE входить до ядра arduino-esp32 — нічого встановлювати не треба.
Код
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLE2902.h>
// Стандартні UUID Nordic UART Service
#define SERVICE_UUID "6e400001-b5a3-f393-e0a9-e50e24dcca9e"
#define RX_UUID "6e400002-b5a3-f393-e0a9-e50e24dcca9e" // телефон → ESP32
#define TX_UUID "6e400003-b5a3-f393-e0a9-e50e24dcca9e" // ESP32 → телефон
const int LED_PIN = 2;
BLECharacteristic *txChar;
bool connected = false;
unsigned long lastNotify = 0;
void sendText(const String &text) {
txChar->setValue((uint8_t *)text.c_str(), text.length());
txChar->notify();
}
class ServerCallbacks : public BLEServerCallbacks {
void onConnect(BLEServer *server) override {
connected = true;
}
void onDisconnect(BLEServer *server) override {
connected = false;
BLEDevice::startAdvertising(); // дозволяємо підключитися знову
}
};
class RxCallbacks : public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *c) override {
String cmd = String(c->getValue().c_str());
cmd.trim();
cmd.toLowerCase();
if (cmd == "on") {
digitalWrite(LED_PIN, HIGH);
} else if (cmd == "off") {
digitalWrite(LED_PIN, LOW);
} else if (cmd != "status") {
sendText("Commands: on, off, status\n");
return;
}
sendText("LED " + String(digitalRead(LED_PIN) ? "ON" : "OFF") + "\n");
}
};
void setup() {
Serial.begin(115200);
pinMode(LED_PIN, OUTPUT);
BLEDevice::init("ESP32-LED");
BLEServer *server = BLEDevice::createServer();
server->setCallbacks(new ServerCallbacks());
BLEService *service = server->createService(SERVICE_UUID);
txChar = service->createCharacteristic(TX_UUID, BLECharacteristic::PROPERTY_NOTIFY);
txChar->addDescriptor(new BLE2902());
BLECharacteristic *rxChar = service->createCharacteristic(
RX_UUID, BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_WRITE_NR);
rxChar->setCallbacks(new RxCallbacks());
service->start();
BLEAdvertising *adv = BLEDevice::getAdvertising();
adv->addServiceUUID(SERVICE_UUID);
adv->setScanResponse(true);
BLEDevice::startAdvertising();
Serial.println("Advertising as ESP32-LED");
}
void loop() {
// Раз на 5 с надсилаємо телефону «пульс» з часом роботи
if (connected && millis() - lastNotify > 5000) {
lastNotify = millis();
sendText("uptime " + String(millis() / 1000) + " s\n");
}
}
Перевірка
- Прошийте плату. У Serial Monitor з'явиться
Advertising as ESP32-LED. - Відкрийте застосунок-термінал → Devices → Bluetooth LE → оберіть ESP32-LED.
- Надішліть
on— світлодіод засвітиться, у відповідь прийдеLED ON. - Кожні 5 секунд у терміналі з'являтиметься
uptime ….
Створювати пару з пристроєм у системних налаштуваннях Bluetooth не потрібно — підключення відбувається прямо із застосунку.
Нюанси
- Ядро 2.x vs 3.x.
getValue()повертаєstd::stringу 2.x іStringу 3.x. Виклик.c_str()робить код сумісним з обома версіями. - Розмір пакета. За замовчуванням в одне повідомлення вміщується 20 байт; довші рядки розбивайте або збільшуйте MTU.
- Безпека. Будь-хто поруч може підключитися. Для реальних пристроїв увімкніть шифрування з PIN (
BLESecurity) або перевіряйте «пароль» першою командою. - BLE і Wi-Fi можуть працювати одночасно, але це займає багато пам'яті — для великих проєктів подивіться бібліотеку NimBLE-Arduino.
Ідеї
- Керування реле у гаражі чи в машині без інтернету.
- Веб-сторінка з Web Bluetooth API (Chrome), яка підключається до ESP32 напряму з браузера.
- Налаштування Wi-Fi через BLE замість порталу — так роблять комерційні пристрої.