BLE ESP32. Bluetooth. Send. Receive. Arduino IDE

Hello friends,

I’ll write in this discussion about BLE on ESP32, send and receive text, with clock and without clock. Notify. I’ll use the codes of Neil Kolban.

0.- Board D1 R32 ESP32.
This is a cheap card ($ 5) with the dimensions and shape of the Arduino UNO, but with the ESP32.

Search images: D1 R32 ESP32

This card has classic Bluetooth, BLE, WiFi, ADC, DAC, and more feature.

This card can be programmed with the Arduino IDE.

1.- Software.

2.- App send text to ESP32. Show on the Serial Monitor.
p110i_esp32_ble_enviar.aia (220.5 KB)

  • Write and Send a text.
  • Texts are sent in packages of 20 characters.
  • Send: “El Ñandú corrió por Cádiz
  • Receive: “El Ñandú corrió p” = 17 chars + special chars: Ñ,ú,ó need 2 bytes.

/*
    Based on Neil Kolban example for IDF: 
https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleWrite.cpp
    Ported to Arduino ESP32 by Evandro Copercini
*/
// Modificado por Juan Antonio Villalpando.
// http://kio4.com/arduino/160i_Wemos_ESP32_BLE.htm

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

String valor;

#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"

class MyCallbacks: public BLECharacteristicCallbacks {
    void onWrite(BLECharacteristic *pCharacteristic) {
      std::string value = pCharacteristic->getValue();

      if (value.length() > 0) {
        valor = "";
        for (int i = 0; i < value.length(); i++){
          // Serial.print(value[i]); // Presenta value.
          valor = valor + value[i];
        }

        Serial.println("*********");
        Serial.print("valor = ");
        Serial.println(valor); // Presenta valor.
      }
    }
};

void setup() {
  Serial.begin(115200);

  BLEDevice::init("MyESP32");
  BLEServer *pServer = BLEDevice::createServer();
  BLEService *pService = pServer->createService(SERVICE_UUID);
  BLECharacteristic *pCharacteristic = pService->createCharacteristic(
                                         CHARACTERISTIC_UUID,
                                         BLECharacteristic::PROPERTY_READ |
                                         BLECharacteristic::PROPERTY_WRITE
                                       );

  pCharacteristic->setCallbacks(new MyCallbacks());
  pCharacteristic->setValue("Hello World");
  pService->start();

  BLEAdvertising *pAdvertising = pServer->getAdvertising();
  pAdvertising->start();
}

void loop() {
  // put your main code here, to run repeatedly:
  delay(2000);
   // Serial.println("valor en el loop = ");
   // Serial.println(valor); // Presenta valor.
}

3.- App sends text and receives random number. With Clock.
p110i_esp32_ble_recibir.aia (221.0 KB)

/*
    Based on Neil Kolban example for IDF: 
https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleWrite.cpp
    Ported to Arduino ESP32 by Evandro Copercini
*/
// Modificado por Juan Antonio Villalpando.
// http://kio4.com/arduino/160i_Wemos_ESP32_BLE.htm

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

String valor;
int aleatorio;
String alea = "2";


#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"

class MyCallbacks: public BLECharacteristicCallbacks {
    void onWrite(BLECharacteristic *pCharacteristic) {
      std::string value = pCharacteristic->getValue();
      pCharacteristic->setValue(alea.c_str()); // Pone el numero aleatorio

      if (value.length() > 0) {
        valor = "";
        for (int i = 0; i < value.length(); i++){
          // Serial.print(value[i]); // Presenta value.
          valor = valor + value[i];
        }

        Serial.println("*********");
        Serial.print("valor = ");
        Serial.println(valor); // Presenta valor.
      }
    }
};

void setup() {
  Serial.begin(115200);

  BLEDevice::init("MyESP32");
  BLEServer *pServer = BLEDevice::createServer();
  BLEService *pService = pServer->createService(SERVICE_UUID);
  BLECharacteristic *pCharacteristic = pService->createCharacteristic(
                                         CHARACTERISTIC_UUID,
                                         BLECharacteristic::PROPERTY_READ |
                                         BLECharacteristic::PROPERTY_WRITE
                                       );

  pCharacteristic->setCallbacks(new MyCallbacks());
  pCharacteristic->setValue("Iniciado.");
  pService->start();

  BLEAdvertising *pAdvertising = pServer->getAdvertising();
  pAdvertising->start();
}

