Hi,
I’ve been working for some time developing a special timer for model aircraft - it uses an onboard xiao_esp32C3 which receives a string of flight parameters to initiate a flight. This information is sent by an Android app via BLE.
I’d got it all working quite nicely with my phone - but when I tried a friend’s phone, it simply would not connect. The ESP would seem to pair, but the app was unable to find it when scanning.
I then had problems connecting with my phone - which until then had worked fine.
I’ve tried using a new ESP board, and sometimes the BLE connection works, sometimes not - I haven’t been able to establish a pattern, but the BLE connection seems to be randomly unreliable.
Apologies for the long post - any advice would be most welcome., thanks.
Hi there,
And Welcome Here…
Pretty good application for a BLE connection. Have you considered testing with the Nrf Connect for Desktops and a ($9) BLE dongle?
Great for that type of Diagnosis and many other applications , Like a BLE sniffer in Wireshark etc.
What mobile phones are we talking about? Not all support BLE , most are BT (classic) You can post the code or some snipt’s using the Code tags " </> " above , just paste it in there. makes it easy to read and you’ll get better quality help as well.
There are lots of BLE examples here so I encourage a look at those also. The C3 is slightly different in it’s interiors than the rest of the ESP line , so be aware.
Seems like the same application would benefit from an onboard IMU also like the Nrf52840 Sense Xiao. What is the data if I may ask, unless of course it is all proprietary.
HTH
GL PJ
Thanks for the swift response and suggestions. This widget is intended for use in small free flight (no radio control) model aircraft, and needs to be as small and light as possible, hence my choice of the C3. I will certainly look into nrf Connect, thanks. The data sent is just a stream of digits which are then sorted by the C3 into an array, defining the flight parameters and motor power setting. All that code is working fine - it’s just this intermittent connectivity that’s an issue. The Android app was written at MIT App inventor, following their examples, and mostly work ok on my Redmi Note (and others), but seems to fail on a Samsung Galaxy.
I’ve read that the C3 keeps a list of connected devices? Wondering if it’s possible to flush this - or something to restore the board to factory defaults.
Thanks again…
Hi there,
Sure thing, Yes I use MITAI 2 also with an app I built for control of a BLE locking device.(patent # US20230314907A1) using the Nrf52840 for battery life/power. There is a RTOS on the chip that will enter low power and may drop the connection for example if the code is not setup properly.
try rolling back to an older BSP first and retest.
then here are some things to consider…
- The ESP-IDF-based Arduino core (used on ESP32-C3) runs BLE on a separate task. rollback suggestion
- If user code (e.g. delay-heavy loops or blocking logic) runs on
loop()
or the main task and prevents BLE event handling, the stack gets starved. - Symptoms:
- BLE doesn’t advertise consistently
- BLE stops responding after a period
- Pairing succeeds but no discovery
Fix: Use non-blocking logic, or call
delay(0)
regularly to yield control, or run BLE in its own task (viaxTaskCreatePinnedToCore()
).
- If the ESP32C3 BLE server advertises once and doesn’t restart advertising after disconnect, it won’t be discoverable to new phones.
- Android can cache services, so sometimes you need to clear Bluetooth cache or reboot the phone.
BLEDevice::startAdvertising(); // Call this again on disconnect
From my experience, some will Argue with it , but for everything after it’s trash. If you want max stability for BLE on Xiao ESP32-C3:
- Use ESP32 Arduino Core v2.0.7 or v2.0.8
- Avoid ESP32 core v2.0.10 — known BLE issues
- Avoid Serial prints inside BLE callbacks
- Restart advertising after every disconnect
- Minimize blocking code in
loop()
HTH
GL PJ
also take a CLOSE look at the UUID’s and there Android friendliness…
NO serial prints in the Callbacks, will hang it…
Peripheral + Android Compatibility
- BLE scan on Android is filtered by service UUID, device name, or address type.
- If your Android app expects a service UUID but ESP isn’t advertising it properly — it’s invisible.
pAdvertising->addServiceUUID(myServiceUUID);
Many thanks for that extensive response! There’s a lot to think about there, will be looking into it. Thanks again…
Different Android phones have different BLE behavior, especially with background scanning and bonding.
Test with nRF Connect app (from Nordic) to verify if the ESP is discoverable and connectable.
If your device pairs but does not advertise properly, avoid pairing unless needed. Most BLE apps don’t need bonding/pairing.
More helpful advice, many thanks…
Few cents from my side:
I tried ESP32-C3 BLE with Arduino libraries (both BLE Device & Nimble). What I can say for sure is that I always was able to see the device advertising. Sometimes there was an issue pairing with the chip (I’ve only tried Windows PC), because Windows not always was able to pop-up the window to enter the security code (as I’ve incorporated some BLE security - authorization). But other than that no issues with the chip.
It is indeed possible to flush the paired/bonded devices list. Unfortunately, can’t tell for sure what is the command now, as it was long time ago.
Few remarks: Nimble is a lightweight library, so If you want to save some space on the device, I would suggest it.
I second PJ, EPS32-C3 is not a battery friendly chip, but if you don’t experience shortage on battery for your particular needs, I wouldn’t bother moving to another chip, like nrf52840. Especially, if it is just a hobby project. However, with the nrf52840 the consumption is 10 times less.
Just a quick update to say that I appear to have fixed this, with a little help from the Gemini AI. My code now monitors the BLE connection and, in the event of disconnection, restarts advertising. This has provided an almost bomb proof connection - although my friends Samsung has to be reset if some hours have elapsed since it last connected. Am assuming that this is a phone-specific issue. Thanks again al for your help…now on to the next stumbling block!
Hi David , I am trying now for weeks to get ESP32C3 with BLE in contact with my XCTrack app. I tried with de NIMBLE Library in Arduino and the NIMBLE Server example. Can you send me your .ino file to check, whats wrong with my software?
Regards Henry
Hi, welcome to the frustrating world of BLE… I had a lot of help from Google Gemini AI, and eventually got it working ok - but had switched to a C3 Supermini. However, afaik, the same code should work ok on the Xiao. I think that library selection is the key, I am not using the NIMBLE library. I’ve sent a stripped out version of my ino, leaving just the essential BLE code. I have compiled this sketch ok, and added (in the sketch) an edited copy of the output during compilation, showing the libraries.
I hope that’s of help…, good luck!
// USE THE TOOLS MENU TO SELECT
// board ESP32 C3 SUPERMINI
// IDE board: ESP32C Dev Module
// Libraries Expressif
// programmer AVRmk2
// USB ON CDC ENABLED
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <BLEAdvertising.h> // v10 gemini
//BLE comms
String rcvdstring;
String rcvdcopy;
String report = "STOPPED"; // used to reply to phone
String widgetStatus = "STOPPED" ; // first phase of a flight
boolean datarcvd = false;
bool deviceConnected = false; // Flag to track connection status
// BLE stuff
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
// 4fafc201-1fb5-459e-8fcc-c5c9c331914b SEEED
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
// beb5483e-36e1-4688-b7f5-ea07361b26a8 SEEED
BLEServer* pServer = nullptr; // Declare pServer globally so we can access it in callbacks
BLEAdvertising* pAdvertising = nullptr; // Declare pAdvertising globally
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
deviceConnected = true;
};
void onDisconnect(BLEServer* pServer) {
deviceConnected = false;
pAdvertising->start(); // Restart advertising on disconnection
}
};
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string value = pCharacteristic->getValue().c_str(); //gemini v10
pCharacteristic->setValue(report.c_str()); // reply to phone
if (value.length() > 0) {
rcvdstring = "";
for (int i = 0; i < value.length(); i++) {
// Serial.print(value[i]); //
rcvdstring = rcvdstring + value[i];
}
datarcvd = true;
report=""; //
}
}
};
//end of gemini code copied over
/////////////////////////////////// SETUP ///////////////////////////
void setup() {
// BLE stuff
// gemini code onwards
BLEDevice::init("MyBLE_DEvice");
pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks()); // Set the server callbacks
BLEService *pService = pServer->createService(SERVICE_UUID);
BLECharacteristic *pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE
);
pCharacteristic->setCallbacks(new MyCallbacks());
pCharacteristic->setValue("Profiler connected!");
pService->start();
pAdvertising = pServer->getAdvertising();
pAdvertising->start();
// end of gemini code
} // end of setup
// ************** MAIN LOOP *******************
void loop() {
if (datarcvd) { // had a msg from the phone
// checkMessage(); // msg rcvd from phone via BLE - this will also set the reply as variable 'report'
}
// PUT YOUR CODE HERE TO DEAL WITH THE INCOMING MSG
} // end of main loop
//////////////////////////////////////////////////////////////////
/*
Compilation output
Using board 'esp32c3' from platform in folder: C:\Users\Dave\AppData\Local\Arduino15\packages\esp32\hardware\esp32\3.2.0
Using core 'esp32' from platform in folder: C:\Users\Dave\AppData\Local\Arduino15\packages\esp32\hardware\esp32\3.2.0
Detecting libraries used...
C:\Users\Dave\AppData\Local\arduino\sketches\0E7F874EB7DA0967668CB84A920D6DD8/ESP32C3_BLE.ino.merged.bin, ready to flash to offset 0x0
Multiple libraries were found for "BLEDevice.h"
Used: C:\Users\Dave\AppData\Local\Arduino15\packages\esp32\hardware\esp32\3.2.0\libraries\BLE
Not used: C:\Users\Dave\Documents\Personal\Electronics\Arduino\Sketches\libraries\ArduinoBLE
Using library BLE at version 3.2.0 in folder: C:\Users\Dave\AppData\Local\Arduino15\packages\esp32\hardware\esp32\3.2.0\libraries\BLE
*/
Hi there,
Nice job and great documenting in the code, SLICK
I know it will help
GL PJ
that C3 has body slammed a lot of beginners and tripped even the experienced with SPI , BLE , etc. small and slight differences, Thanks espresso
I hope that it is of help, took me quite a while to get here… btw, the main variable to deal with is ‘report’ - have your code set this to the reply when the phone sends a message and you should see it on your device (phone/whatever).