En este tutorial, vamos a aprender a activar y gestionar Bluetooth Low Energy (BLE) en un ESP32 utilizando el lenguaje de programación Arduino.
Bluetooth Low Energy es una versión de baja energía de Bluetooth que permite enviar pequeños paquetes de datos a intervalos regulares.
Equipamiento
- Un módulo ESP32 (Bluetooth+Wifi a bordo)
- Un ordenador con Python instalado o un smartphone
- Cable USB para conexión ESP32-ordenador
Configuración del entorno y del IDE
Para programar tu ESP32 con el IDE de Arduino, puedes seguir este tutorial anterior.
Communication Série via BLE
La comunicación BLE debe configurarse con un cierto número de direcciones (UIIDs) que son como registros de memoria en los que podemos leer y escribir.
//https://github.com/espressif/arduino-esp32/tree/master/libraries/BLE
#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"
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string value = pCharacteristic->getValue();
if (value.length() > 0) {
Serial.println("*********");
Serial.print("New value: ");
for (int i = 0; i < value.length(); i++)
Serial.print(value[i]);
Serial.println();
Serial.println("*********");
}
}
};
void setup() {
Serial.begin(115200);
Serial.println("1- Download and install an BLE Terminal FREE");
Serial.println("2- Scan for BLE devices in the app");
Serial.println("3- Connect to ESP32BLE");
Serial.println("4- Go to CUSTOM CHARACTERISTIC in CUSTOM SERVICE and write something");
BLEDevice::init("ESP32BLE");
BLEServer *pServer = BLEDevice::createServer();
BLEService *pService = pServer->createService(SERVICE_UUID);
BLECharacteristic *pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE
);
pCharacteristic->setCallbacks(new MyCallbacks());
pCharacteristic->setValue("Hello World");
pService->start();
BLEAdvertising *pAdvertising = pServer->getAdvertising();
pAdvertising->start();
Serial.print("Server address:");
Serial.println(BLEDevice::getAddress().toString().c_str());
}
void loop() {
// put your main code here, to run repeatedly:
delay(2000);
}
N.B.: es posible recuperar la dirección MAC del ESP32 utilizando la función BLEDevice::getAddress().toString().c_str().
Emparejamiento
Una vez configurado el módulo como desee, puede emparejar el ESP32 con el sistema de su elección como cualquier otro dispositivo Bluetooth. Seleccione el nombre de la lista de dispositivos detectados (nombre ESP32BLE)

Prueba de la comunicación BLE con el terminal BLE
Vamos a probar la comunicación BLE utilizando la aplicación BLE Terminal.




El mensaje se intercambia entre el teléfono y el ESP32 a través de Bluetooth LE
Comunicación bidireccional entre el dispositivo y el ESP32BLE
Este es el código utilizado para modificar el valor de la característica utilizando el monitor serie. El dispositivo conectado y el monitor serie modifican el valor de la característica.
#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"
BLECharacteristic *pCharacteristic = NULL;
std::string msg;
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string value = pCharacteristic->getValue();
if (value.length() > 0) {
Serial.println("*********");
Serial.print("New value: ");
for (int i = 0; i < value.length(); i++)
Serial.print(value[i]);
Serial.println();
Serial.println("*********");
}
}
};
void setup() {
Serial.begin(115200);
Serial.println("1- Download and install an BLE Terminal Free");
Serial.println("2- Scan for BLE devices in the app");
Serial.println("3- Connect to ESP32BLE");
Serial.println("4- Go to CUSTOM CHARACTERISTIC in CUSTOM SERVICE and write something");
BLEDevice::init("ESP32BLE");
BLEServer *pServer = BLEDevice::createServer();
BLEService *pService = pServer->createService(SERVICE_UUID);
pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE
);
pCharacteristic->setCallbacks(new MyCallbacks());
pCharacteristic->setValue("Hello World");
pService->start();
BLEAdvertising *pAdvertising = pServer->getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
pAdvertising->setScanResponse(true);
pAdvertising->setMinPreferred(0x06); // functions that help with iPhone connections issue
pAdvertising->setMinPreferred(0x12);
pAdvertising->start();
Serial.print("Server address:");
Serial.println(BLEDevice::getAddress().toString().c_str());
}
void loop() {
readSerialPort();
//Send data to slave
if(msg!=""){
pCharacteristic->setValue(msg);
msg="";
}
delay(2000);
}
void readSerialPort(){
while (Serial.available()) {
delay(10);
if (Serial.available() >0) {
char c = Serial.read(); //gets one byte from serial buffer
msg += c; //add to String
}
}
Serial.flush(); //clean buffer
}
En la práctica, será preferible utilizar un servicio para escribir y otro para leer.
Comunicación entre ESP32 y Python a través de BLE
Puedes gestionar la comunicación Bluetooth Low Energy desde tu PC.
Para ello, instale el paquete Bleak
python -m pip install bleak
Detectar dispositivos bluetooth
import asyncio
from bleak import BleakScanner
async def main():
target_name = "ESP32BLE"
target_address = None
devices = await BleakScanner.discover()
for d in devices:
print(d)
if target_name == d.name:
target_address = d.address
print("found target {} bluetooth device with address {} ".format(target_name,target_address))
break
asyncio.run(main())
Salida
C1:2E:C6:8E:47:E8: None 3C:61:05:31:5F:12: ESP32BLE found target ESP32BLE bluetooth device with address 3C:61:05:31:5F:12
Conexión y comunicación con el ESP32
Aquí tienes un script en Python para conectarte automáticamente al dispositivo ESP32 BLE desde un PC. Para comunicarse con el dispositivo BLE, es importante conocer el UUID de los diferentes servicios. Definimos los UUID como los definidos en el código del ESP32
import asyncio
from bleak import BleakScanner
from bleak import BleakClient
async def main():
target_name = "ESP32BLE"
target_address = None
SERVICE_UUID= "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
CHARACTERISTIC_UUID= "beb5483e-36e1-4688-b7f5-ea07361b26a8"
devices = await BleakScanner.discover()
for d in devices:
print(d)
if target_name == d.name:
target_address = d.address
print("found target {} bluetooth device with address {} ".format(target_name,target_address))
break
if target_address is not None:
async with BleakClient(target_address) as client:
print(f"Connected: {client.is_connected}")
while 1:
text = input()
if text == "quit":
break
await client.write_gatt_char(CHARACTERISTIC_UUID, bytes(text, 'UTF-8'), response=True)
try:
data = await client.read_gatt_char(CHARACTERISTIC_UUID)
data = data.decode('utf-8') #convert byte to str
print("data: {}".format(data))
except Exception:
pass
else:
print("could not find target bluetooth device nearby")
asyncio.run(main())

Aplicación
- Creación de un sensor IoT conectado que envía datos a través de BLE
- Creación de un terminal BLE con React Native