void loop() {
  // put your main code here, to run repeatedly:
  delay(2000);
  //Serial.println("valor en el loop = ");
  //Serial.println(valor); // Presenta valor.
  aleatorio = random(1,100); // Crea el numero aleatorio.
  alea = (String) aleatorio; // Lo convierte en String.
}

4.- App sends text and receives random number. Without Clock.
p110i_esp32_ble_enviar_recibir.aia (220.9 KB)

// Modificado por Juan Antonio Villalpando.
// http://kio4.com/arduino/160i_Wemos_ESP32_BLE.htm

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

String valor;
int aleatorio;
String alea;

#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"

class MyCallbacks: public BLECharacteristicCallbacks {
    void onWrite(BLECharacteristic *pCharacteristic) {
      std::string value = pCharacteristic->getValue();
      pCharacteristic->setValue(alea.c_str()); // Pone el numero aleatorio
      
	  if (value.length() > 0) {
        valor = "";
        for (int i = 0; i < value.length(); i++){
          // Serial.print(value[i]); // Presenta value.
          valor = valor + value[i];
        }

        Serial.println("*********");
        Serial.print("valor = ");
        Serial.println(valor); // Presenta valor.
      }
    }
};

void setup() {
  Serial.begin(115200);

  BLEDevice::init("MyESP32");
  BLEServer *pServer = BLEDevice::createServer();
  BLEService *pService = pServer->createService(SERVICE_UUID);
  BLECharacteristic *pCharacteristic = pService->createCharacteristic(
                                         CHARACTERISTIC_UUID,
                                         BLECharacteristic::PROPERTY_READ |
                                         BLECharacteristic::PROPERTY_WRITE
                                       );

  pCharacteristic->setCallbacks(new MyCallbacks());
  pCharacteristic->setValue("Iniciado.");
  pService->start();

  BLEAdvertising *pAdvertising = pServer->getAdvertising();
  pAdvertising->start();
}

void loop() {
  delay(1000);
  aleatorio = random(1,100); // Crea el numero aleatorio.
  alea = (String) aleatorio; // Lo convierte en String.aleatorio
}

5.- App sends text and receives according to the text sent a random number. Without Clock.

  • The same application as the previous example: p110i_esp32_ble_enviar_recibir.aia (220.9 KB)

  • If send text: uno, receive a random number: 1…50

  • If send text: dos, receive a random number: 100…200

  • Ir send text: tres, receive two random numbers: (1…50,100…200)

// Modificado por Juan Antonio Villalpando.
// http://kio4.com/arduino/160i_Wemos_ESP32_BLE.htm

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

String valor;
int aleatorio1;
int aleatorio2;
String alea1;
String alea2;
String alea3;

#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"

class MyCallbacks: public BLECharacteristicCallbacks {
    void onWrite(BLECharacteristic *pCharacteristic) {
      std::string value = pCharacteristic->getValue();
     
	  if (value.length() > 0) {
        valor = "";
        for (int i = 0; i < value.length(); i++){
          // Serial.print(value[i]); // Presenta value.
          valor = valor + value[i];
        }

        Serial.println("*********");
        Serial.print("valor = ");
        Serial.println(valor); // Presenta valor.
		
        if(valor == "uno") {
        pCharacteristic->setValue(alea1.c_str()); // Pone el numero aleatorio
          }
        if(valor == "dos") {
        pCharacteristic->setValue(alea2.c_str()); // Pone el numero aleatorio
          }
        if(valor == "tres") {
        pCharacteristic->setValue(alea3.c_str()); // Pone el numero aleatorio
          }
      }
    }
};

