Начало работы с ESP32 Bluetooth Low Energy (BLE) в Arduino IDE

ESP32 поставляется не только с Wi-Fi, но также с Bluetooth и Bluetooth Low Energy (BLE). Эта статья представляет собой краткое введение в BLE с ESP32. Сначала мы рассмотрим, что такое BLE и для чего он может использоваться, а затем рассмотрим несколько примеров с ESP32, используя Arduino IDE. Для простого введения мы создадим BLE-сервер на ESP32 и BLE-сканер на ESP32 для поиска этого сервера.

Начало работы с ESP32 Bluetooth Low Energy (BLE) в Arduino IDE

Обновлено 11 июня 2024

Введение в Bluetooth Low Energy

Для быстрого ознакомления с BLE вы можете посмотреть видео ниже или прокрутить вниз для текстового объяснения.

Рекомендуемое чтение: узнайте, как использовать ESP32 Bluetooth Classic с Arduino IDE для обмена данными между ESP32 и смартфоном Android.

Что такое Bluetooth Low Energy?

Bluetooth Low Energy, сокращенно BLE, является энергосберегающим вариантом Bluetooth. Основное применение BLE – передача небольших объемов данных на короткие расстояния (низкая пропускная способность). В отличие от Bluetooth, который постоянно включен, BLE постоянно находится в спящем режиме, за исключением моментов, когда инициируется соединение.

Это обеспечивает очень низкое энергопотребление. BLE потребляет примерно в 100 раз меньше энергии, чем Bluetooth (в зависимости от сценария использования).

Введение в BLE - сравнение энергопотребления

Кроме того, BLE поддерживает не только связь «точка-точка», но также режим широковещания и ячеистую сеть (mesh network).

Взгляните на таблицу ниже, которая более подробно сравнивает BLE и Bluetooth Classic.

Сравнение Bluetooth Classic и Bluetooth Low Energy

Источник изображения

Благодаря своим свойствам BLE подходит для приложений, которым необходимо периодически обмениваться небольшими объемами данных, работая от батарейки типа «таблетка». Например, BLE широко используется в здравоохранении, фитнесе, отслеживании, маяках, безопасности и индустрии домашней автоматизации.

Области применения BLE

BLE-сервер и клиент

В Bluetooth Low Energy существует два типа устройств: сервер и клиент. ESP32 может выступать как в роли клиента, так и в роли сервера.

Сервер объявляет о своем существовании, чтобы его могли найти другие устройства, и содержит данные, которые клиент может прочитать. Клиент сканирует ближайшие устройства, и когда находит нужный сервер, устанавливает соединение и прослушивает входящие данные. Это называется связью «точка-точка».

BLE-сервер и клиент - связь точка-точка

Как упоминалось ранее, BLE также поддерживает режим широковещания и ячеистую сеть:

  • Режим широковещания: сервер передает данные множеству подключенных клиентов;

  • Ячеистая сеть (Mesh network): все устройства соединены между собой, это связь «многие ко многим».

Несмотря на то, что настройки широковещания и ячеистой сети возможны для реализации, они были разработаны совсем недавно, поэтому на данный момент для ESP32 не так много реализованных примеров.

GATT

GATT расшифровывается как Generic Attributes (общие атрибуты) и определяет иерархическую структуру данных, которая доступна подключенным BLE-устройствам. Это означает, что GATT определяет способ, которым два BLE-устройства отправляют и получают стандартные сообщения. Понимание этой иерархии важно, поскольку оно облегчит использование BLE и написание ваших приложений.

Иерархия GATT для BLE на ESP32

BLE-сервис

Верхний уровень иерархии – это профиль, который состоит из одного или нескольких сервисов. Обычно BLE-устройство содержит более одного сервиса.

Каждый сервис содержит как минимум одну характеристику или может также ссылаться на другие сервисы. Сервис – это просто набор информации, например, показания датчиков.

Существуют предопределенные сервисы для различных типов данных, определенных SIG (Bluetooth Special Interest Group), таких как: уровень заряда батареи, кровяное давление, частота сердечных сокращений, весы и т.д. Вы можете посмотреть другие определенные сервисы здесь.

Предопределенные GATT-сервисы Bluetooth SIG

Источник изображения

BLE-характеристика

Характеристика всегда принадлежит сервису, и именно в ней содержатся фактические данные в иерархии (значение). Характеристика всегда имеет два атрибута: объявление характеристики (которое предоставляет метаданные о данных) и значение характеристики.

