XIAO ESP32S3: getting robust bluetooth communication

I have a project I’m working on, which has several bluetooth sensors (most XIAO) and one central unit with a display (seeed studio round display) which should display the sensor values.

I have this working, but there are 2 issues:

  1. the BLE Connect call freezes the screen. So does discoverattributes
  2. If a connection is established and then lost, you get unpredictable results. Sometimes the xiao just crashes, sometimes you get erratic sensor values, and so forth.

The first item is logical. As BLE is not threaded, any blocking call (like connect or discover) takes time. And time spent doing that, cannot be spent updating the screen.

In and on itself this isn’t such a big problem, as it does not hurt the functionality much. At least, for one sensor. I have like 8 sensors. Basically this means upon bootup it’ll take at least 2 minutes before anything is seen on the screen.

Then, the connection itself, once it’s established. I subscribe to a character and then periodically check the valueupdated() value. This works fine.

For now the only ‘solution’ I have, is to make it a threaded application and have BLE run in it’s own thread. Since it only needs to transfer values to the screeen, and I’m the one writing that, I can keep it thread-save using mutexes or something like that.

However, I cannot believe ArduinoBLE is this inapt. Sure if you have one device connecting to one other device, it works fine. But it seems no-one ever thougth of handling multiple devices.

So how does one correctly handle multiple devices? Is there even such a thing as ‘the correct way’?

Apparently it is not possible to use these things for reliable bluetooth…

A shame.

ArduinoBLE is NOT designed for concurrent central connections. The correct way is to offload BLE to its own thread/task, especially if you’re using a device with FreeRTOS under the hood (e.g., ESP32 or some nRF52 variants). This way, your screen/UI can run smoothly while BLE does its thing.

What use is it then? if you can only connect a single device.

However, I solved it the other way around. I put the UI task in a thread.

That way the screen stays responsive.

#include "freeRTOS\freeRTOS.h"
#include "freeRTOS\task.h"
[..]
void setup() {
  xTaskCreate(tick, "tick", 4096, NULL, 2, NULL); // keeps the GUI running
}
[..]
void tick(void *parameters)
{
    while (true) { 
        delay(5);
        lv_timer_handler(); 
    }
}