Example Code for Arduino - ESP32-C6 Bluetooth Receive & Transmit
This project demonstrates BLE data transmission with the FireBeetle 2 ESP32-C6, enabling wireless communication between an ESP32 and a mobile phone or between two ESP32 boards.
Hardware Preparation
- FireBeetle 2 ESP32-C6 (SKU: DFR1075) * 1
- USB Type-C Cable (Included with the board) * 1
Software Preparation
- Download Arduino IDE: Click to download Arduino IDE
Data Transmission between ESP32 and Mobile Phone
The demo below shows the data transmission between ESP32 and a mobile phone. Users can modify the data transmit or data receive part to fit their needs.
Sample Code
/*
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
Create a BLE server that, once we receive a connection, will send periodic notifications.
The service advertises itself as: 6E400001-B5A3-F393-E0A9-E50E24DCCA9E
Has a characteristic of: 6E400002-B5A3-F393-E0A9-E50E24DCCA9E - used for receiving data with "WRITE"
Has a characteristic of: 6E400003-B5A3-F393-E0A9-E50E24DCCA9E - used to send data with "NOTIFY"
The design of creating the BLE server is:
1. Create a BLE Server
2. Create a BLE Service
3. Create a BLE Characteristic on the Service
4. Create a BLE Descriptor on the characteristic
5. Start the service.
6. Start advertising.
*/
/* This example domenstrates the Bluetooth data transparent transmission function. Burn the code, open serial monitor, turn on the BLE debugger on the phone, then,
* 1. you can see the data sent by ESP32-S3--see APP usage image
* 2. send data to ESP32-S3 by the input box of BLE debugger--see APP usage image
* This example originates from BLE_uart sample
*/
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
BLEServer *pServer = NULL;
BLECharacteristic * pTxCharacteristic;
bool deviceConnected = false;
uint8_t txValue = 0;
// See the following for generating UUIDs:
// https://www.uuidgenerator.net/
#define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
//Bluetooth connect/disconnect. Auto triggered when connection/disconnection event occurs.
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) { //Execute this function when Bluetooth is connected.
Serial.println("Bluetooth connected");
deviceConnected = true;
};
void onDisconnect(BLEServer* pServer) { //Execute this function when Bluetooth is disconnected
Serial.println("Bluetooth disconnected");
deviceConnected = false;
delay(500); // give the bluetooth stack the chance to get things ready
pServer->startAdvertising(); // restart advertising
}
};
/****************Data Receiving*************/
/****************************************/
//Process received Bluetooth data. Auto triggered when data received.
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
String rxValue = pCharacteristic->getValue();//Receive data, and assign it to rxValue
//if(rxValue == "ON"){Serial.println("Turn light on");} //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]);
}
Serial.println();
Serial.println("*********");
}
}
};
/***************************************/
/****************************************/
void setup() {
Serial.begin(115200);
BLEBegin(); //Init Bluetooth
}
void loop() {
/****************Data Transmitting*************/
/****************************************/
if (deviceConnected) { //Transmit data when the Bluetooth is connected.
pTxCharacteristic->setValue("Hello"); //Send char string
pTxCharacteristic->notify();
delay(10); // bluetooth stack will go into congestion, if too many packets are sent
pTxCharacteristic->setValue("DFRobot"); //Send char string
pTxCharacteristic->notify();
delay(10); // bluetooth stack will go into congestion, if too many packets are sent
}
/****************************************/
/****************************************/
}
void BLEBegin(){
// Create the BLE Device
BLEDevice::init(/*BLE Name*/"UART Service");
// 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
pTxCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_TX,
BLECharacteristic::PROPERTY_NOTIFY
);
pTxCharacteristic->addDescriptor(new BLE2902());
BLECharacteristic * pRxCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_RX,
BLECharacteristic::PROPERTY_WRITE
);
pRxCharacteristic->setCallbacks(new MyCallbacks());
// Start the service
pService->start();
// Start advertising
pServer->getAdvertising()->start();
Serial.println("Waiting a client connection to notify...");
}
Bluetooth Communication between two ESP32 Boards
The demo below shows the Bluetooth communication between two ESP32 boards. Users can modify the data transmit or data receive part to fit their needs.
Sample Code
Program for client:
/**
* 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*************/
/****************************************/
//Bluetooth receiving data handle. Auto triggered when data received.
static void notifyCallback(BLERemoteCharacteristic* pBLERemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify) { //Pass in uint8_t* pData for storing 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 light on");} //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. Auto triggered when connection/disconnection 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 scanning handle event. Auto-triggered when scanning is enabled.
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 nothing more we will do.");
}
doConnect = false;
}
/****************Data Transmit*************/
/****************************************/
if (connected) { //Transmit data when Bluetooth server is connected
pTXRemoteCharacteristic->writeValue("I am client");
pTXRemoteCharacteristic->writeValue("Hello client");
}
if(!connected){ //Re-scan when no Bluetooth server is connected
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());//scanning function
pBLEScan->setInterval(1349);//Set scanning interval
pBLEScan->setWindow(449);//Active scanning time
pBLEScan->setActiveScan(true);
pBLEScan->start(5, false);//Scanning time. Unit: s
}
//Bluetooth connection handling
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;
}
Program for Server:
/*
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. Auto triggered when connection/disconnection event occurs.
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) { //Execute this function when Bluetooth is connected.
Serial.println("Bluetooth connected");
deviceConnected = true;
};
void onDisconnect(BLEServer* pServer) { //Execute this function 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*************/
/****************************************/
//Bluetooth receiving data handle. Auto triggered when data received.
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
String rxValue = pCharacteristic->getValue(); //Receive data, and assign it to rxValue
//if(rxValue == "ON"){Serial.println("Turn light on");} //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 out
Serial.println();
Serial.println("*********");
}
}
};
/****************************************/
/****************************************/
void setup() {
Serial.begin(115200);
Serial.println("Starting BLE work!");
bleBegin();
}
/****************Data Transmitting*************/
/****************************************/
void loop() {
if(deviceConnected){ //Transmit data when the Bluetooth is connected.
pTxCharacteristic->setValue("I am server");
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?
