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