Title: Nano 33 BLE: BLE.connected() Stuck True After Disconnect with ArduinoBLE Library

Hi everyone,

I’ve been troubleshooting a BLE issue with my Nano 33 BLE boards using the ArduinoBLE library, and I’m hoping someone can help me confirm if this is a bug or suggest a workaround. I’ve got a client/server setup where one Nano 33 BLE acts as a central (N33S) and another as a peripheral (N33C). The system works for a few connections, but then the peripheral gets stuck reporting BLE.connected() as true, even after the central disconnects, blocking further reliable cycles.

Setup:

  • Boards: Two Nano 33 BLEs (bought from the Arduino Store).

  • Library: ArduinoBLE (version [insert version from Library Manager, e.g., 1.3.6]).

  • IDE: Arduino IDE 2.3.2 (as of Feb 20, 2025).

  • Code: Full N33C (peripheral) and N33S (central) sketches below.

What Happens:

  • N33S connects to N33C, sends "Hello from N33S", and disconnects successfully for multiple cycles (up to 13+ in one run).

  • After each disconnect, N33C’s bleDisconnectHandler fires ("Central disconnected"), and it restarts advertising.

  • However, N33C then reports "Still connected - waiting for disconnect" repeatedly because BLE.connected() stays true, even though N33S has disconnected.

  • I’ve tried BLE.stopAdvertise()/BLE.advertise() and even BLE.end()/BLE.begin() to reset the stack, but BLE.connected() remains stuck. Oddly, N33S can still connect and send messages despite this state.

  • This lag between connections (20-30s due to resets) is too slow for my application, which needs faster cycles.

Serial Output (N33C):
Here’s a trimmed log showing the pattern:

Restarted advertising
[... repeated ...]
Message received from central: e1:07:2e:f2:f5:cf
Hello from N33S
Central disconnected
Advertising restarted after disconnect
Still connected - waiting for disconnect
[... repeated ...]
Connection stuck too long - resetting BLE stack
BLE stack reset and advertising restarted
Still connected - waiting for disconnect
[... repeated ...]
Message received from central: e1:07:2e:f2:f5:cf
Hello from N33S
Central disconnected
Advertising restarted after disconnect
Still connected - waiting for disconnect

Full output attached if needed.

Code:
N33C (Peripheral):

cpp

#include <ArduinoBLE.h>

void messageReceived(BLEDevice central, BLECharacteristic characteristic);
void bleDisconnectHandler(BLEDevice central);

BLEService messageService("19B10000-E8F2-537E-4F6C-D104768A1214");
BLECharacteristic messageCharacteristic("19B10001-E8F2-537E-4F6C-D104768A1214", 
                                       BLERead | BLEWrite, 
                                       20);

void setup() {
  Serial.begin(115200);
  if (!BLE.begin()) {
    Serial.println("Starting BLE failed!");
    while (1);
  }
  BLE.setLocalName("N33C");
  BLE.setAdvertisedService(messageService);
  messageService.addCharacteristic(messageCharacteristic);
  BLE.addService(messageService);
  messageCharacteristic.setEventHandler(BLEWritten, messageReceived);
  BLE.setEventHandler(BLEDisconnected, bleDisconnectHandler);
  BLE.setAdvertisingInterval(100);
  BLE.advertise();
  Serial.println("BLE Peripheral - N33C ready");
}

void messageReceived(BLEDevice central, BLECharacteristic characteristic) {
  Serial.print("Message received from central: ");
  Serial.println(central.address());
  uint8_t buffer[20];
  int length = messageCharacteristic.valueLength();
  messageCharacteristic.readValue(buffer, length);
  for (int i = 0; i < length; i++) {
    Serial.write(buffer[i]);
  }
  Serial.println();
}

void bleDisconnectHandler(BLEDevice central) {
  Serial.println("Central disconnected");
  BLE.stopAdvertise();
  BLE.advertise();
  Serial.println("Advertising restarted after disconnect");
}

