hack4electronics.com

Comprehensive Guide to Unlock the Power of ESP32 BLE

Bluetooth Low Energy (BLE) is a powerful and efficient technology for wireless communication, especially suitable for IoT devices. The ESP32 microcontroller, equipped with BLE capabilities, offers extensive features for creating BLE applications. This guide provides a comprehensive overview, example programs, and practical applications for using ESP32 BLE .

Understanding BLE

BLE is a wireless communication technology designed for short-range communication with low energy consumption. It is ideal for battery-powered devices, including fitness trackers, smart home devices, and various IoT applications.

ESP32 BLE Overview

The ESP32 microcontroller supports BLE and includes a variety of libraries and APIs to facilitate BLE development. It can operate as both a BLE server and client, making it versatile for numerous applications.

ESP32 BLE Scan Mode

BLE Scan mode is used to detect nearby BLE devices. The ESP32 can scan for advertisements from other BLE devices and retrieve information about them. Below is an example program that scans for BLE devices:

Example: BLE Scan

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>

int scanTime = 5;  // In seconds
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();  // Create new scan
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
  pBLEScan->setActiveScan(true);  // Active scan uses more power, but gets results faster
  pBLEScan->setInterval(100);
  pBLEScan->setWindow(99);  // Less or equal setInterval value
}

void loop() {
  BLEScanResults foundDevices = pBLEScan->start(scanTime, false);
  Serial.print("Devices found: ");
  Serial.println(foundDevices.getCount());
  Serial.println("Scan done!");
  pBLEScan->clearResults();  // Delete results from BLEScan buffer to release memory
  delay(2000);
}

ESP32 BLE UART Mode

ESP32 BLE UART mode allows for wireless communication between devices. The ESP32 can create a BLE server that sends and receives data using UART services. The following example demonstrates how to set up a BLE UART server:

Example: UART

#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>

BLEServer* pServer = NULL;
BLECharacteristic* pTxCharacteristic;
bool deviceConnected = false;
bool oldDeviceConnected = false;
uint8_t txValue = 0;

#define SERVICE_UUID           "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"

class MyServerCallbacks : public BLEServerCallbacks {
  void onConnect(BLEServer* pServer) {
    deviceConnected = true;
  };

  void onDisconnect(BLEServer* pServer) {
    deviceConnected = false;
  }
};

class MyCallbacks : public BLECharacteristicCallbacks {
  void onWrite(BLECharacteristic* pCharacteristic) {
    String rxValue = pCharacteristic->getValue();
    if (rxValue.length() > 0) {
      Serial.println("*********");
      Serial.print("Received Value: ");
      for (int i = 0; i < rxValue.length(); i++)
        Serial.print(rxValue[i]);
      Serial.println();
      Serial.println("*********");
    }
  }
};

void setup() {
  Serial.begin(115200);
  BLEDevice::init("UART Service");
  pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());
  BLEService* pService = pServer->createService(SERVICE_UUID);
  pTxCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_TX, BLECharacteristic::PROPERTY_NOTIFY);
  pTxCharacteristic->addDescriptor(new BLE2902());
  BLECharacteristic* pRxCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_RX, BLECharacteristic::PROPERTY_WRITE);
  pRxCharacteristic->setCallbacks(new MyCallbacks());
  pService->start();
  pServer->getAdvertising()->start();
  Serial.println("Waiting for a client connection to notify...");
}

void loop() {
  if (deviceConnected) {
    pTxCharacteristic->setValue(&txValue, 1);
    pTxCharacteristic->notify();
    txValue++;
    delay(10);
  }

  if (!deviceConnected && oldDeviceConnected) {
    delay(500);
    pServer->startAdvertising();
    Serial.println("Start advertising");
    oldDeviceConnected = deviceConnected;
  }

  if (deviceConnected && !oldDeviceConnected) {
    oldDeviceConnected = deviceConnected;
  }
}

ESP32 BLE Server and Client Roles

The ESP32 can function as both a BLE server and client. As a server, it can host services and characteristics that clients can interact with. As a client, it can connect to other BLE servers to access their services and characteristics.

Example: ESP32 BLE Client

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>

static BLEUUID serviceUUID("6E400001-B5A3-F393-E0A9-E50E24DCCA9E");
static BLEUUID charUUID("6E400003-B5A3-F393-E0A9-E50E24DCCA9E");
static boolean doConnect = false;
static boolean connected = false;
static boolean doScan = false;
static BLERemoteCharacteristic* pRemoteCharacteristic;
static BLEAdvertisedDevice* myDevice;

class MyClientCallback : public BLEClientCallbacks {
  void onConnect(BLEClient* pclient) {
  }

  void onDisconnect(BLEClient* pclient) {
    connected = false;
    Serial.println("Disconnected");
  }
};

bool connectToServer() {
  Serial.print("Forming a connection to ");
  Serial.println(myDevice->getAddress().toString().c_str());
  BLEClient* pClient = BLEDevice::createClient();
  pClient->setClientCallbacks(new MyClientCallback());
  pClient->connect(myDevice);
  BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
  if (pRemoteService == nullptr) {
    Serial.print("Failed to find our service UUID: ");
    Serial.println(serviceUUID.toString().c_str());
    pClient->disconnect();
    return false;
  }
  pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID);
  if (pRemoteCharacteristic == nullptr) {
    Serial.print("Failed to find our characteristic UUID: ");
    Serial.println(charUUID.toString().c_str());
    pClient->disconnect();
    return false;
  }
  connected = true;
  return true;
}

