arduino-libraries / ArduinoBLE

ArduinoBLE library for Arduino
GNU Lesser General Public License v2.1
309 stars 205 forks source link

nano33ble boards seem to ignore scan() without duplicates #124

Closed iactiva closed 3 years ago

iactiva commented 3 years ago

I'm porting a code already working on a Arduino MKR WiFi 1010 board to a new Arduino Nano 33 BLE board and noticed BLE.scan() seem to be working 'withDuplicates' and it goes crazy returning multiple times the same devices. The I went to the samples/Central/Scan/Scan.ino and the sample code as is is also ignoring the default no duplites option. I've also tried BLE.scan(false) w/o success. I'm using board mbed 1.3.0 (tried 1.1.6 too) and ArduinoBLE 1.1.3. BTW I've tried two different Nano33ble boards with the same issues. Any idea on what may be wrong here? Many thanks!

giulcioffi commented 3 years ago

Hi @iactiva, I tried to simulate your issue with example Scan.ino and the library and core version that you mentioned, but everything seems to work fine on my side. Duplication happens only with BLE.scan(true), while it doesn't happen with BLE.scan() and BLE.scan(false). Are you sure that you didn't modify any other thing in the sketch/library? If you still have this issue, you could post your own sketch here. Thanks!

polldo commented 3 years ago

Hi @iactiva, you might also consider adding scan filters https://github.com/arduino-libraries/ArduinoBLE/blob/master/src/utility/GAP.h#L42-L44

iactiva commented 3 years ago

Here is the example code Central/scan/scan.ino. It is actually ignoring also BLE.scan(false) and showing duplicates. Don't know why, but it is the same in both the new 33ble boards I've just purchased.

BN: Arduino Nano 33 BLE VID: 2341 PID: 805a

/*
  Scan

  This example scans for BLE peripherals and prints out their advertising details:
  address, local name, adverised service UUID's.

  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.

  This example code is in the public domain.
*/

#include <ArduinoBLE.h>

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

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

    while (1);
  }

  Serial.println("BLE Central scan");

  // start scanning for peripheral
  BLE.scan();
}

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

  if (peripheral) {
    // discovered a peripheral
    Serial.println("Discovered a peripheral");
    Serial.println("-----------------------");

    // print address
    Serial.print("Address: ");
    Serial.println(peripheral.address());

    // print the local name, if present
    if (peripheral.hasLocalName()) {
      Serial.print("Local Name: ");
      Serial.println(peripheral.localName());
    }

    // print the advertised service UUIDs, if present
    if (peripheral.hasAdvertisedServiceUuid()) {
      Serial.print("Service UUIDs: ");
      for (int i = 0; i < peripheral.advertisedServiceUuidCount(); i++) {
        Serial.print(peripheral.advertisedServiceUuid(i));
        Serial.print(" ");
      }
      Serial.println();
    }

    // print the RSSI
    Serial.print("RSSI: ");
    Serial.println(peripheral.rssi());

    Serial.println();
  }
}

And here is the serial output:

BLE Central scan
Discovered a peripheral
-----------------------
Address: 90:dd:5d:d2:eb:2d
RSSI: -85

Discovered a peripheral
-----------------------
Address: 07:28:78:a0:76:7a
RSSI: -85

Discovered a peripheral
-----------------------
Address: 76:f7:b4:50:b2:e5
RSSI: -52

Discovered a peripheral
-----------------------
Address: 40:71:79:fb:5e:b9
RSSI: -81

Discovered a peripheral
-----------------------
Address: cb:f5:16:6e:18:d6
Local Name: MI Band 2
Service UUIDs: fee0 
RSSI: -67

Discovered a peripheral
-----------------------
Address: 64:61:bd:e5:a7:8f
RSSI: -54

Discovered a peripheral
-----------------------
Address: cb:f5:16:6e:18:d6
Local Name: MI Band 2
Service UUIDs: fee0 
RSSI: -67

Discovered a peripheral
-----------------------
Address: 90:dd:5d:d2:eb:2d
RSSI: -83

Discovered a peripheral
-----------------------
Address: 76:f7:b4:50:b2:e5
RSSI: -56

Discovered a peripheral
-----------------------
Address: 07:28:78:a0:76:7a
RSSI: -80

Discovered a peripheral
-----------------------
Address: cb:f5:16:6e:18:d6
Local Name: MI Band 2
Service UUIDs: fee0 
RSSI: -68

Discovered a peripheral
-----------------------
Address: 76:f7:b4:50:b2:e5
RSSI: -52
iactiva commented 3 years ago

@Polldo Just confirmed using BLE.scanForName("My Device") in previous example also returns duplicates.

BTW the library is working perfectly in my MRK1010 boards. Maybe something has changed in newest BLE33 boards?

giulcioffi commented 3 years ago

Hi @iactiva, could you please provide us the serial output with BLE.scan(false) and BLE.scan(true), showing also the timestamp? On my side, I notice a certain difference in these two cases. Thanks!

polldo commented 3 years ago

Hi @iactiva , thanks for your feedback. Can you try this issue with this version of the core? I've made a change to address your problem

Explanation of the change I've done: The nano33ble is using the mbed CORDIO controller for handling the ble radio. This controller handles a filter buffer of 8 elements, so if more than 8 devices closed to your central are advertising, then it's probable that you will receive duplicated advertising reports. This is because the filter cannot filter more than 8 devices at the same time. (ref. here and here) So I've simply increased the size of the filter buffer from 8 to 16. It could still be not enough for your case, but let's try it.

iactiva commented 3 years ago

@Polldo Many thanks! That worked. In fact I can have over 40 devices nearby here...

What exactly you have modified? I'd like to implement (join) this ble-adv-filter into ble-multiconnection in order to connect up to 8 devices at the same time.

@giulcioffi Do you still need serial outputs?

Thank you so much for the nice support

giulcioffi commented 3 years ago

Not needed anymore @iactiva, thanks. The only change has been to increase the size of the buffer of the scanned peripherals. In the master branch the actual buffer size is 8. If you have more than 8 devices in the nearby, when the 9th one advertises the central device, a device already saved in the buffer will be removed. When this "removed" peripheral advertises again the central device, it is seen as a "new" device. By increasing the buffer size we move the problem to a higher number of devices. If in the nearby you have less number of devices than the buffer size, you will not see duplicates.

iactiva commented 3 years ago

hmmm... just checked LL_NUM_ADV_FILT is still =8 in cfg_mac_ble.h (here)

Yeah, tested again with over 16 reachable peripherals. I confirm it gets duplicates again, so I'll have to increase that filter buffer to 32 or even more.

iactiva commented 3 years ago

I'm a bit stuck on compiling mbed by using the provided script mbed-os-to-arduino.

_./mbed-os-to-arduino -c ARDUINO_NANO33BLE:ARDUINONANO33BLE Funtion generate_libs () is breaking since files GCC_ARM/.link_options.txt and GCC_ARM/.link_script.ld do not exist in BUILD folder. May them should be created during process?