Кроме того, за значением характеристики могут следовать дескрипторы, которые дополнительно расширяют метаданные, содержащиеся в объявлении характеристики.

Свойства описывают, как можно взаимодействовать со значением характеристики. По сути, они содержат операции и процедуры, которые можно использовать с характеристикой:

  • Broadcast (Широковещание)

  • Read (Чтение)

  • Write without response (Запись без ответа)

  • Write (Запись)

  • Notify (Уведомление)

  • Indicate (Индикация)

  • Authenticated Signed Writes (Аутентифицированная подписанная запись)

  • Extended Properties (Расширенные свойства)

UUID

Каждый сервис, характеристика и дескриптор имеют UUID (Universally Unique Identifier – универсальный уникальный идентификатор). UUID – это уникальное 128-битное (16 байт) число. Например:

55072829-bc9e-4c53-938a-74a6d4c78776

Существуют сокращенные UUID для всех типов, сервисов и профилей, указанных в SIG (Bluetooth Special Interest Group).

Но если вашему приложению нужен собственный UUID, вы можете сгенерировать его с помощью этого веб-сайта генератора UUID.

В итоге UUID используется для уникальной идентификации информации. Например, он может идентифицировать конкретный сервис, предоставляемый Bluetooth-устройством.

BLE с ESP32

ESP32 может выступать в роли BLE-сервера или BLE-клиента. Существует несколько примеров BLE для ESP32 в библиотеке ESP32 BLE для Arduino IDE. Эта библиотека устанавливается по умолчанию при установке ESP32 в Arduino IDE.

Примечание: вам необходимо установить дополнение ESP32 в Arduino IDE. Следуйте следующему руководству для подготовки Arduino IDE к работе с ESP32, если вы этого еще не сделали.

В Arduino IDE вы можете перейти в File > Examples > BLE и изучить примеры, поставляемые с библиотекой BLE.

Примеры ESP32 Bluetooth Low Energy в Arduino IDE

Примечание: чтобы увидеть примеры ESP32, необходимо выбрать плату ESP32 в Tools > Board.

Для краткого введения в ESP32 с BLE в Arduino IDE мы создадим BLE-сервер на ESP32, а затем BLE-сканер на ESP32 для поиска этого сервера. Мы будем использовать и объяснять примеры, поставляемые с библиотекой BLE.

Для выполнения этого примера вам потребуются две платы разработки ESP32. Мы будем использовать ESP32 DOIT DEVKIT V1 Board.

BLE-сервер ESP32

Чтобы создать BLE-сервер на ESP32, откройте Arduino IDE и перейдите в File > Examples > BLE и выберите пример Server. Должен загрузиться следующий код:

/*
  Complete Getting Started Guide: https://RandomNerdTutorials.com/esp32-bluetooth-low-energy-ble-arduino-ide/
  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
*/

#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");
  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);
}

Исходный код

Для создания BLE-сервера код должен выполнить следующие шаги:

  1. Создать BLE-сервер. В данном случае ESP32 выступает в роли BLE-сервера.

  2. Создать BLE-сервис.

  3. Создать BLE-характеристику для сервиса.

  4. Создать BLE-дескриптор для характеристики.

  5. Запустить сервис.

  6. Начать рекламирование (advertising), чтобы устройство могло быть найдено другими устройствами.

Как работает код

Давайте кратко рассмотрим, как работает код примера BLE-сервера.

Он начинается с импорта необходимых библиотек для работы с BLE.

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

Затем необходимо определить UUID для сервиса и характеристики.

#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"

Вы можете оставить UUID по умолчанию или перейти на uuidgenerator.net для создания случайных UUID для ваших сервисов и характеристик.

В setup() инициализируется последовательная связь на скорости 115200 бод.

Serial.begin(115200);

Затем создается BLE-устройство с именем «MyESP32». Вы можете изменить это имя на любое другое.

// Create the BLE Device
BLEDevice::init("MyESP32");

В следующей строке BLE-устройство настраивается как сервер.

BLEServer *pServer = BLEDevice::createServer();

После этого создается сервис для BLE-сервера с ранее определенным UUID.

BLEService *pService = pServer->createService(SERVICE_UUID);

Затем задается характеристика для этого сервиса. Как видите, здесь также используется ранее определенный UUID, и в качестве аргументов передаются свойства характеристики. В данном случае это: READ (чтение) и WRITE (запись).

