Can't Add Descriptors to BLECharacteristic with Nano 33 BLE

Hello,

I'm writing some bluetooth application using the Nano 33 BLE. I was trying to use the addDescriptor method as described in the ArduinoBLE documentation but I'm finding that the descriptor isn't actually being added.

I found an example on stack overflow where a user posted their code and a screenshot from a scanner like nRF connect showing the descriptors. Example

I copied this code and am still not finding the descriptors. Here is the code in question.

#include <ArduinoBLE.h>

BLEService echoService("00000000-0000-1000-8000-00805f9b34fb");
BLEStringCharacteristic charac ("741c12b9-e13c-4992-8a5e-fce46dec0bff", BLERead | BLEWrite | BLENotify,40);
BLEDescriptor Descriptor("beca6057-955c-4f8a-e1e3-56a1633f04b1","Descriptor");
String var = "";


void setup() {
  // put your setup code here, to run once:
 Serial.begin(9600);
  while(!Serial);

  if(!BLE.begin()){
    Serial.println("starting BLE failed.");
    while(1);
  }

  
  BLE.setLocalName("Arduino BLE Echo");
  BLE.setAdvertisedService(echoService);
  charac.addDescriptor(Descriptor);
  echoService.addCharacteristic(charac);
  BLE.addService(echoService);
  BLE.advertise();

  Serial.print("Descriptor Count: ");
  Serial.println(charac.descriptorCount());
  
  Serial.println("Bluetooth device active, waiting for connections...");
  Serial.println(" ");
}

void loop() {
  // put your main code here, to run repeatedly:

}

I'm outputting the number of descriptors and that's coming back as zero. Connecting to the device in nRF connect shows the expected service/characteristic, but no descriptors. I've verified this with 2 different BLE scanner apps and with my iOS app.

I'm really unsure what I'm doing wrong. Hopefully someone can point me in a direction.

Thanks

I've done some more investigating via my iOS app and it seems as though the descriptor is discovered, but its value is null.

When I add your descriptor to the library example "Battery Level" I can see the descriptor in nrfConnect with the value of "Descriptor", so I think the issue may be with your sketch.

/*
  Battery Monitor

  This example creates a Bluetooth® Low Energy peripheral with the standard battery service and
  level characteristic. The A0 pin is used to calculate the battery level.

  The circuit:
  - Arduino MKR WiFi 1010, Arduino Uno WiFi Rev2 board, Arduino Nano 33 IoT,
    Arduino Nano 33 BLE, or Arduino Nano 33 BLE Sense board.

  You can use a generic Bluetooth® Low Energy central app, like LightBlue (iOS and Android) or
  nRF Connect (Android), to interact with the services and characteristics
  created in this sketch.

  This example code is in the public domain.
*/

#include <ArduinoBLE.h>

 // Bluetooth® Low Energy Battery Service
BLEService batteryService("180F");

// Bluetooth® Low Energy Battery Level Characteristic
BLEUnsignedCharCharacteristic batteryLevelChar("2A19",  // standard 16-bit characteristic UUID
    BLERead | BLENotify); // remote clients will be able to get notifications if this characteristic changes
BLEDescriptor Descriptor("beca6057-955c-4f8a-e1e3-56a1633f04b1","Descriptor");
int oldBatteryLevel = 0;  // last battery level reading from analog input
long previousMillis = 0;  // last time the battery level was checked, in ms

void setup() {
  Serial.begin(9600);    // initialize serial communication
  while (!Serial);

  pinMode(LED_BUILTIN, OUTPUT); // initialize the built-in LED pin to indicate when a central is connected

  // begin initialization
  if (!BLE.begin()) {
    Serial.println("starting BLE failed!");

    while (1);
  }

  /* Set a local name for the Bluetooth® Low Energy device
     This name will appear in advertising packets
     and can be used by remote devices to identify this Bluetooth® Low Energy device
     The name can be changed but maybe be truncated based on space left in advertisement packet
  */
  BLE.setLocalName("BatteryMonitor");
  BLE.setAdvertisedService(batteryService); // add the service UUID
  batteryLevelChar.addDescriptor(Descriptor);
  batteryService.addCharacteristic(batteryLevelChar); // add the battery level characteristic
  BLE.addService(batteryService); // Add the battery service
  batteryLevelChar.writeValue(oldBatteryLevel); // set initial value for this characteristic

  /* Start advertising Bluetooth® Low Energy.  It will start continuously transmitting Bluetooth® Low Energy
     advertising packets and will be visible to remote Bluetooth® Low Energy central devices
     until it receives a new connection */

  // start advertising
  BLE.advertise();
  Serial.println("Bluetooth® device active, waiting for connections...");
}

void loop() {
  // wait for a Bluetooth® Low Energy central
  BLEDevice central = BLE.central();

  // if a central is connected to the peripheral:
  if (central) {
    Serial.print("Connected to central: ");
    // print the central's BT address:
    Serial.println(central.address());
    // turn on the LED to indicate the connection:
    digitalWrite(LED_BUILTIN, HIGH);

    // check the battery level every 200ms
    // while the central is connected:
    while (central.connected()) {
      long currentMillis = millis();
      // if 200ms have passed, check the battery level:
      if (currentMillis - previousMillis >= 200) {
        previousMillis = currentMillis;
        updateBatteryLevel();
      }
    }
    // when the central disconnects, turn off the LED:
    digitalWrite(LED_BUILTIN, LOW);
    Serial.print("Disconnected from central: ");
    Serial.println(central.address());
  }
}

void updateBatteryLevel() {
  /* Read the current voltage level on the A0 analog input pin.
     This is used here to simulate the charge level of a battery.
  */
  int battery = analogRead(A0);
  int batteryLevel = map(battery, 0, 1023, 0, 100);

  if (batteryLevel != oldBatteryLevel) {      // if the battery level has changed
    Serial.print("Battery Level % is now: "); // print it
    Serial.println(batteryLevel);
    batteryLevelChar.writeValue(batteryLevel);  // and update the battery level characteristic
    oldBatteryLevel = batteryLevel;           // save the level for next comparison
  }
}

I have exactly the same issue. On iOS I can see that the descriptor is discovered with the configured UUID in my case 0x2901. But still, its value is null in terms of iOS's CBDescriptor.
I'm using ESP32 with C++

static BLEDescriptor* delayDescriptor = new BLEDescriptor((uint16_t)0x2901);
delayDescriptor->setValue("Delay");
delayDescriptor->setCallbacks(new DelayDescriptorCallbacks());
delayCharacteristic->addDescriptor(delayDescriptor);

If you still looking to setup BLE here I have a tutorial in video format to help with sending data over BLE - Adding NUS Service.

1 Like

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