Bluetooth & BLE
As covered in the Specifications lesson, the ESP32 supports two different Bluetooth stacks - Classic Bluetooth (BR/EDR, Bluetooth v4.2) and Bluetooth LE (BLE) - and both are genuinely available on the chip. They are suited to quite different jobs.
Classic Bluetooth vs BLE
| Classic Bluetooth (BR/EDR) | BLE | |
|---|---|---|
| Best for | Continuous data streams - acts like a serial-port-style connection | Small, infrequent bursts of data |
| Power use | Higher | Very low - built for battery-powered devices |
| Typical use case | A serial-replacement link to a phone or computer | A battery-powered sensor that wakes up occasionally and reports a reading |
In short: reach for Classic Bluetooth when you want something that behaves like a continuous serial cable replacement, and reach for BLE when you want the lowest possible power draw for a device that only needs to send small amounts of data now and then - which describes the large majority of battery-powered sensor projects.
How a BLE Server Works, Conceptually
A BLE device that advertises data to the world (rather than connecting out to something else) is called
a BLE server. The general flow, using the Arduino ESP32 BLE library's
BLEDevice/BLEServer style API, looks like this:
- Initialize the BLE stack and give the device a name.
- Create a BLE server object.
- Create a service on that server - a logical grouping identified by a UUID.
- Create a characteristic within that service - this is the actual piece of data (for example, a sensor reading) that other devices can read.
- Start the service and begin advertising, so nearby BLE devices (like a phone running a BLE scanner app) can discover it.
A Simple Illustrative Example
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
void setup() {
BLEDevice::init("ESP32-Sensor");
BLEServer *pServer = BLEDevice::createServer();
BLEService *pService = pServer->createService(SERVICE_UUID);
BLECharacteristic *pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ
);
pCharacteristic->setValue("hello from ESP32");
pService->start();
pServer->getAdvertising()->start();
}
void loop() {
// update pCharacteristic's value here as new readings come in
}
This is intentionally a simple, illustrative sketch rather than a full production example - it shows the shape of the flow (init, create server, create service, create characteristic, start advertising) without every detail a real project would add, such as handling connect/disconnect callbacks.
Real Use Cases
BLE is the natural fit for a battery-powered sensor that spends most of its time idle and occasionally wakes up to advertise or update a reading - a remote temperature sensor, a door/window contact sensor, or a wearable that reports data in short bursts. Classic Bluetooth fits better when you want something closer to a continuous serial link to a phone or computer, at the cost of higher power use.