I’m trying to build a robust peripheral in a nano 33 BLE that can survive a loss of connectivity to the central, and can subsequently reconnect, in the style of many commercially available Bluetooth products. Using any of the Arduino example sketches - eg LED, I find that when the central is connected, and moves out of Bluetooth range of the peripheral, and then returns, it is not possible to reconnect. I have tried a number of different iOS central applications - either nRF Connect, LightBlue, or my own iOS app. All of these notify and drop the session and survive the session loss when they move too far away. They are ready to reconnect either immediately or when their scan finds the Arduino BLE advertising again. The nano 33 is neither accepting connections nor advertising again. The central will find it again after it is rebooted, but I would prefer a less drastic solution. Inside the peripheral code, I note that central.connected() remains TRUE after the loss of connection, so the program remains in its loop waiting for requests. I have done lots of google searches and find no guidelines or examples of how to code recovery from session loss using the ArduinoBLE library. I would have thought when the connection is lost, central.connected() would return FALSE or BLE.central() would be nil to indicate session loss. Neither of these occurs within many minutes after the session is lost. If central.connection() would return FALSE, then the sample program might just work as provided, or perhaps with the addition of a BLE.advertise() call after the session loss.
So is this a bug? Or am I supposed to detect the situation and call central.disconnect() or BLE.disconnect()? I have tried various combinations of such actions without success.
I even tried BLE.end(), but this causes a subsequent BLE.begin() to fail.
I am surprised that I could not find on the forum or elsewhere any discussion of recovering lost connections. Isn’t that a pretty common requirement for Bluetooth sessions?
I’m using Arduino IDE 1.8.10; macOS 10.14.6; Arduino Nano 33 BLE; ArduinoBLE 1.1.1;
The code I’m using is the the LED example from the ArduinoBLE library.
I have been experiencing the disconnect problem discussed in this thread and have been following issue #33 on Github, which appears to have be resolved in December. I am still experiencing a problem where the peripheral cannot reconnect after loosing connection as a result of being out of range from my Arduino nano 33 BLE.
I just tried running the Battery Level example again and I'm still experiencing the problem using that sketch. I have been using an iPad running LightBlue to test this.
Has the solution been incorporated in the BLEArduino library, do I need to do a pull from Github, or is there some other change I need to make?
I have a simple test program which I used on the Arduino Nano 33 IoT and Nano 33 BLE.
The behavior for them is different. I guess they both use the same BLE library but there might be differences in the integration with mbedOS on the Nano 33 BLE.
The Arduino Nano 33 BLE does not set the central.connected correctly when the connection is lost. It returns central.rssi() = 0 a couple of times when the connection is about to get lost. But it can recover from that when the connection gets better. But when the connection is lost it cannot recover without reset.
The Arduino Nano 33 IoT does set central.connected correctly so the sketch can get back to a state where it waits for connections. The central.rssi never gets to 0, but gets to some maximum negative value around -128 or so as expected.
The latest library for the Nano 33 BLE still has this bug. When the bluetooth connection is lost, the Nano can't be reconnected without a reset. Does anyone have a reliable work-around? Thank you.
I am also struggling with this issue and find out that watchdog seems to be a reliable workaround.
I am using following setup which sets the watchdog to 120s. Once the central is connected, it restarts the timer and 120s later the system resets. I have very short sessions and this kind of setup works for me but if you need a longer session, I would suggest implementing some kind of a central initiated heartbeat or ping-pong message to manage the watchdog.
You can put additional resets where needed, especially if you are initiating a longer action by BT. In my case it is plant watering function which makes sure that the system will not reboot during watering.
bool shouldResetWDTOnConnection = true;
(...)
void setup() {
enableWDT();
resetWDT();
// rest of the setup
resetWDT();
}
void loop() {
BLEDevice central = BLE.central();
if (central && central.connected()) {
if (shouldResetWDTOnConnection) {
shouldResetWDTOnConnection = false;
resetWDT();
}
// rest of the logic when connected
}
}
void enableWDT() {
//Configure WDT on nRF52840.
NRF_WDT->CONFIG = 0x01; // Configure WDT to run when CPU is asleep
NRF_WDT->CRV = 3932159; // Timeout set to 120 seconds, timeout[s] = (CRV-1)/32768
NRF_WDT->RREN = 0x01; // Enable the RR[0] reload register
NRF_WDT->TASKS_START = 1; // Start WDT
}
void resetWDT() {
// Reload the WDTs RR[0] reload register
NRF_WDT->RR[0] = WDT_RR_RR_Reload;
}