void loop() {
  BLE.poll();
  static unsigned long lastCheck = 0;
  static unsigned long lastMessage = 0;
  static bool wasConnected = false;
  if (millis() - lastCheck > 5000) {
    if (BLE.connected()) {
      if (!wasConnected) {
        Serial.println("Still connected - waiting for disconnect");
        wasConnected = true;
      }
    } else {
      if (wasConnected) {
        Serial.println("Connection cleared");
        wasConnected = false;
      }
      BLE.stopAdvertise();
      BLE.advertise();
      Serial.println("Restarted advertising");
    }
    if (lastMessage && (millis() - lastMessage > 60000)) {
      Serial.println("No messages for 60s - resetting BLE stack");
      BLE.end();
      delay(1000);
      if (!BLE.begin()) {
        Serial.println("BLE restart failed - halting");
        while (1);
      }
      BLE.setLocalName("N33C");
      BLE.setAdvertisedService(messageService);
      messageService.addCharacteristic(messageCharacteristic);
      BLE.addService(messageService);
      messageCharacteristic.setEventHandler(BLEWritten, messageReceived);
      BLE.setEventHandler(BLEDisconnected, bleDisconnectHandler);
      BLE.setAdvertisingInterval(100);
      BLE.advertise();
      Serial.println("BLE stack reset and advertising restarted");
      lastMessage = 0;
    }
    lastCheck = millis();
  }
  if (messageCharacteristic.written()) {
    lastMessage = millis();
  }
}

N33S (Central):

cpp

#include <ArduinoBLE.h>

bool connectAndSendMessage();

void setup() {
  Serial.begin(115200);
  if (!BLE.begin()) {
    Serial.println("Starting BLE failed!");
    while (1);
  }
  Serial.println("BLE Central - N33S ready");
}

bool connectAndSendMessage() {
  Serial.println("Preparing to scan for N33C...");
  delay(2000);
  Serial.println("Scanning for N33C...");
  BLE.stopScan();
  BLE.scanForName("N33C", true);
  BLEDevice peripheral;
  unsigned long startTime = millis();
  while (!peripheral && (millis() - startTime < 15000)) {
    peripheral = BLE.available();
    delay(200);
  }
  if (!peripheral) {
    Serial.println("Failed to find N33C peripheral after 15 seconds");
    BLE.stopScan();
    return false;
  }
  Serial.print("Peripheral address: ");
  Serial.println(peripheral.address());
  BLE.stopScan();
  int connectAttempts = 0;
  while (!peripheral.connect() && connectAttempts < 3) {
    Serial.println("Connection attempt failed. Retrying...");
    delay(1000);
    connectAttempts++;
  }
  if (!peripheral.connected()) {
    Serial.println("Failed to connect to N33C after 3 attempts");
    return false;
  }
  Serial.println("Connected to N33C");
  if (!peripheral.discoverAttributes()) {
    Serial.println("Attribute discovery failed");
    peripheral.disconnect();
    return false;
  }
  Serial.println("Attributes discovered");
  BLECharacteristic messageChar = peripheral.characteristic("19B10001-E8F2-537E-4F6C-D104768A1214");
  if (!messageChar) {
    Serial.println("Failed to find message characteristic");
    peripheral.disconnect();
    return false;
  }
  Serial.println("Message characteristic found");
  if (!messageChar.canWrite()) {
    Serial.println("Characteristic not writable");
    peripheral.disconnect();
    return false;
  }
  Serial.println("Characteristic is writable");
  const char* message = "Hello from N33S";
  if (!messageChar.writeValue(message, strlen(message))) {
    Serial.println("Failed to send message");
    peripheral.disconnect();
    return false;
  }
  Serial.println("Message sent successfully");
  peripheral.disconnect();
  unsigned long disconnectStart = millis();
  while (peripheral.connected() && (millis() - disconnectStart < 5000)) {
    delay(100);
  }
  if (peripheral.connected()) {
    Serial.println("Warning: Disconnect timed out");
    BLE.stopScan();
  } else {
    Serial.println("Disconnected from N33C");
  }
  return true;
}

void loop() {
  if (connectAndSendMessage()) {
    Serial.println("Communication successful");
  } else {
    Serial.println("Communication failed");
  }
  BLE.stopScan();
  delay(20000);
}

Questions:

  1. Is this a known bug with BLE.connected() in the ArduinoBLE library on Nano 33 BLE?

  2. Could it be an nRF52840 firmware issue? How can I check the firmware version on my boards?

  3. Any workarounds to ensure reliable disconnects and faster reconnection cycles (my app needs <20s intervals)?

  4. Has anyone else seen this behavior with repeated BLE connect/disconnect cycles?

I’m happy to share more logs or test suggestions. Thanks in advance for any insights—this has been a tough one to crack!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.