Example Code for Arduino-Two ESP32C3 Bluetooth Communication

Use this example to demonstrate the data transmission between ESP32-C3 and ESP32-C3. If you need to modify or use the data, you only need to change the data receiving part or the data transmitting part of the code.

Hardware Preparation

Software Preparation

Sample Code

Host code

/**
 * A BLE client example that is rich in capabilities.
 * There is a lot new capabilities implemented.
 * author unknown
 * updated by chegewara
 */

#include "BLEDevice.h"
//#include "BLEScan.h"

// The remote service we wish to connect to.
static BLEUUID serviceUUID("4fafc201-1fb5-459e-8fcc-c5c9c331914b");
// The characteristic of the remote service we are interested in.
static BLEUUID    charTXUUID("beb5483e-36e1-4688-b7f5-ea07361b26a8");

static BLEUUID    charRXUUID("beb5483f-36e1-4688-b7f5-ea07361b26a8");

static boolean doConnect = false;
static boolean connected = false;
static boolean doScan = false;
static BLERemoteCharacteristic* pTXRemoteCharacteristic;
static BLERemoteCharacteristic* pRXRemoteCharacteristic;
static BLEAdvertisedDevice* myDevice;


/****************Data receiving section*************/
/****************************************/
//Bluetooth receive data processing, automatically trigger when data is received
static void notifyCallback(BLERemoteCharacteristic* pBLERemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify) {  //Transfer in uint8_t* pData to store data
    String BLEData = "";
    for(int i = 0; i < length; i++)  //
      BLEData += (char)pData[i];
    Serial.println("*********");
    Serial.print("Received Value: ");
    Serial.println(BLEData);
    Serial.println("*********");

    //if(BLEData == "ON"){Serial.println("Turn on the light");}  //Determine whether the received character is "ON"

    //Serial.print("Notify callback for characteristic ");
    //Serial.print(pBLERemoteCharacteristic->getUUID().toString().c_str());
    //Serial.print(" of data length ");
    //Serial.println(length);
}
/****************************************/
/****************************************/

//Bluetooth connect/disconnect handling. Triggered automatically when a connect/disconnect event occurs
class MyClientCallback : public BLEClientCallbacks {
  void onConnect(BLEClient* pclient) {
  }

  void onDisconnect(BLEClient* pclient) {
    connected = false;
    Serial.println("onDisconnect");
  }
};


/**
 * Scan for BLE servers and find the first one that advertises the service we are looking for.
 */
 //Bluetooth scan processing event. Triggered automatically when scanning is turned on
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
 /**
   * Called for each advertising BLE server.
   */
  void onResult(BLEAdvertisedDevice advertisedDevice) {
    //Serial.print("BLE Advertised Device found: ");
    //Serial.println(advertisedDevice.toString().c_str());

    // We have found a device, let us now see if it contains the service we are looking for.
    if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(serviceUUID)) {
      BLEDevice::getScan()->stop();
      myDevice = new BLEAdvertisedDevice(advertisedDevice);
      doConnect = true;
      doScan = true;

    } // Found our server
  } // onResult
}; // MyAdvertisedDeviceCallbacks



void setup() {
  Serial.begin(115200);
  Serial.println("Starting Arduino BLE Client application...");
  bleBegin();

}

void loop() {
  // If the flag "doConnect" is true then we have scanned for and found the desired
  // BLE Server with which we wish to connect.  Now we connect to it.  Once we are 
  // connected we set the connected flag to be true.
  if (doConnect == true) {
    if (connectToServer()) {
      Serial.println("We are now connected to the BLE Server.");
    } else {
      Serial.println("We have failed to connect to the server; there is nothin more we will do.");
    }
    doConnect = false;
  }
/****************Data transmitting section*************/
/****************************************/
  if (connected) {  //Send data when connected to bluetooth slave
    pTXRemoteCharacteristic->writeValue("I am the host");
    pTXRemoteCharacteristic->writeValue("Hello client");
  }
  if(!connected){  //Rescan when not connected to bluetooth slave
    BLEDevice::getScan()->start(5,false);  // this is just example to start scan after disconnect, most likely there is better way to do it in arduino
  }
/****************************************/
/****************************************/
  delay(1000); 
}


void bleBegin()
{
  BLEDevice::init("");

  // Retrieve a Scanner and set the callback we want to use to be informed when we
  // have detected a new device.  Specify that we want active scanning and start the
  // scan to run for 5 seconds.
  BLEScan* pBLEScan = BLEDevice::getScan();
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());//Scan processing function
  pBLEScan->setInterval(1349);//Set the scan interval time
  pBLEScan->setWindow(449);//Active scan time
  pBLEScan->setActiveScan(true);
  pBLEScan->start(5, false);//Scan time, in seconds
  }


