Failed Attribute Discovery on 3 different Boards. Success On One

Hello!

My code is meant to connect to a bluetooth die and read what it has rolled. I originally was using an Arduino Uno Wifi Rev2 and it works perfectly. However, I would like to swap which microcontroller I am using for this project. This is where things go wrong.

The same problem occurs for all of my other three Arduinos:
Arduino Uno R4 Wifi
Arduino Nano 33 BLE Rev2
Arduino Nano 33 BLE Sense Rev2

The code uploads fine to the boards, and they manage to connect to the peripheral, but when they go to discover attributes, they fail and get stuck in "Attribute discovery failed! Trying again...". This does not happen with my Arduino Uno Wifi Rev2.

What's going on?

#include <ArduinoBLE.h>

void setup() {
  Serial.begin(9600);
  while (!Serial);

  // begin initialization
  if (!BLE.begin()) {
    Serial.println("starting Bluetooth® Low Energy module failed!");

    while (1);
  }

  Serial.println("Bluetooth® Low Energy Central - MRGD Die");

  // start scanning for peripherals
  BLE.scanForName("MRGD");
}

void loop() {
  // check if a peripheral has been discovered
  BLEDevice peripheral = BLE.available();

  if (peripheral) {

    if (peripheral.localName() == "MRGD") {
      // stop scanning
      BLE.stopScan();

      connectToPeripheral(peripheral);

    }
  }
}

void connectToPeripheral(BLEDevice peripheral) {
  // connect to the peripheral
  Serial.println("Connecting ...");

  if (peripheral.connect()) {
    Serial.println("Connected");
    discoverAttributes(peripheral);
  } else {
    Serial.println("Failed to connect! Trying again...");
    connectToPeripheral(peripheral);
    return;
  }

}

void discoverAttributes(BLEDevice peripheral) {
  Serial.println("Discovering attributes ...");
  if (peripheral.discoverAttributes()) {
    Serial.println("Attributes discovered");
    discoverService(peripheral);
  } else {
    Serial.println("Attribute discovery failed! Trying again...");
    discoverAttributes(peripheral);
    return;
  }
}

void discoverService(BLEDevice peripheral) {
  BLEService rollStateService = peripheral.service(2);

  if(rollStateService) {
    Serial.println("Service discovered");
    discoverCharacteristic(peripheral, rollStateService);
  } else {
    Serial.println("Failed to find Service!");
    discoverService(peripheral);
    return;
  }
}

void discoverCharacteristic(BLEDevice peripheral, BLEService rollStateService) {
  BLECharacteristic rollStateCharacteristic = rollStateService.characteristic(1);
  if(rollStateCharacteristic) {
    Serial.println("Characteristic discovered");
    rollStateCharacteristic.subscribe();
    while (peripheral.connected()) {
      if (rollStateCharacteristic.valueUpdated()) {
        byte value[] = {0, 0, 0};
        rollStateCharacteristic.readValue(value, 3);
        if(value[0] == 3 && value[1] == 1) {
          Serial.println(value[2] + 1);
        }
      }
    }
  } else {
    Serial.println("Failed to find Characteristic!");
    discoverCharacteristic(peripheral, rollStateService);
    return;
  }
}

Check up the ArduinoBLE.h library and read which core units it's written for.

I looked into it and I found this:

Enables Bluetooth® Low Energy connectivity on the Arduino MKR WiFi 1010, Arduino UNO WiFi Rev2, Arduino Nano 33 IoT, Arduino Nano 33 BLE, Arduino Portenta H7, Arduino Giga R1 and Arduino UNO R4 WiFi.

Are you saying that because my Arduino Nano 33 BLE Rev 2 and Arduino Nano 33 BLE Sense Rev 2 are Rev 2's that the library doesn't work for them? What would I use instead?

It also doesn't explain why it wouldn't work on my Arduino UNO R4 WiFi.

If you use a phone app like LightBlue or nrfConnect can you discover the attributes of the bluetooth die.

The same problem occurs for all of my other three Arduinos:
Arduino Uno R4 Wifi
Arduino Nano 33 BLE Rev2
Arduino Nano 33 BLE Sense Rev2

All these boards use a different ble chip than the Uno WIFI rev2.

Do you have any documentation on the bluetooth dice?

Yes, it's a Game with Pixels die and it's open source.

I know what attributes to look at and write to, but if my boards aren't detecting them, I'm not sure what to do.

I don't understand the issues with the attribute discovery and the different platforms.

However, per the communication protocol the information you need to read from the die is in the ManufacturerData field of the advertisement. You should be able to read that without the attributes discovery.

I don't know if you need to read and write to the characteristic, and if so, I don't know how to do that without the attribute discovery.

See what you can find what you need with this.

#include <ArduinoBLE.h>

uint8_t dieManufacturerData[24] = {};

void setup() {
  delay(2500);
  Serial.begin(9600);
  Serial.println("Serial Enabled");

  if (!BLE.begin()) {
    Serial.println("starting BLE module failed!");
    while (1);
  }
  Serial.println("BLE Central for PixelDie");
  BLE.scanForName("MRGD");
}

void loop() {
  BLEDevice peripheral = BLE.available();
  if (peripheral) {
    BLE.stopScan();
    Serial.print("MRGD Found @ ");
    Serial.print(peripheral.address());
    Serial.println();
    if (peripheral.hasManufacturerData()) {
      peripheral.manufacturerData(dieManufacturerData, 24);  //probeManufacturerData is the 24 byte data array the data will get copied into by the function.
      Serial.println("Die Data Found");
      printData(dieManufacturerData, 24);
      Serial.println();
    }
    BLE.scanForName("MRGD");
  }
  delay(1000);
}

void printData(uint8_t data[], int length) {
  for (int i = 0; i < length; i++) {
    uint8_t b = data[i];

    if (b < 16) {
      Serial.print("0");
    }

    Serial.print(b, HEX);
    Serial.print(' ');
  }

  Serial.println();
}

Interesting! I can use the manufacturer data to access the current face and roll state from the advertisement rather than having to connect. In a lot of ways this might be better than permanently connecting to the die, although it does mean I can't write to the LEDs.

I never would have thought of that possibility, thanks!