Home

Guide no. 64

A BLE server with two characteristics: the phone reads the temperature, receives updates and turns on the LED. With nRF Connect.

By Ada Intelisano · informaticait.it technical team

Download the PDF (A4, 6 pages) Free to print and share, without changes — CC BY-ND 4.0
In short
  • Service = folder, characteristics = values, each with a UUID.
  • Temperature with read and notifications; LED with a write of 1 or 0.
  • You test it with nRF Connect for Mobile.
  • After a disconnection: startAdvertising().
Time: 45 minutesLevel: next stepsBefore: guide no. 56

No router, no network: the phone talks to the board over Bluetooth LE, the same one used by fitness bands and home sensors. The phone reads the temperature and receives updates on its own; writing 1 or 0 turns the LED on and off.

1The words of Bluetooth LE

Phone and board over Bluetooth LEnRF ConnectFireBeetle-MeteoUnknown Servicecb5a991b-bf61-…a3cc1db8-…READ, NOTIFYValue: 21.41171cd6c-…WRITEValue: 12/D927/D4ESP32-WROOM-32EespressifFireBeetle 2 ESP32-ERST3V3GNDENSCKMOSIMISOSCLSDAD9D7D6D5D3D2TXRXVCC3V3GNDSCLSDAA4A3A2A1A0D13D12D11D10GND3.3VSDASCLGND3.3VSCKSDISDOCSBME280notify: 21.4write: 1Bluetooth LE, a few metresinformaticait.it
New word: service and characteristicsThe board is a small archive (the “GATT server”). Inside it there is a service, a folder; in the service there are the characteristics, the individual values: here the temperature and the LED command. Each characteristic states what you can do with it: read, write, receive notifications.
New word: UUIDThe long, unique name of services and characteristics, like cb5a991b-bf61-…. The short 16-bit ones are reserved for standard uses; for your own project you generate 128-bit ones at random. The sketch already has them.

2The circuit and the sketch

FireBeetle 2 ESP32-E and BME2802/D927/D4ESP32-WROOM-32EespressifFireBeetle 2 ESP32-ERST3V3GNDENSCKMOSIMISOSCLSDAD9D7D6D5D3D2TXRXVCC3V3GNDSCLSDAA4A3A2A1A0D13D12D11D10GND3.3VSDASCLGND3.3VSCKSDISDOCSBME2803V3 → 3.3VGND → GNDSCL (GPIO 22) → SCLSDA (GPIO 21) → SDAfour female-female jumpersinformaticait.it

The sensor is connected as in guide no. 56; the LED is the one on the board. Bluetooth is already in the ESP32 package: no library to install.

// Bluetooth LE server: the phone reads the temperature (and receives updates) and turns on the LED by writing 1 or 0.
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLE2902.h>
#include <Adafruit_BME280.h>

// 128-bit UUIDs made up for this project (generated at random, as the Bluetooth SIG expects for custom services)
#define SERVICE_UUID      "cb5a991b-bf61-4bee-af4b-976ee137c7e6"
#define TEMPERATURE_UUID  "a3cc1db8-b2b8-4886-af86-36deee2fdd20"
#define LED_UUID          "1171cd6c-7e71-4867-b3e1-2a8ac3b36cd4"

const int LED = 2;
Adafruit_BME280 bme;
BLECharacteristic* temperature;
bool connected = false;

class Connection : public BLEServerCallbacks {
  void onConnect(BLEServer* s) { connected = true; }
  void onDisconnect(BLEServer* s) {
    connected = false;
    s->startAdvertising();                 // becomes visible again for the next phone
  }
};

class LedCommand : public BLECharacteristicCallbacks {
  void onWrite(BLECharacteristic* c) {
    auto value = c->getValue();            // std::string in package 2.x, String in 3.x: auto works for both
    if (value.length() > 0) digitalWrite(LED, value[0] == '1' ? HIGH : LOW);
  }
};

void setup() {
  Serial.begin(115200);
  pinMode(LED, OUTPUT);
  if (!bme.begin(0x77)) Serial.println("BME280 not found");

  BLEDevice::init("FireBeetle-Meteo");                   // the name you see on the phone
  BLEServer* server = BLEDevice::createServer();
  server->setCallbacks(new Connection());
  BLEService* service = server->createService(SERVICE_UUID);

  temperature = service->createCharacteristic(TEMPERATURE_UUID,
                  BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY);
  temperature->addDescriptor(new BLE2902());             // the phone needs it to turn on notifications
  BLECharacteristic* led = service->createCharacteristic(LED_UUID, BLECharacteristic::PROPERTY_WRITE);
  led->setCallbacks(new LedCommand());

  service->start();
  BLEDevice::getAdvertising()->addServiceUUID(SERVICE_UUID);
  BLEDevice::startAdvertising();
  Serial.println("Ready: look for FireBeetle-Meteo with nRF Connect");
}

void loop() {
  char text[8];
  snprintf(text, sizeof(text), "%.1f", bme.readTemperature());
  temperature->setValue((uint8_t*)text, strlen(text));   // the value the phone reads
  if (connected) temperature->notify();                  // and sends it to whoever turned on notifications
  delay(2000);
}
New word: notificationInstead of asking for the temperature every time, the phone “subscribes”: the board sends it on its own when it changes. That is why the characteristic has PROPERTY_NOTIFY and the BLE2902 descriptor, the one the phone uses to turn on the subscription.

3Try it with nRF Connect

  1. Install nRF Connect for Mobile by Nordic on your phone (Android and iOS).
  2. Tap Scan, find FireBeetle-Meteo and tap Connect.
  3. Open the service cb5a991b…. On the characteristic a3cc1db8… tap the read arrow: the temperature appears. Tap the notifications symbol: the value updates every 2 seconds.
  4. On the characteristic 1171cd6c… tap the write arrow, choose the text format (UTF-8) and write 1: the LED turns on; 0 turns it off.
✓ What you should seeThe temperature updates by itself in the app and the LED responds to 1 and 0.
If it doesn't work
  • The board does not appear: is Bluetooth on in the phone? The app may ask for scanning permissions: grant them.
  • The value arrives as odd numbers (0x32 0x31…): the app shows it in hexadecimal; choose the text view.
  • Once disconnected it cannot be found again: startAdvertising() is missing from onDisconnect.

4Two things to know

  • Since ESP32 package 3.0 many BLE functions use String instead of std::string. In the sketch, auto value = c->getValue() works in both versions.
  • The range is a few meters and anyone nearby can connect: for real use you add pairing with a passkey.
  • The classic ESP32 also has “traditional” (serial) Bluetooth, which BLE does not replace: they are two different things.

5Challenge yourself

Try it yourself
  • Add a characteristic for humidity.
  • Control the relay from guide no. 43 instead of the LED.
  • Send the temperature only when it changes by at least 0.2 degrees.
✓ What you learned
  • in BLE the board exposes services and characteristics, each with a UUID;
  • the phone reads, writes and receives notifications;
  • after a disconnection you must become visible again with startAdvertising().
Sources: Espressif, ESP-IDF: Bluetooth LE guides; arduino-esp32: BLE examples and 2.x→3.0 migration guide · Bluetooth SIG, Assigned Numbers · Nordic Semiconductor, nRF Connect for Mobile · DFRobot, FireBeetle 2 ESP32-E wiki (Bluetooth example) · informaticait guides no. 43 and 56

Useful products

Other guides

All our guides →
Loading...
Back to top