Начало работы с ESP32 Bluetooth в Arduino IDE

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

Представляем Bluetooth с низким энергопотреблением

Что такое Bluetooth с низким энергопотреблением?

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

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

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

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

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

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

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

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

Как упоминалось ранее, BLE также поддерживает широковещательный режим и mesh сеть:

  • Режим широковещания: сервер передает данные всем подключенным клиентам;
  • mesh сеть: все устройства сопряжены, это соединение многие ко многим.

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

GATT

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

BLE Сервис

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

Каждый сервис содержит хотя бы одну характеристику или может также ссылаться на другие сервисы. Сервис - это просто набор информации, например показания датчиков. Существуют предопределенные службы для нескольких типов данных, определенных SIG (Специальная группа по интересам Bluetooth), таких как: уровень заряда батареи, артериальное давление, частота сердечных сокращений, шкала веса и т. д. Здесь можно проверить другие сервисы.

 

Характеристика BLE

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

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

Операции и процедуры, которые можно использовать с признаком:

  • Broadcast
  • Read
  • Write without response
  • Write
  • Notify
  • Indicate
  • Authenticated Signed Writes
  • Extended Properties

UUID

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

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

Для всех типов, служб и профилей, указанных в SIG (Специальная группа по интересам Bluetooth), существуют сокращенные UUID.

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

Таким образом, UUID используется для однозначно идентифицирующей информации. Например, он может идентифицировать конкретную услугу, предоставляемую устройством Bluetooth.

BLE с ESP32

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

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

Примечание: чтобы увидеть примеры ESP32, вы должны выбрать плату ESP32 в меню Инструменты > Плата.

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

Чтобы следовать этому примеру, вам нужны две платы разработки ESP32. Мы будем использовать плату ESP32 DOIT DEVKIT V1.

ESP32 BLE Server

Чтобы создать сервер BLE ESP32, откройте свою среду разработки Arduino и выберите «Файл»> «Примеры»> «BLE Arduino ESP32» и выберите пример сервера BLE_server. Должен открыться следующий код:

/*
    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("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);
}

Исходный код 

Для создания сервера BLE необходимо:

  1. Создать сервер BLE. В этом случае ESP32 действует как сервер BLE.
  2. Создать службу BLE.
  3. Создать BLE-характеристику для службы.
  4. Создать BLE-дескриптор для характеристики.
  5. Запустить службу.
  6. Запустить рассылку, чтобы ее могли увидеть другие устройства.

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

Давайте кратко рассмотрим, как работает пример кода сервера 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);

Затем устанавливается характеристика для этой услуги. 

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(), но вы можете добавить действие, которое происходит, когда подключается новый клиент.

ESP32 BLE Scanner

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

/*
   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».

Перейдите к последовательному монитору с ESP32, на котором запущен пример «BLE_scan»,

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

Сканер обнаружил два устройства: одно - ESP32 (оно называется MyESP32), а другое - MiBand2.

Тестирование сервера ESP32 BLE на смартфоне

Большинство современных смартфонов имеют BLE. 

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

Перейдите в Google Play Store или App Store и выполните поиск «nRF Connect для мобильных устройств». Установите приложение и откройте его.

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

В приложении нажмите кнопку сканирования, чтобы найти ближайшие устройства. Вы должны найти ESP32 с именем «MyESP32».

Нажмите кнопку «Подключиться».

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