void setup() {
  Serial.begin(115200);

  BLEDevice::init("MyESP32");
  BLEServer *pServer = BLEDevice::createServer();
  BLEService *pService = pServer->createService(SERVICE_UUID);
  BLECharacteristic *pCharacteristic = pService->createCharacteristic(
                                         CHARACTERISTIC_UUID,
                                         BLECharacteristic::PROPERTY_READ |
                                         BLECharacteristic::PROPERTY_WRITE
                                       );

  pCharacteristic->setCallbacks(new MyCallbacks());
  pCharacteristic->setValue("Iniciado.");
  pService->start();

  BLEAdvertising *pAdvertising = pServer->getAdvertising();
  pAdvertising->start();
}

void loop() {
  delay(1000);
  aleatorio1 = random(1,50); // Crea el numero aleatorio.
  alea1 = (String) aleatorio1; // Lo convierte en String.aleatorio
  aleatorio2 = random(100,200); // Crea el numero aleatorio.
  alea2 = (String) aleatorio2; // Lo convierte en String.aleatorio
  alea3 = alea1 + "," + alea2;
       }

6.- ESP32 sends automatically (Notify) a random number to App.
p110i_esp32_ble_notifica.aia (220.6 KB)
The Bluetooth LE specification includes a mechanism known as notify that lets you know when data’s changed. When notify on a characteristic is enabled and the sender writes to it, the new value is automatically sent to the receiver, without the receiver explicitly issuing a read command. (Reference ArduinoBLE)

ESP32 code generates a random number every 500 milisecond and notifies (sends) it to the application.


/*
    Based on Neil Kolban example for IDF:
   https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleNotify.cpp
   Ported to Arduino ESP32 by Evandro Copercini updated by chegewara
   Create a BLE server that, once we receive a connection, will send periodic notifications.
   A connect hander associated with the server starts a background task that performs notification
   every couple of seconds.
*/

// Modificado por Juan A. Villalpando
// http://kio4.com/arduino/160i_Wemos_ESP32_BLE.htm

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

BLEServer* pServer = NULL;
BLECharacteristic* pCharacteristic = NULL;
bool deviceConnected = false;
bool oldDeviceConnected = false;
uint32_t value = 0;

// See the following for generating UUIDs:
// https://www.uuidgenerator.net/

#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"


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

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

void setup() {
  Serial.begin(115200);

  // Create the BLE Device
  BLEDevice::init("MyESP32");

  // Create the BLE Server
  pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());

  // Create the BLE Service
  BLEService *pService = pServer->createService(SERVICE_UUID);

  // Create a BLE Characteristic
  pCharacteristic = pService->createCharacteristic(
                      CHARACTERISTIC_UUID,
                      BLECharacteristic::PROPERTY_READ   |
                      BLECharacteristic::PROPERTY_WRITE  |
                      BLECharacteristic::PROPERTY_NOTIFY |
                      BLECharacteristic::PROPERTY_INDICATE
                    );

  // https://www.bluetooth.com/specifications/gatt/viewer?
  // attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml
  // Create a BLE Descriptor
  pCharacteristic->addDescriptor(new BLE2902());

  // Start the service
  pService->start();

  // Start advertising
  BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
  pAdvertising->addServiceUUID(SERVICE_UUID);
  pAdvertising->setScanResponse(false);
  pAdvertising->setMinPreferred(0x0);  // set value to 0x00 to not advertise this parameter
  BLEDevice::startAdvertising();
  Serial.println("Waiting a client connection to notify...");
}

void loop() {
    // notify changed value
    if (deviceConnected) {
       // pCharacteristic->setValue((uint8_t*)&value, 4);
        int aleatorio = random(1,100); // Crea el numero aleatorio.
        String alea = (String) aleatorio; // Lo convierte en String.
        pCharacteristic->setValue(alea.c_str()); // Pone el numero aleatorio
        delay(500); // bluetooth stack will go into congestion, if too many packets are sent.
    }
    // disconnecting
    if (!deviceConnected && oldDeviceConnected) {
        delay(500); // give the bluetooth stack the chance to get things ready
        pServer->startAdvertising(); // restart advertising
        Serial.println("start advertising");
        oldDeviceConnected = deviceConnected;
    }
    // connecting
    if (deviceConnected && !oldDeviceConnected) {
        // do stuff here on connecting
        oldDeviceConnected = deviceConnected;
    }
}

