Neste tutorial, vamos aprender a ativar e gerir o Bluetooth Low Energy (BLE) num ESP32 utilizando a linguagem de programação Arduino.
O Bluetooth Low Energy é uma versão de baixo consumo de energia do Bluetooth que permite o envio de pequenos pacotes de dados a intervalos regulares.
Equipamento
- Um módulo ESP32 (Bluetooth+Wifi integrados)
- Um computador com Python instalado ou um smartphone
- Cabo USB para ligação ao computador ESP32
Configuração do ambiente e do IDE
Para programar o seu ESP32 com o IDE Arduino, pode seguir este tutorial anterior.
Communication Série via BLE
A comunicação BLE deve ser configurada com um determinado número de endereços (UIID), que são como registos de memória nos quais podemos ler e escrever.
//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);
}
Nota: é possível obter o endereço MAC do ESP32 utilizando a função BLEDevice::getAddress().toString().c_str().
Emparelhamento
Uma vez configurado o módulo, pode emparelhar o ESP32 com o sistema da sua escolha, como qualquer outro dispositivo Bluetooth. Seleccione o nome na lista dos dispositivos detectados (nome ESP32BLE)

Teste da comunicação BLE utilizando o terminal BLE
Vamos testar a comunicação BLE utilizando a aplicação Terminal BLE.




A mensagem é trocada entre o telemóvel e o ESP32 através de Bluetooth LE
Comunicação bidirecional entre o dispositivo e o ESP32BLE
Este é o código utilizado para modificar o valor da caraterística através do monitor serial. O dispositivo conectado e o monitor serial modificam o valor da caraterí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
}
Na prática, será certamente preferível utilizar um serviço para a escrita e outro para a leitura.
Comunicação entre o ESP32 e o Python via BLE
Pode gerir a comunicação Bluetooth Low Energy a partir do seu PC.
Para isso, instale o pacote Bleak
python -m pip install bleak
Detetar 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())
Saída
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
Ligação e comunicação com o ESP32
Eis um script Python para ligar automaticamente o dispositivo ESP32 BLE a partir de um PC. Para comunicar com o dispositivo BLE, é importante conhecer o uiid dos diferentes serviços. Definimos os UUIDs como os definidos no código do 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())

Aplicação
- Criar um sensor IoT ligado que envia dados através de BLE
- Criar um terminal BLE com o React Native