El ESP32 no solo trae Wi-Fi, también incorpora Bluetooth clásico y Bluetooth Low Energy (BLE). Este artículo es una introducción rápida a BLE con el ESP32. Primero exploraremos qué es BLE y para qué se puede usar, y después veremos algunos ejemplos con el ESP32 usando Arduino IDE. Para empezar de forma sencilla, crearemos un servidor BLE con el ESP32 y un escáner BLE con el ESP32 que encuentre ese servidor.
¿Qué es Bluetooth Low Energy (BLE)?
Bluetooth Low Energy, o BLE para abreviar, es una variante de bajo consumo del Bluetooth clásico. La aplicación principal de BLE es la transmisión de corta distancia de pequeñas cantidades de datos (ancho de banda bajo). A diferencia del Bluetooth clásico, que está siempre encendido, BLE permanece en modo sleep constantemente excepto cuando se inicia una conexión.
Esto hace que consuma muy poca energía. BLE consume aproximadamente 100 veces menos energía que el Bluetooth clásico (dependiendo del caso de uso). Esa diferencia abismal es la que ha convertido a BLE en el estándar de facto para dispositivos portátiles y wearables.
Además, BLE no solo soporta comunicación punto a punto, sino también modo broadcast y red mesh.
Debido a sus propiedades, BLE es adecuado para aplicaciones que necesitan intercambiar pequeñas cantidades de datos periódicamente, funcionando con una pila de botón. Por ejemplo, BLE es muy útil en los sectores de salud, fitness, seguimiento, beacons, seguridad y domótica.
Servidor y cliente BLE: los dos roles
Con Bluetooth Low Energy, existen dos tipos de dispositivos: el servidor y el cliente. El ESP32 puede actuar tanto como cliente como servidor.
El servidor anuncia su existencia, para que pueda ser encontrado por otros dispositivos, y contiene los datos que el cliente puede leer. El cliente escanea los dispositivos cercanos, y cuando encuentra el servidor que busca, establece una conexión y escucha los datos entrantes. Esto se llama comunicación punto a punto.
Como mencionamos antes, BLE también soporta modo broadcast y red mesh:
Modo broadcast: el servidor transmite datos a muchos clientes que están conectados. Red mesh: todos los dispositivos están conectados entre sí, es una conexión de muchos a muchos.
Aunque las configuraciones de broadcast y mesh son posibles de implementar, fueron desarrolladas muy recientemente, por lo que no hay muchos ejemplos implementados para el ESP32 en este momento.
GATT: la estructura de datos de BLE
GATT significa Generic Attributes (Atributos Genéricos) y define una estructura de datos jerárquica que se expone a los dispositivos BLE conectados. Esto significa que GATT define la forma en que dos dispositivos BLE envían y reciben mensajes estándar. Entender esta jerarquía es importante, porque te hará más fácil entender cómo usar BLE y escribir tus aplicaciones.
Servicio BLE
El nivel superior de la jerarquía es un perfil (profile), que se compone de uno o más servicios. Normalmente, un dispositivo BLE contiene más de un servicio.
Cada servicio contiene al menos una característica, o también puede referenciar otros servicios. Un servicio es simplemente una colección de información, como lecturas de sensores, por ejemplo.
Existen servicios predefinidos para varios tipos de datos definidos por el SIG (Bluetooth Special Interest Group), como: Battery Level, Blood Pressure, Heart Rate, Weight Scale, etc.
Característica BLE
La característica siempre es propiedad de un servicio, y es donde los datos reales están contenidos en la jerarquía (el valor). La característica siempre tiene dos atributos: la declaración de característica (que proporciona metadatos sobre los datos) y el valor de la característica.
Además, el valor de la característica puede ir seguido de descriptores, que amplían aún más los metadatos contenidos en la declaración de característica.
Las propiedades describen cómo se puede interactuar con el valor de la característica. Básicamente, contienen las operaciones y procedimientos que se pueden usar con la característica: Broadcast, Read, Write without response, Write, Notify, Indicate, Authenticated Signed Writes y Extended Properties.
UUID: el identificador único
Cada servicio, característica y descriptor tiene un UUID (Universally Unique Identifier). Un UUID es un número único de 128 bits (16 bytes). Por ejemplo:
55072829-bc9e-4c53-938a-74a6d4c78776
Existen UUIDs abreviados para todos los tipos, servicios y perfiles especificados en el SIG (Bluetooth Special Interest Group). Pero si tu aplicación necesita su propio UUID, puedes generarlo usando un generador de UUID online.
En resumen, el UUID se usa para identificar información de forma única. Por ejemplo, puede identificar un servicio particular proporcionado por un dispositivo Bluetooth.
BLE con el ESP32
El ESP32 puede actuar como servidor BLE o como cliente BLE. Hay varios ejemplos BLE para el ESP32 en la librería ESP32 BLE para Arduino IDE. Esta librería viene instalada por defecto cuando instalas el ESP32 en Arduino IDE.
Nota: Necesitas tener el complemento ESP32 instalado en Arduino IDE para que los ejemplos aparezcan en el menú.
En tu Arduino IDE, puedes ir a Archivo > Ejemplos > BLE y explorar los ejemplos que vienen con la librería BLE. Para ver los ejemplos del ESP32, debes tener la placa ESP32 seleccionada en Herramientas > Placa.
Para una breve introducción al ESP32 con BLE en Arduino IDE, crearemos un servidor BLE ESP32 y luego un escáner BLE ESP32 para encontrar ese servidor. Usaremos y explicaremos los ejemplos que vienen con la librería BLE.
Para seguir este ejemplo, necesitas dos placas de desarrollo ESP32. En nuestro caso, usaremos la ESP32 DOIT DEVKIT V1.
Servidor BLE con el ESP32
Para crear un servidor BLE con el ESP32, abre tu Arduino IDE y ve a Archivo > Ejemplos > BLE y selecciona el ejemplo Server. Debería cargarse el siguiente código:
/*
Guía completa de introducción: https://RandomNerdTutorials.com/esp32-bluetooth-low-energy-ble-arduino-ide/
Basado en el ejemplo de Neil Kolban para IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleServer.cpp
Portado a Arduino ESP32 por Evandro Copercini
*/
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
// Consulta lo siguiente para generar 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(); // esto aún funciona por compatibilidad
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
pAdvertising->setScanResponse(true);
pAdvertising->setMinPreferred(0x06); // funciones que ayudan con el problema de conexión con iPhone
pAdvertising->setMinPreferred(0x12);
BLEDevice::startAdvertising();
Serial.println("Characteristic defined! Now you can read it in your phone!");
}
void loop() {
// Pon aquí tu código principal, para que se ejecute repetidamente:
delay(2000);
}
Para crear un servidor BLE, el código debe seguir estos pasos:
Crear un servidor BLE. En este caso, el ESP32 actúa como servidor BLE. Crear un servicio BLE. Crear una característica BLE en el servicio. Crear un descriptor BLE en la característica. Iniciar el servicio. Iniciar el advertising, para que pueda ser encontrado por otros dispositivos.
Cómo funciona el código del servidor paso a paso
El código empieza importando las librerías necesarias para las capacidades BLE:
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
Después, necesitas definir un UUID para el servicio y la característica:
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
Puedes dejar los UUIDs por defecto, o puedes ir a uuidgenerator.net para crear UUIDs aleatorios para tus servicios y características.
En el setup(), se inicia la comunicación serie a 115200 baudios. Después, se crea un dispositivo BLE llamado “MyESP32”. Puedes cambiar este nombre por el que quieras:
BLEDevice::init("MyESP32");
En la siguiente línea, se establece el dispositivo BLE como servidor:
BLEServer *pServer = BLEDevice::createServer();
Después, se crea un servicio para el servidor BLE con el UUID definido antes:
BLEService *pService = pServer->createService(SERVICE_UUID);
Luego, se establece la característica para ese servicio. Como puedes ver, también se usa el UUID definido antes, y necesitas pasar como argumentos las propiedades de la característica. En este caso, es READ y WRITE:
BLECharacteristic *pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE
);
Después de crear la característica, puedes establecer su valor con el método setValue():
pCharacteristic->setValue("Hello World says Neil");
En este caso, estamos estableciendo el valor al texto “Hello World says Neil”. Puedes cambiar este texto por lo que quieras. En futuros proyectos, este texto puede ser una lectura de sensor o el estado de una lámpara, por ejemplo.
Finalmente, puedes iniciar el servicio y el advertising, para que otros dispositivos BLE puedan escanear y encontrar este dispositivo BLE:
BLEAdvertising *pAdvertising = pServer->getAdvertising();
pAdvertising->start();
Este es solo un ejemplo simple de cómo crear un servidor BLE. En este código no se hace nada en el loop(), pero puedes añadir qué ocurre cuando un nuevo cliente se conecta.
Escáner BLE con el ESP32
Crear un escáner BLE con el ESP32 es sencillo. Coge otro ESP32 (mientras el otro está ejecutando el sketch del servidor BLE). En tu Arduino IDE, ve a Archivo > Ejemplos > BLE y selecciona el ejemplo Scan. Debería cargarse el siguiente código:
/*
Guía completa de introducción: https://RandomNerdTutorials.com/esp32-bluetooth-low-energy-ble-arduino-ide/
Basado en el ejemplo de Neil Kolban para IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleScan.cpp
Portado a Arduino ESP32 por Evandro Copercini
*/
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
int scanTime = 5; // en segundos
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(); // crea un nuevo escaneo
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setActiveScan(true); // el escaneo activo usa más energía, pero obtiene resultados más rápido
pBLEScan->setInterval(100);
pBLEScan->setWindow(99); // valor menor o igual a setInterval
}
void loop() {
// Pon aquí tu código principal, para que se ejecute repetidamente:
BLEScanResults *foundDevices = pBLEScan->start(scanTime, false);
Serial.print("Devices found: ");
Serial.println(foundDevices->getCount());
Serial.println("Scan done!");
pBLEScan->clearResults(); // borra los resultados del buffer de BLEScan para liberar memoria
delay(2000);
}
Este código inicializa el ESP32 como dispositivo BLE y escanea dispositivos cercanos. Sube este código a tu ESP32. Puede que quieras desconectar temporalmente el otro ESP32 de tu ordenador, para asegurarte de que estás subiendo el código a la placa ESP32 correcta.
Una vez subido el código, deberías tener las dos placas ESP32 encendidas: una con el sketch “BLE_server” y otra con el sketch “BLE_scan”.
Ve al Monitor Serie del ESP32 que ejecuta el ejemplo “BLE_scan”, pulsa el botón ENABLE del ESP32 (con el sketch “BLE_scan”) para reiniciar y espera unos segundos mientras escanea.
El escáner encontrará varios dispositivos: uno de ellos será tu ESP32 (con el nombre “MyESP32”), y probablemente otros dispositivos cercanos como un smartwatch o auriculares Bluetooth.
Probar el servidor BLE del ESP32 con tu smartphone
La mayoría de los smartphones modernos tienen capacidades BLE. Puedes escanear tu servidor BLE con el ESP32 desde tu smartphone y ver sus servicios y características.
Para eso, usaremos una app gratuita llamada nRF Connect for Mobile de Nordic, que funciona en Android (Google Play Store) y iOS (App Store).
Ve a Google Play Store o App Store y busca “nRF Connect for Mobile”. Instala la app y ábrela. No olvides ir a los ajustes de Bluetooth y habilitar el adaptador Bluetooth en tu smartphone.
Una vez que todo esté listo en tu smartphone y el ESP32 esté ejecutando el sketch del servidor BLE, en la app, pulsa el botón de escanear para buscar dispositivos cercanos. Deberías encontrar un ESP32 con el nombre “MyESP32”. Pulsa el botón “Connect”.
Como verás, el ESP32 tiene un servicio con el UUID que definiste antes. Si pulsas el servicio, se expande el menú y muestra la característica con el UUID que también definiste.
La característica tiene las propiedades READ y WRITE, y el valor es el que definiste previamente en el sketch del servidor BLE. Así que todo está funcionando correctamente.
Conclusión: lo que has aprendido
En este tutorial te hemos mostrado los principios básicos de Bluetooth Low Energy y algunos ejemplos con el ESP32. Hemos explorado el sketch del servidor BLE y el sketch del escáner BLE. Estos son ejemplos simples para empezar con BLE.
La idea es usar BLE para enviar o recibir lecturas de sensores desde otros dispositivos. Combinando BLE con el bajo consumo del ESP32, puedes construir dispositivos portátiles o wearables que duren semanas o meses con una pila de botón, comunicándose con un smartphone o con otros ESP32.
BLE es especialmente útil cuando quieres comunicar el ESP32 con un smartphone sin pasar por Wi-Fi. Por ejemplo, para configurar credenciales Wi-Fi de forma inalámbrica (Wi-Fi provisioning), para enviar notificaciones, o para controlar dispositivos desde una app móvil sin necesidad de router.
Cuando domines los conceptos de servidor BLE, cliente BLE, servicios, características y UUIDs, podrás diseñar tus propios perfiles BLE personalizados y construir sistemas de comunicación inalámbrica de bajo consumo completamente adaptados a tus necesidades.
Descubre más desde CIBERED
Suscríbete y recibe las últimas entradas en tu correo electrónico.
