El ESP32 cuenta con Bluetooth integrado, compatible tanto con Bluetooth Classic como con Bluetooth Low Energy (BLE).
BLE es una variante del estándar Bluetooth (introducida en la versión 4.0 de Bluetooth) diseñada para aplicaciones que requieren un bajo consumo de energía.
- Bluetooth Classic, que está optimizado para la transmisión continua de datos (como audio)
- BLE está diseñado para enviar pequeños paquetes de datos de manera intermitente.
Esto reduce drásticamente el consumo de energía, lo que la hace ideal para dispositivos IoT (Internet de las Cosas) y wearables. Vamos a ver cómo podemos usarla.
Diferencias entre Bluetooth Classic y BLE
Bluetooth Classic y Bluetooth Low Energy (BLE) son dos variantes de la tecnología Bluetooth, pero tienen diferencias clave:
- Consumo de energía: BLE consume significativamente menos energía que Bluetooth Classic, lo que permite que los dispositivos funcionen durante meses o incluso años con una pequeña batería.
- Tasa de transferencia: BLE tiene una tasa de transferencia de datos más baja (hasta 1 Mbps) en comparación con Bluetooth Classic (hasta 3 Mbps).
- Latencia: Bluetooth Classic tiene una latencia más baja que BLE (importante para aplicaciones en tiempo real, como auriculares inalámbricos).
- Conexión: BLE está diseñado para conexiones rápidas y de corta duración, mientras que Bluetooth Classic es más adecuado para conexiones continuas y de larga duración.
Básicamente BLE es “peor” en todo, salvo el consumo de energía (lógico).
Arquitectura de BLE
BLE se basa en una arquitectura cliente-servidor, donde:
- Dispositivo periférico (Peripheral): Actúa como servidor y proporciona datos. Por ejemplo, un sensor de temperatura que envía lecturas.
- Dispositivo central (Central): Actúa como cliente y solicita datos. Por ejemplo, un teléfono inteligente que recibe lecturas del sensor.
Componentes clave de BLE
- GATT (Generic Attribute Profile): Define cómo se organizan y transmiten los datos entre dispositivos BLE. Los datos se organizan en servicios y características.
- Servicio: Un conjunto de características relacionadas. Por ejemplo, un servicio de salud podría incluir características como la frecuencia cardíaca y la temperatura corporal.
- Característica: Un valor específico que se puede leer o escribir. Por ejemplo, la frecuencia cardíaca actual.
- Advertising: Los dispositivos periféricos envían paquetes de anuncio para que los dispositivos centrales los detecten. Estos paquetes contienen información como el nombre del dispositivo y los servicios que ofrece.
Configuración del ESP32 para BLE
Para configurar el ESP32 como un dispositivo periférico BLE, utilizaremos la biblioteca ESP32 BLE Arduino
, que simplifica la implementación de BLE.
Configuración de BTLE
Para utilizar BTLE, debemos incluir la biblioteca BLEDevice.h
y crear una instancia de BLEServer
. Luego, agregamos servicios y características que queremos exponer a otros dispositivos.
#include <BLEDevice.h>
#include <BLEServer.h>
// Variables para identificar el servicio y la característica BTLE
#define SERVICE_UUID "00000000-0000-0000-0000-000000000000"
#define CHARACTERISTIC_UUID "00000000-0000-0000-0000-0000000b0000"
BLEServer *pServer;
BLEService *pService;
BLECharacteristic *pCharacteristic;
void configurarBTLE() {
// Crear el servidor BTLE
BLEDevice::init("ESP32_BTLE");
pServer = BLEDevice::createServer();
// Crear el servicio
pService = pServer->createService(SERVICIO_UUID);
// Agregar una característica al servicio
pCharacteristic = pService->createCharacteristic(
CARACTERISTICA_UUID, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE);
// Iniciar el servicio
pService->start();
// Iniciar la publicidad del servidor BTLE
BLEAdvertising *pAdvertising = pServer->getAdvertising();
pAdvertising->start();
}
Lectura y escritura de datos BTLE
Una vez añadidas las características, podemos leer o grabar datos. Por ejemplo,
void setup() {
Serial.begin(115200);
configurarBTLE();
}
void loop() {
// Leer datos de la característica BTLE
std::string valorRecibido = pCharacteristic->getValue();
if (valorRecibido.length() > 0) {
Serial.print("Valor recibido: ");
Serial.println(valorRecibido.c_str());
}
// Escribir datos en la característica BTLE
std::string valorEnviar = "Hola, este es un mensaje BTLE";
pCharacteristic->setValue(valorEnviar);
pCharacteristic->notify();
delay(1000);
}
Interacción desde Android / iOS
Una vez que el ESP32 está configurado como un periférico BLE, puedes conectarte a él desde un teléfono utilizando una aplicación como nRF Connect (disponible para iOS y Android).
- Abrimos la aplicación y escanea los dispositivos BLE cercanos.
- Conéctate al dispositivo llamado “ESP32_BLE_Server”.
- Explora el servicio y la característica que hemos creado.
- Lee o escribe en la característica para interactuar con el ESP32.
Ejemplos prácticos
Configuración de un servidor BLE simple
En este ejemplo, configuramos el ESP32 como servidor BLE que envía datos de temperatura simulados.
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
// Nombre del dispositivo BLE
#define DEVICE_NAME "ESP32_BLE_Server"
// UUIDs personalizados
#define SERVICE_UUID "00000000-0000-0000-0000-000000000000"
#define CHARACTERISTIC_UUID "00000000-0000-0000-0000-0000000b0000"
BLEServer *servidorBLE;
BLECharacteristic *caracteristica;
void setup() {
Serial.begin(9600);
// Inicializa el dispositivo BLE
BLEDevice::init(DEVICE_NAME);
// Crea el servidor BLE
servidorBLE = BLEDevice::createServer();
// Crea el servicio y la característica
BLEService *servicio = servidorBLE->createService(SERVICE_UUID);
caracteristica = servicio->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY);
// Asigna un valor inicial
caracteristica->setValue("Inicializando...");
// Inicia el servicio
servicio->start();
// Hace el dispositivo visible
BLEAdvertising *publicidad = BLEDevice::getAdvertising();
publicidad->start();
Serial.println("Servidor BLE iniciado");
}
void loop() {
// Simula una temperatura
float temperatura = random(20, 30) + 0.1 * random(0, 10);
String valor = "Temp: " + String(temperatura) + "°C";
// Actualiza el valor de la característica
caracteristica->setValue(valor.c_str());
caracteristica->notify(); // Notifica a los clientes conectados
Serial.println(valor);
delay(1000);
}
Cliente BLE que lee datos
En este ejemplo, configuramos un ESP32 como cliente BLE que se conecta al servidor anterior para leer datos.
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEClient.h>
#define SERVER_ADDRESS "XX:XX:XX:XX:XX:XX" // Dirección MAC del servidor BLE
#define SERVICE_UUID "00000000-0000-0000-0000-000000000000"
#define CHARACTERISTIC_UUID "00000000-0000-0000-0000-0000000b0000"
void setup() {
Serial.begin(9600);
// Inicializa el dispositivo BLE
BLEDevice::init("ESP32_BLE_Client");
// Conecta al servidor BLE
BLEClient *cliente = BLEDevice::createClient();
cliente->connect(BLEAddress(SERVER_ADDRESS));
// Accede al servicio y a la característica
BLERemoteService *servicio = cliente->getService(SERVICE_UUID);
BLERemoteCharacteristic *caracteristica = servicio->getCharacteristic(CHARACTERISTIC_UUID);
if (caracteristica->canRead()) {
String valor = caracteristica->readValue().c_str();
Serial.println("Valor recibido: " + valor);
}
}
void loop() {
// El cliente puede leer el valor en intervalos regulares
delay(2000);
}