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.

This page's code is a preview, not something you can run right on this website - this server runs PHP, not the ESP32's own firmware.

Classic Bluetooth vs BLE

Classic Bluetooth (BR/EDR)BLE
Best forContinuous data streams - acts like a serial-port-style connectionSmall, infrequent bursts of data
Power useHigherVery low - built for battery-powered devices
Typical use caseA serial-replacement link to a phone or computerA 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:

  1. Initialize the BLE stack and give the device a name.
  2. Create a BLE server object.
  3. Create a service on that server - a logical grouping identified by a UUID.
  4. Create a characteristic within that service - this is the actual piece of data (for example, a sensor reading) that other devices can read.
  5. 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.

Recap: The ESP32 supports both Classic Bluetooth (BR/EDR) and BLE. Classic Bluetooth suits continuous, serial-style streams; BLE suits small, infrequent, low-power data bursts. A BLE server is built from: init the BLE stack, create a server, create a service, create a characteristic, then start advertising.
Next steps: Continue to ADC & Reading Sensors to read real-world analog signals.