//Bluetooth connection processing
bool connectToServer() {
    Serial.print("Forming a connection to ");
    Serial.println(myDevice->getAddress().toString().c_str());

    BLEClient*  pClient  = BLEDevice::createClient();
    Serial.println(" - Created client");

    pClient->setClientCallbacks(new MyClientCallback());

    // Connect to the remove BLE Server.
    pClient->connect(myDevice);  // if you pass BLEAdvertisedDevice instead of address, it will be recognized type of peer device address (public or private)
    Serial.println(" - Connected to server");
    pClient->setMTU(517); //set client to request maximum MTU from server (default is 23 otherwise)

    // Obtain a reference to the service we are after in the remote BLE server.
    BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
    if (pRemoteService == nullptr) {
      Serial.print("Failed to find our service UUID: ");
      Serial.println(serviceUUID.toString().c_str());
      pClient->disconnect();
      return false;
    }
    Serial.println(" - Found our service");


    // Obtain a reference to the characteristic in the service of the remote BLE server.
    pTXRemoteCharacteristic = pRemoteService->getCharacteristic(charTXUUID);
    if (pTXRemoteCharacteristic == nullptr) {
      Serial.print("Failed to find our characteristic UUID: ");
      Serial.println(charTXUUID.toString().c_str());
      pClient->disconnect();
      return false;
    }
    pRXRemoteCharacteristic = pRemoteService->getCharacteristic(charRXUUID);
    if (pRXRemoteCharacteristic == nullptr) {
      Serial.print("Failed to find our characteristic UUID: ");
      Serial.println(charRXUUID.toString().c_str());
      pClient->disconnect();
      return false;
    }
    Serial.println(" - Found our characteristic");

    if(pRXRemoteCharacteristic->canNotify())
      pRXRemoteCharacteristic->registerForNotify(notifyCallback);

    connected = true;
    return true;
}

Slave code

/*
    Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleServer.cpp
    Ported to Arduino ESP32 by Evandro Copercini
    updates by chegewara
*/

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

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

#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID_RX "beb5483e-36e1-4688-b7f5-ea07361b26a8"
#define CHARACTERISTIC_UUID_TX "beb5483f-36e1-4688-b7f5-ea07361b26a8"
uint8_t txValue = 0;
bool deviceConnected = false;
BLECharacteristic *pTxCharacteristic;


//Bluetooth connect/disconnect processing. Triggered automatically when a connect/disconnect event occurs
class MyServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {   //This function will be executed when Bluetooth is connected
      Serial.println("Bluetooth connected");
      deviceConnected = true;
    };

    void onDisconnect(BLEServer* pServer) {  //This function will be executed when Bluetooth is disconnected
        Serial.println("Bluetooth disconnected");
        deviceConnected = false;
        delay(500); // give the bluetooth stack the chance to get things ready
        BLEDevice::startAdvertising(); // restart advertising
    }
};
/****************Data receiving section*************/
/****************************************/
//Bluetooth receive data processing. Triggered automatically when data is received
class MyCallbacks: public BLECharacteristicCallbacks {
    void onWrite(BLECharacteristic *pCharacteristic) {
      String rxValue = pCharacteristic->getValue();  //Use rxValue to receive data

      //if(rxValue == "ON"){Serial.println("Turn on the light");}   //Determine whether the received character is "ON"

      if (rxValue.length() > 0) {
        Serial.println("*********");
        Serial.print("Received Value: ");
        for (int i = 0; i < rxValue.length(); i++)
              Serial.print(rxValue[i]);    //Print the received data

        Serial.println();
        Serial.println("*********");
      }
    }
};
/****************************************/
/****************************************/

void setup() {
  Serial.begin(115200);
  Serial.println("Starting BLE work!");
  bleBegin();
}

/****************Data sending section*************/
/****************************************/
void loop() {
  if(deviceConnected){  //Send data when a device is connected
    pTxCharacteristic->setValue("I am a slave");
    pTxCharacteristic->notify();

    pTxCharacteristic->setValue("Hello Sever");
    pTxCharacteristic->notify();
  }
  /****************************************/
  /****************************************/
  delay(1000);
}


void bleBegin()
{
  BLEDevice::init(/*BLE name*/"Long name works now");
  BLEServer *pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());
  BLEService *pService = pServer->createService(SERVICE_UUID);
  BLECharacteristic *pRxCharacteristic = pService->createCharacteristic(
                                         CHARACTERISTIC_UUID_RX,
                                         BLECharacteristic::PROPERTY_WRITE 
                                       );
  pRxCharacteristic->setCallbacks(new MyCallbacks()); 

 pTxCharacteristic = pService->createCharacteristic(
                                         CHARACTERISTIC_UUID_TX,
                                         BLECharacteristic::PROPERTY_NOTIFY
                                       );
 pTxCharacteristic->addDescriptor(new BLE2902());

  pService->start();
  // BLEAdvertising *pAdvertising = pServer->getAdvertising();  // this still is working for backward compatibility
  BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
  pAdvertising->addServiceUUID(SERVICE_UUID);
  pAdvertising->setScanResponse(true);
  pAdvertising->setMinPreferred(0x06);  // functions that help with iPhone connections issue
  pAdvertising->setMinPreferred(0x12);
  BLEDevice::startAdvertising();

  }

Was this article helpful?

TOP