BLECharacteristic *pCharacteristic = pService->createCharacteristic(
                                     CHARACTERISTIC_UUID,
                                     BLECharacteristic::PROPERTY_READ |
                                     BLECharacteristic::PROPERTY_WRITE
                                     );

После создания характеристики можно установить её значение с помощью метода setValue().

pCharacteristic->setValue("Hello World says Neil");

В данном случае мы устанавливаем значение в текст «Hello World says Neil». Вы можете изменить этот текст на любой другой. В будущих проектах этот текст может быть показанием датчика или состоянием лампы, например.

Наконец, можно запустить сервис и рекламирование, чтобы другие BLE-устройства могли сканировать и найти это BLE-устройство.

BLEAdvertising *pAdvertising = pServer->getAdvertising();
pAdvertising->start();

Это лишь простой пример создания BLE-сервера. В этом коде ничего не происходит в loop(), но вы можете добавить обработку подключения нового клиента (ознакомьтесь с примером Notify для получения рекомендаций).

BLE-сканер ESP32

Создать BLE-сканер на ESP32 очень просто. Возьмите другой ESP32 (пока на первом работает скетч BLE-сервера). В Arduino IDE перейдите в File > Examples > BLE и выберите пример Scan. Должен загрузиться следующий код.

/*
  Complete Getting Started Guide: https://RandomNerdTutorials.com/esp32-bluetooth-low-energy-ble-arduino-ide/
  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);
}

Исходный код

Этот код инициализирует ESP32 как BLE-устройство и сканирует ближайшие устройства. Загрузите этот код на ваш ESP32. Возможно, стоит временно отключить другой ESP32 от компьютера, чтобы убедиться, что вы загружаете код на правильную плату ESP32.

После загрузки кода обе платы ESP32 должны быть включены:

  • Один ESP32 со скетчем «BLE_server»;

  • Другой ESP32 со скетчем «BLE_scan».

Связь BLE-сканера и BLE-сервера на ESP32

Откройте монитор порта с ESP32, на котором запущен пример «BLE_scan», нажмите кнопку ENABLE на ESP32 (со скетчем «BLE_scan») для перезагрузки и подождите несколько секунд, пока выполняется сканирование.

Демонстрация связи BLE-сканера и сервера ESP32

Сканер нашел два устройства: одно из них – ESP32 (с именем «MyESP32»), а другое – умные часы.

Результаты BLE-сканирования в Arduino IDE

Тестирование BLE-сервера ESP32 с помощью смартфона

Большинство современных смартфонов должны поддерживать BLE. Автор использовал OnePlus, но большинство смартфонов также должны работать.

Вы можете просканировать ваш BLE-сервер ESP32 с помощью смартфона и просмотреть его сервисы и характеристики. Для этого мы будем использовать бесплатное приложение nRF Connect for Mobile от Nordic, которое работает на Android (Google Play Store) и iOS (App Store).

Перейдите в Google Play Store или App Store и найдите «nRF Connect for Mobile». Установите приложение и откройте его.

Приложение nRF Connect for Mobile от Nordic

Не забудьте зайти в настройки Bluetooth и включить адаптер Bluetooth на вашем смартфоне. Вы также можете сделать его видимым для других устройств, чтобы позже протестировать другие скетчи.

Включение Bluetooth на смартфоне для nRF Connect

Когда все готово на вашем смартфоне и ESP32 запущен со скетчем BLE-сервера, в приложении нажмите кнопку сканирования для поиска ближайших устройств. Вы должны найти ESP32 с именем «MyESP32».

ESP32 BLE-сервер найден в nRF Connect

Нажмите кнопку «Connect».

Как видно на рисунке ниже, ESP32 имеет сервис с UUID, который вы определили ранее. Если вы нажмете на сервис, меню развернется и покажет характеристику с UUID, который вы также определили.

Сервис и характеристика BLE-сервера ESP32 в nRF Connect

Характеристика имеет свойства READ и WRITE, а значение – то, которое вы ранее задали в скетче BLE-сервера. Итак, все работает правильно.

Заключение

В этом руководстве мы показали вам основные принципы Bluetooth Low Energy и продемонстрировали несколько примеров с ESP32. Мы рассмотрели скетч BLE-сервера и скетч BLE-сканера. Это простые примеры для начала работы с BLE.

Идея заключается в использовании BLE для отправки или получения показаний датчиков от других устройств.

Другие руководства, связанные с Bluetooth, которые могут вам понравиться:


Источник: Getting Started with ESP32 Bluetooth Low Energy (BLE) on Arduino IDE