11. Networking and Communications
This week I used the XIAO nrf52840 to send the accelerometer data via Bluetooth to the ESP32 PCB I made during week08. We also did a group assignment, which you can find here.
I first tried to use the Python script I made for week 4. Our advisor briefly explained how to connect boards to send data via Bluetooth, so I tried making my ESP32 board. First, I obtained the MAC address of my XIAO. The XIAO board would be the server, and the ESP32 the client, which would connect to the XIAO requesting the data.
Although I added the MAC address to the ESP32 code, when I ran both codes, the ESP32 couldn’t find the XIAO. I made sure it was the right one by making a code only to show the address from the XIAO in the serial monitor. After making sure it was indeed correct, I asked ChatGPT to compare both codes and help me figure out what was wrong. It told me that I had to make sure the XIAO advertised the service UUID that the ESP32 was looking for. Although everything seemed to be right, it wasn’t working either. Another thing ChatGPT gave me was a code for the ESP32 that scans all the nearby BLE devices and prints their MAC addresses in the serial monitor. Below is the scanning code:
#include
#include
#include
#include
int scanTime = 5; // scan duration in seconds
void setup() {
Serial.begin(115200);
Serial.println("BLE Scanner starting...");
BLEDevice::init("");
BLEScan* pBLEScan = BLEDevice::getScan();
pBLEScan->setActiveScan(true); // active scan to get scan responses (names, etc.)
pBLEScan->setInterval(100); // scan interval (in 0.625 ms units)
pBLEScan->setWindow(50); // scan window (must be <= interval)
}
void loop() {
BLEScan* pBLEScan = BLEDevice::getScan();
BLEScanResults* results = pBLEScan->start(scanTime, false); // Fix: results should be a pointer
Serial.print("Devices found: ");
Serial.println(results->getCount());
for (int i = 0; i < results->getCount(); ++i) {
BLEAdvertisedDevice device = results->getDevice(i);
String deviceName = device.getName().c_str(); // Directly use String constructor for conversion
String deviceAddr = device.getAddress().toString().c_str();
Serial.print("Device ");
Serial.print(i);
Serial.print(": ");
Serial.print(deviceName);
Serial.print(" [");
Serial.print(deviceAddr);
Serial.println("]");
}
Serial.println("Scan done!");
Serial.println();
pBLEScan->clearResults(); // free scan results to avoid memory leaks
delay(2000); // wait 2 seconds before next scan cycle
}
After several failed attempts trying to detect the board, I decided to use the Arduino code I also made during week 4 for my XIAO instead of the Python one. It worked, so I knew I was on the right track. Since the ESP32 finally detected the XIAO.
For the final ESP32 code I included these files:
#include BLEDevice.h>
#include BLEUtils.h>
#include BLEScan.h>
#include BLEAdvertisedDevice.h>
The problem was that I constantly had this error: Multiple libraries were found for "BLEDevice.h" after asking Chat GPT why I was getting this error while compiling the code. It told me there was a confusion between the ESP32 BLE and the ArduinoBLE libraries, so I had to uninstall the ArduinoBLE library for the code to work. Here are the codes:
#include
#include "LSM6DS3.h"
#include "Wire.h"
#define SERVICE_UUID "12345678-1234-1234-1234-1234567890ab"
#define CHARACTERISTIC_UUID "abcd1234-5678-90ab-cdef-1234567890ab"
BLEService accelService(SERVICE_UUID);
BLECharacteristic accelCharacteristic(CHARACTERISTIC_UUID, BLERead | BLENotify, 50);
LSM6DS3 myIMU(I2C_MODE, 0x6A);
void setup() {
Serial.begin(115200);
while (!Serial);
if (!BLE.begin()) {
Serial.println("BLE failed!");
while (1);
}
BLE.setLocalName("Xiao-Accel");
BLE.setAdvertisedService(accelService);
accelService.addCharacteristic(accelCharacteristic);
BLE.addService(accelService);
BLE.advertise();
Serial.println("BLE Advertising...");
if (myIMU.begin() != 0) {
Serial.println("IMU error!");
while (1);
}
}
void loop() {
BLEDevice central = BLE.central();
if (central) {
Serial.print("Connected to: ");
Serial.println(central.address());
while (central.connected()) {
float x = myIMU.readFloatAccelX();
float y = myIMU.readFloatAccelY();
float z = myIMU.readFloatAccelZ();
char buffer[50];
snprintf(buffer, sizeof(buffer), "X:%.2f Y:%.2f Z:%.2f", x, y, z);
accelCharacteristic.writeValue(buffer);
Serial.println(buffer);
delay(100);
}
Serial.println("Disconnected!");
}
}
#include
#include
#include
#include
#define SERVICE_UUID "12345678-1234-1234-1234-1234567890ab"
#define CHARACTERISTIC_UUID "abcd1234-5678-90ab-cdef-1234567890ab"
bool deviceFound = false;
BLEAdvertisedDevice* myDevice;
BLEClient* pClient;
BLERemoteCharacteristic* pRemoteCharacteristic;
class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks {
void onResult(BLEAdvertisedDevice advertisedDevice) {
if (advertisedDevice.getName() == "Xiao-Accel") {
advertisedDevice.getScan()->stop();
myDevice = new BLEAdvertisedDevice(advertisedDevice);
deviceFound = true;
}
}
};
void setup() {
Serial.begin(115200);
BLEDevice::init("ESP32-BLE-Client");
BLEScan* pBLEScan = BLEDevice::getScan();
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setActiveScan(true);
pBLEScan->start(5, false); // Scan for 5 seconds
}
void loop() {
if (deviceFound) {
pClient = BLEDevice::createClient();
pClient->connect(myDevice);
BLERemoteService* pRemoteService = pClient->getService(SERVICE_UUID);
if (pRemoteService != nullptr) {
pRemoteCharacteristic = pRemoteService->getCharacteristic(CHARACTERISTIC_UUID);
if (pRemoteCharacteristic != nullptr && pRemoteCharacteristic->canNotify()) {
pRemoteCharacteristic->registerForNotify([](BLERemoteCharacteristic* pBLERemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify) {
Serial.print("Received: ");
Serial.write(pData, length);
Serial.println();
});
}
}
while (pClient->isConnected()) {
delay(1000); // Keep connection alive
}
Serial.println("Disconnected, rescanning...");
deviceFound = false;
BLEDevice::getScan()->start(5, false);
}
delay(1000);
}
After uploading the final code, the ESP32 detected the XIAO, and the communication was successfully established. Below is the video showing the boards communicating:
Summary
This week I worked on establishing Bluetooth communication between the XIAO nRF52840 and the ESP32. I used two approaches; one with Python and another with Arduino IDE, both using BLE for communication. After obtaining the MAC address and making sure I had worked with the right UUID, I needed to take extra steps before success. The process involved troubleshooting some library conflicts, but ultimately both boards were able to communicate seamlessly over Bluetooth, and I was able to display the data in real-time.