class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks {
  void onResult(BLEAdvertisedDevice advertisedDevice) {
    Serial.print("BLE Advertised Device found: ");
    Serial.println(advertisedDevice.toString().c_str());
    if (advertisedDevice.haveServiceUUID() && advertisedDevice.getServiceUUID().equals(serviceUUID)) {
      advertisedDevice.getScan()->stop();
      myDevice = new BLEAdvertisedDevice(advertisedDevice);
      doConnect = true;
      doScan = true;
    }
  }
};

void setup() {
  Serial.begin(115200);
  BLEDevice::init("");
  BLEScan* pBLEScan = BLEDevice::getScan();
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
  pBLEScan->setActiveScan(true);
  pBLEScan->start(30);
}

void loop() {
  if (doConnect) {
    if (connectToServer()) {
      Serial.println("We are now connected to the BLE Server.");
    } else {
      Serial.println("We have failed to connect to the server; there is nothing more we will do.");
    }
    doConnect = false;
  }
  if (connected) {
    String newValue = "Time since boot: " + String(millis() / 1000);
    pRemoteCharacteristic->writeValue(newValue.c_str(), newValue.length());
  } else if (doScan) {
    BLEDevice::getScan()->start(0);
  }
  delay(1000);
}

BLE Security and Encryption

BLE communication security is critical for protecting data and ensuring privacy. ESP32 supports various security features, including authentication, authorization, and encryption. Implementing these features helps secure the BLE communication channels.

Practical Applications and Examples of ESP32 BLE

By utilizing the BLE capabilities of the ESP32, developers can create various applications, including wireless sensors, remote controls, and fitness trackers. The BLE Scan and UART modes provide foundational functionality for these applications, enabling efficient and reliable wireless communication.

BLE Health Monitoring System

BLE can be used to create a health monitoring system that collects data from various sensors (e.g., heart rate, blood pressure) and transmits it to a smartphone or a central server for analysis. This application benefits from BLE’s low power consumption, making it suitable for wearable devices.

ESP32 BLE Smart Home Automation

ESP32 BLE is ideal for smart home automation systems. It can control lights, thermostats, door locks, and other appliances. The ESP32 can act as a central controller, communicating with various BLE-enabled devices to automate and monitor the home environment.

ESP32 BLE Location Tracking

ESP32 BLE beacons can be used for indoor location tracking. The ESP32 can detect BLE signals from beacons placed around a facility to determine its location. This application is useful in retail, healthcare, and logistics for asset tracking and navigation.

Detailed Example: ESP32 BLE Temperature and Humidity Monitor

This example demonstrates how to use the ESP32 to create a BLE temperature and humidity monitor. The ESP32 reads data from a DHT11 sensor and transmits it over BLE to a smartphone.

Example Code: ESP32 BLE Temperature and Humidity Monitor

#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#include <DHT.h>

#define DHTPIN 4         // Digital pin connected to the DHT sensor
#define DHTTYPE DHT11    // DHT 11
DHT dht(DHTPIN, DHTTYPE);

BLEServer* pServer = NULL;
BLECharacteristic* pTxCharacteristic;
bool deviceConnected = false;
uint8_t txValue = 0;

#define SERVICE_UUID           "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"

class MyServerCallbacks : public BLEServerCallbacks {
  void onConnect(BLEServer* pServer) {
    deviceConnected = true;
  }

  void onDisconnect(BLEServer* pServer) {
    deviceConnected = false;
  }
};

void setup() {
  Serial.begin(115200);
  dht.begin();
  
  BLEDevice::init("ESP32_DHT11");
  pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());
  
  BLEService* pService = pServer->createService(SERVICE_UUID);
  pTxCharacteristic = pService->createCharacteristic(
                        CHARACTERISTIC_UUID_TX,
                        BLECharacteristic::PROPERTY_NOTIFY
                      );
  pTxCharacteristic->addDescriptor(new BLE2902());
  pService->start();
  pServer->getAdvertising()->start();
  Serial.println("Waiting for a client connection...");
}

void loop() {
  if (deviceConnected) {
    float temperature = dht.readTemperature();
    float humidity = dht.readHumidity();
    
    if (isnan(temperature) || isnan(humidity)) {
      Serial.println("Failed to read from DHT sensor!");
      return;
    }
    
    char tempHumString[8];
    dtostrf(temperature, 1, 2, tempHumString);
    strcat(tempHumString, "C ");
    char humString[4];
    dtostrf(humidity, 1, 2, humString);
    strcat(tempHumString, humString);
    strcat(tempHumString, "%");
    
    pTxCharacteristic->setValue(tempHumString);
    pTxCharacteristic->notify();
    Serial.print("Temperature: ");
    Serial.print(temperature);
    Serial.print(" C, Humidity: ");
    Serial.print(humidity);
    Serial.println(" %");
  }
  delay(2000);
}

Explanation:

  1. Setup:
    • The DHT11 sensor is initialized and set up to read temperature and humidity.
    • BLE is initialized, creating a server and setting up a service and characteristic for temperature and humidity data.
  2. Main Loop:
    • If a BLE client is connected, the ESP32 reads temperature and humidity from the DHT11 sensor.
    • The data is formatted into a string and sent to the connected BLE client.
  3. BLE Callbacks:
    • The MyServerCallbacks class manages the connection status, ensuring data is only sent when a client is connected.

The ESP32’s BLE capabilities open up numerous possibilities for developing innovative IoT applications. Whether it’s health monitoring, smart home automation, or location tracking, the ESP32 provides a flexible and powerful platform for wireless communication. By leveraging BLE, developers can create efficient, low-power devices that enhance connectivity and functionality in various domains

Leave a Reply

Your email address will not be published. Required fields are marked *