Getting Started With ESP32 Bluetooth Low Energy (BLE) On Arduino IDE
Getting Started With ESP32 Bluetooth Low Energy (BLE) On Arduino IDE
Getting Started With ESP32 Bluetooth Low Energy (BLE) On Arduino IDE
The ESP32 comes not only with Wi-Fi but also with Bluetooth and Bluetooth Low Energy (BLE). This post is a quick
introduction to BLE with the ESP32. First, we’ll explore what’s BLE and what it can be used for, and then we’ll take a look
at some examples with the ESP32 using Arduino IDE. For a simple introduction we’ll create an ESP32 BLE server, and an
ESP32 BLE scanner to find that server.
For a quick introduction to BLE, you can watch the video below, or you can scroll down for a written explanation.
Recommended reading: learn how to use ESP32 Bluetooth Classic with Arduino IDE to exchange data between an ESP32
and an Android smartphone.
Bluetooth Low Energy, BLE for short, is a power-conserving variant of Bluetooth. BLE’s primary application is short
distance transmission of small amounts of data (low bandwidth). Unlike Bluetooth that is always on, BLE remains in
sleep mode constantly except for when a connection is initiated.
This makes it consume very low power. BLE consumes approximately 100x less power than Bluetooth (depending on the
use case).
Additionally, BLE supports not only point-to-point communication, but also broadcast mode, and mesh network.
Take a look at the table below that compares BLE and Bluetooth Classic in more detail. View Image Souce
Due to its properties, BLE is suitable for applications that need to exchange small amounts of data periodically running
on a coin cell. For example, BLE is of great use in healthcare, fitness, tracking, beacons, security, and home automation
industries.
With Bluetooth Low Energy, there are two types of devices: the server and the client. The ESP32 can act either as a client
or as a server.
The server advertises its existence, so it can be found by other devices, and contains the data that the client can read.
The client scans the nearby devices, and when it finds the server it is looking for, it establishes a connection and listens
for incoming data. This is called point-to-point communication.
As mentioned previously, BLE also supports broadcast mode and mesh network:
Broadcast mode: the server transmits data to many clients that are connected;
Mesh network: all the devices are connected, this is a many to many connection.
Even though the broadcast and mesh network setups are possible to implement, they were developed very recently, so
there aren’t many examples implemented for the ESP32 at this moment.
GATT
GATT stands for Generic Attributes and it defines an hierarchical data structure that is exposed to connected BLE
devices. This means that GATT defines the way that two BLE devices send and receive standard
messages. Understanding this hierarchy is important, because it will make it easier to understand how to use the BLE
and write your applications.
BLE Service
The top level of the hierarchy is a profile, which is composed of one or more services. Usually, a BLE device contains
more than one service.
Every service contains at least one characteristic, or can also reference other services. A service is simply a collection of
information, like sensor readings, for example.
There are predefined services for several types of data defined by the SIG (Bluetooth Special Interest Group) like: Battery
Level, Blood Pressure, Heart Rate, Weight Scale, etc. You can check here other defined services.
BLE Characteristic
The characteristic is always owned by a service, and it is where the actual data is contained in the hierarchy (value). The
characteristic always has two attributes: characteristic declaration (that provides metadata about the data) and the
characteristic value.
Additionally, the characteristic value can be followed by descriptors, which further expand on the metadata contained in
the characteristic declaration.
The properties describe how the characteristic value can be interacted with. Basically, it contains the operations and
procedures that can be used with the characteristic:
Broadcast
Read
Write without response
Write
Notify
Indicate
Authenticated Signed Writes
Extended Properties
UUID
Each service, characteristic and descriptor have an UUID (Universally Unique Identifier). An UUID is a unique 128-bit (16
bytes) number. For example:
55072829-bc9e-4c53-938a-74a6d4c78776
There are shortened UUIDs for all types, services, and profiles specified in the SIG (Bluetooth Special Interest Group).
But if your application needs its own UUID, you can generate it using this UUID generator website.
In summary, the UUID is used for uniquely identifying information. For example, it can identify a particular service
provided by a Bluetooth device.
The ESP32 can act as a BLE server or as a BLE client. There are several BLE examples for the ESP32 in the ESP32 BLE
library for Arduino IDE. This library comes installed by default when you install the ESP32 on the Arduino IDE.
Note: You need to have the ESP32 add-on installed on the Arduino IDE. Follow one of the next tutorials to prepare your
Arduino IDE to work with the ESP32, if you haven’t already.
In your Arduino IDE, you can go to File > Examples > ESP32 BLE Arduino and explore the examples that come with the
BLE library.
Note: to see the ESP32 examples, you must have the ESP32 board selected on Tools > Board.
For a brief introduction to the ESP32 with BLE on the Arduino IDE, we’ll create an ESP32 BLE server, and then an ESP32
BLE scanner to find that server. We’ll use and explain the examples that come with the BLE library.
To follow this example, you need two ESP32 development boards. We’ll be using the ESP32 DOIT DEVKIT V1 Board.
To create an ESP32 BLE Server, open your Arduino IDE and go to File > Examples > ESP32 BLE Arduino and select the
BLE_server example. The following code should load:
/*
*/
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
// https://www.uuidgenerator.net/
void setup() {
Serial.begin(115200);
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE
);
pService->start();
pAdvertising->addServiceUUID(SERVICE_UUID);
pAdvertising->setScanResponse(true);
pAdvertising->setMinPreferred(0x12);
BLEDevice::startAdvertising();
void loop() {
delay(2000);
For creating a BLE server, the code should follow the next steps:
1. Create a BLE Server. In this case, the ESP32 acts as a BLE server.
2. Create a BLE Service.
3. Create a BLE Characteristic on the Service.
4. Create a BLE Descriptor on the Characteristic.
5. Start the Service.
6. Start advertising, so it can be found by other devices.
Let’s take a quick look at how the BLE server example code works.
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
Then, you need to define a UUID for the Service and Characteristic.
Then, you create a BLE device called “MyESP32”. You can change this name to whatever you like.
BLEDevice::init("MyESP32");
After that, you create a service for the BLE server with the UUID defined earlier.
Then, you set the characteristic for that service. As you can see, you also use the UUID defined earlier, and you need to
pass as arguments the characteristic’s properties. In this case, it’s: READ and WRITE.
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE
);
After creating the characteristic, you can set its value with the setValue() method.
pCharacteristic->setValue("Hello World says Neil");
In this case we’re setting the value to the text “Hello World says Neil”. You can change this text to whatever your like. In
future projects, this text can be a sensor reading, or the state of a lamp, for example.
Finally, you can start the service, and the advertising, so other BLE devices can scan and find this BLE device.
pAdvertising->start();
This is just a simple example on how to create a BLE server. In this code nothing is done in the loop(), but you can add
what happens when a new client connects (check the BLE_notify example for some guidance).
ESP32 BLE Scanner
Creating an ESP32 BLE scanner is simple. Grab another ESP32 (while the other is running the BLE server sketch). In your
Arduino IDE, go to File > Examples > ESP32 BLE Arduino and select the BLE_scan example. The following code should
load.
/*
*/
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
BLEScan* pBLEScan;
};
void setup() {
Serial.begin(115200);
Serial.println("Scanning...");
BLEDevice::init("");
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
pBLEScan->setInterval(100);
void loop() {
Serial.println(foundDevices.getCount());
Serial.println("Scan done!");
delay(2000);
This code initializes the ESP32 as a BLE device and scans for nearby devices. Upload this code to your ESP32. You might
want to temporarily disconnect the other ESP32 from your computer, so you’re sure that you’re uploading the code to
the right ESP32 board.
Once the code is uploaded and you should have the two ESP32 boards powered on:
Go to the Serial Monitor with the ESP32 running the “BLE_scan” example, press the ESP32 (with the “BLE_scan” sketch)
ENABLE button to restart and wait a few seconds while it scans.
The scanner found two devices: one is the ESP32 (it has the name “MyESP32), and the other is our MiBand2.
Most modern smartphones should have BLE capabilities. I’m currently using a OnePlus 5, but most smartphones should
also work.
You can scan your ESP32 BLE server with your smartphone and see its services and characteristics. For that, we’ll be
using a free app called nRF Connect for Mobile from Nordic, it works on Android (Google Play Store) and iOS (App
Store).
Go to Google Play Store or App Store and search for “nRF Connect for Mobile”. Install the app and open it.
Don’t forget go to the Bluetooth settings and enable Bluetooth adapter in your smartphone. You may also want to make
it visible to other devices to test other sketches later on.
Once everything is ready in your smartphone and the ESP32 is running the BLE server sketch, in the app, tap the scan
button to scan for nearby devices. You should find an ESP32 with the name “MyESP32”.
As you can see in the figure below, the ESP32 has a service with the UUID that you’ve defined earlier. If you tap the
service, it expands the menu and shows the Characteristic with the UUID that you’ve also defined.
The characteristic has the READ and WRITE properties, and the value is the one you’ve previously defined in the BLE
server sketch. So, everything is working fine.