That must have been a lot of work.
I don’t see any use of the Register block in your examples.
I remember a thread


where having it made a difference.

7.-App sends a number by a Slider to ESP32. ESP32 return double. Notify.
p110i_esp32_ble_notifica_Deslizador.aia (221.1 KB)

/*
    Video: https://www.youtube.com/watch?v=oCMOYS71NIU
    Based on Neil Kolban example for IDF: 
    https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleNotify.cpp
    Ported to Arduino ESP32 by Evandro Copercini
    updated by chegewara
   Create a BLE server that, once we receive a connection, will send periodic notifications.
   A connect hander associated with the server starts a background task that performs notification
   every couple of seconds.
*/

// Modificado por Juan A. Villalpando
// http://kio4.com/arduino/160i_Wemos_ESP32_BLE.htm

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

String valor;

BLEServer* pServer = NULL;
BLECharacteristic* pCharacteristic = NULL;
bool deviceConnected = false;
bool oldDeviceConnected = false;
//uint32_t value = 0;

#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"

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

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

////////////////////// WriteStrings /////////////////////////////
class MyCallbacks: public BLECharacteristicCallbacks {
    void onWrite(BLECharacteristic *pCharacteristic) {
      std::string value = pCharacteristic->getValue();

      if (value.length() > 0) {
        valor = "";
        for (int i = 0; i < value.length(); i++){
          // Serial.print(value[i]); // Presenta value.
          valor = valor + value[i];
        }

        Serial.println("*********");
        Serial.print("valor = ");
        Serial.println(valor); // Presenta valor.
      }
    }
};
///////////////////////////////////////////////////

void setup() {
  Serial.begin(115200);

  // Create the BLE Device
  BLEDevice::init("MyESP32");

  // Create the BLE Server
  pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());

  // Create the BLE Service
  BLEService *pService = pServer->createService(SERVICE_UUID);

  // Create a BLE Characteristic
  pCharacteristic = pService->createCharacteristic(
                      CHARACTERISTIC_UUID,
                      BLECharacteristic::PROPERTY_READ   |
                      BLECharacteristic::PROPERTY_WRITE  |
                      BLECharacteristic::PROPERTY_NOTIFY |
                      BLECharacteristic::PROPERTY_INDICATE
                    );

  // https://www.bluetooth.com/specifications/gatt/viewer?
  //   attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml
  // Create a BLE Descriptor
  pCharacteristic->addDescriptor(new BLE2902());
  // Esta línea es para el WriteStrings:
  pCharacteristic->setCallbacks(new MyCallbacks());

  // Start the service
  pService->start();

  // Start advertising
  BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
  pAdvertising->addServiceUUID(SERVICE_UUID);
  pAdvertising->setScanResponse(false);
  pAdvertising->setMinPreferred(0x0);  // set value to 0x00 to not advertise this parameter
  BLEDevice::startAdvertising();
  Serial.println("Waiting a client connection to notify...");
}

void loop() {
    // notify changed value
    if (deviceConnected) {
          std::string value = pCharacteristic->getValue();
       // pCharacteristic->setValue((uint8_t*)&value, 4);
        int doble = valor.toInt() * 2 ;
        String doblado = (String) doble; // Lo convierte en String.
       
        pCharacteristic->setValue(doblado.c_str()); // Pone el numero doble
        pCharacteristic->notify();
        delay(5); // bluetooth stack will go into congestion, if too many packets are sent.
    }
    // disconnecting
    if (!deviceConnected && oldDeviceConnected) {
        delay(500); // give the bluetooth stack the chance to get things ready
        pServer->startAdvertising(); // restart advertising
        Serial.println("start advertising");
        oldDeviceConnected = deviceConnected;
    }
    // connecting
    if (deviceConnected && !oldDeviceConnected) {
        // do stuff here on connecting
        oldDeviceConnected = deviceConnected;
    }
}

Regards.
Juan Antonio Villalpando.

More information: http://kio4.com/arduino/160i_Wemos_ESP32_BLE.htm

RegisterForStrings also in the examples.

I see them now, examples 6 & 7.
Sorry for the confusion!

Invaluable help Juan. A much needed guide.

1 Like