Need faster scans in BLE central mode (BLEScanner sketch)


#1

Well, I’m back again trying to make it work with RedBear Duo. Same problem as before: I just can not understand why it gives so few scan results. There must be something drastically wrong somewhere, but I can’t seem to figure it out. Here’s the situation:

I’m running the BLEScanner example sketch (using Arduino IDE). I have an iBeacon sitting near the RedBear Duo. The iBeacon is set to advertise once every second. My goal is to get one scan of the iBeacon’s rssi every one second. Should be simple, right? I set the scan interval to 0x1600 (which works out to 1 second) and the scan window is also set at 0x1600.

When I upload the sketch and watch the results in the serial monitor, I’m getting scan results at VERY unreliable intervals, ranging from 2 seconds to 10 seconds or more. Completely unusable.

Anyone have any ideas???


#3

@zimbu,

I don’t work with beacons, but I think your intervals are too high ? You should set your beacons to advertise every 0.5 seconds or less, and you should use lower scan intervals and scan windows (a lot !).
Time ago I tried advertising every 1 second with my ble peripherals to keep battery drain low, and that was a Bad Thing™.

On duo I set ble.setScanParams(0, 0x0030, 0x0030);
and on peripherals I advertise every 400 ms

But, again, I don’t know much about iBeacons


#4

Hi Duffo64,

Yes, I’m also trying to keep battery from getting drained, hence 1 ad per second. At the same time, I only want one scan per second, so it seems to me that advertising 10 times per second is a waste. At least that’s my logic…which I’m not sure about at this point.

Re interval and window, my thinking is the same. Why scan every 30 milliseconds for 29 milliseconds when all I want is one scan per second? Maybe there is something I’m missing here.

Would be great if some redbear support person could address this very very fundamental issue. If the Duo can’t achieve even one scan result per second, it’s basically only useful as a very light paperweight. :wink:


#5

I am not sure about the battery drain, but I do know I stopped missing advertisements when I set the scanning to 0x30, 0x30 from .500ms. On the battery drain, won’t running the scan longer drain the battery quicker versus, short scan bursts?


#6

I’m running the Duo as central. It’s plugged in so no battery drain issue no matter how long or how often it scans. The battery issue is with the iBeacon (sending out ads) not with the Duo (scanning for ads).

The iBeacon is currently set up to send out one ad per second. If the Duo is scanning once per second (scan interval) and the scan window is one second, it should theoretically capture every single advertisement from the iBeacon. Instead, it is only getting one ad every 3-12 seconds…sometimes it even waits 20+ seconds between scans.


#7

Interesting. I do not have that issue at all as a Central and I am using heartrate wristbands and Adafruit BLE Friend devices.

Both devices advertise every second.

Here is my scanning parameters.

ble.setScanParams(1, 0x0030, 0x0030); //previous setting 0, 0x02A0, 0x02A0);

I just ran a quick test and I can scan. connect and service discovery in less than 2 seconds to 4 devices.


#8

We may be talking about two different goals. I do not want to connect to the peripheral (the iBeacon). I only want the duo to scan and receive the advertisement from the iBeacon. The advertisement includes the rssi value which is the info I need. I need this to be updated once per second.

Additionally, you mention the timing for the initial scan result. I don’t really care about that timing. But I do care about the time between each additional scan result.


#9

For the record, I just tried your settings and had no improvement. I can get a couple of scans every 3 seconds, then next one will take 10 seconds or so, then maybe 5 seconds for next, then maybe two in a row at 3 seconds each, etc. Frustrating to say the least.

Also for the record, I have checked my iBeacon’s settings, and it is in fact advertising once per second. I can also capture this ad with a different BLE module (the HM-10) very reliably. The problem with the HM-10 is that the scan window is not adjustable. It’s permanently fixed at 3 seconds. So when I use the HM-10, I can get super reliable scan results every 3 seconds. The bad news is that this is not the 1 second interval that I am after, hence my return to the Duo to see if it can be done here. So far, the answer seems to be no.

One additional point/question: I noticed you set the first parameter, Scan Type, to 1. According to the comment in the RedBear sample sketch, the choices are 0 for passive scan and 1 for active scan. But according to my knowledge of BLE, there is no such thing as an “active scan” unless perhaps a continuous connection has been established between the central device (Duo in my case) and the peripheral device (iBeacon in my case). Firstly, in my opinion, this is not a correct implementation of the beacon concept. Beacons advertise their info on a regular basis without a connection; there should be no need for a connection to be made. Secondly, if a peripheral connects with one central device, that peripheral is then no longer able to advertise its info to other central devices, thus defeating the purpose of being a Beacon: for example, in a retail store environment, the Beacon should be advertising its info to anyone passing by, NOT connecting with one of those people and ignoring all the others.


#10

As a test, I just adjusted the iBeacon to 10 ads per second. Results:

With Duo set at 0x1600 interval and 0x1600 window, I’m getting many scan results. Hard to count but should be more than one per second. This totally makes sense. 10 ads per second and a 1 second scan window and interval means that many ads are received.

With Duo set at 0x0030 interval and 0x0030 window, I’m getting slightly fewer scan results, and also the reliability is not as good, i. e. the time gap between results is not stable. This totally makes sense too since the scan window is so short, it misses some ads. I’m assuming that a 30/30 scan window is not actually continuous since there probably is some processing time wasted between the scans.

Still…makes no sense that one ad per second can not be captured reliably by the Duo.


#11

Here is the sketch I am using. It’s RedBear’s sample BLEScanner with a timer added:

#if defined(ARDUINO) 
SYSTEM_MODE(MANUAL); 
#endif

/* 
 * BLE scan parameters:
 *     - BLE_SCAN_TYPE     
 *           0x00: Passive scanning, no scan request packets shall be sent.(default)
 *           0x01: Active scanning, scan request packets may be sent.
 *           0x02 - 0xFF: Reserved for future use.
 *     - BLE_SCAN_INTERVAL: This is defined as the time interval from when the Controller started its last LE scan until it begins the subsequent LE scan.
 *           Range: 0x0004 to 0x4000
 *           Default: 0x0010 (10 ms)
 *           Time = N * 0.625 msec
 *           Time Range: 2.5 msec to 10.24 seconds
 *     - BLE_SCAN_WINDOW: The duration of the LE scan. The scan window shall be less than or equal to the scan interval.
 *           Range: 0x0004 to 0x4000
 *           Default: 0x0010 (6.25 ms)
 *           Time = N * 0.625 msec
 *           Time Range: 2.5 msec to 10240 msec
 */
#define BLE_SCAN_TYPE        0x00   // Passive scanning
#define BLE_SCAN_INTERVAL    0x1600 // 1000 ms
#define BLE_SCAN_WINDOW      0x1600 // 1000 ms

unsigned long timestamp2; //for scan result timer


void reportCallback(advertisementReport_t *report) {
  uint8_t index;

  Serial.println("reportCallback: ");
  Serial.print("The advEventType: ");
  Serial.println(report->advEventType, HEX);
  Serial.print("The peerAddrType: ");
  Serial.println(report->peerAddrType, HEX);
  Serial.print("The peerAddr: ");
  for (index = 0; index < 6; index++) {
    Serial.print(report->peerAddr[index], HEX);
    Serial.print(" ");
  }
  Serial.println(" ");

  Serial.print("The rssi: ");
  Serial.println(report->rssi, DEC);

  Serial.print("The ADV data: ");
  for (index = 0; index < report->advDataLen; index++) {
    Serial.print(report->advData[index], HEX);
    Serial.print(" ");
  }
  Serial.print("Milliseconds elapsed since last scan result: ");
  Serial.println(millis() - timestamp2); // amount of milliseconds elapsed since that line of info received
  timestamp2 = millis(); // reset the countdown timer for delay between strings received
  Serial.println(" ");
}

void setup() {
  Serial.begin(57600);
  //delay(2000);
  Serial.println("BLE scan demo.");
  timestamp2 = millis(); //"synchronize your watches!"
  
  ble.init();

  ble.onScanReportCallback(reportCallback);

  // Set scan parameters.
  ble.setScanParams(BLE_SCAN_TYPE, BLE_SCAN_INTERVAL, BLE_SCAN_WINDOW);
  
  ble.startScanning();
  Serial.println("BLE scan start.");
}

void loop() {

}

Here are a sample of the poor results I am getting with 0/1600/1600 scan settings on the Duo and 1 ad per second on the iBeacon:

`BLE scan start.
reportCallback:
The advEventType: 3
The peerAddrType: 0
The peerAddr: C F3 EE 9 3D A4
The rssi: -69
The ADV data: 2 1 6 1A FF 4C 0 2 15 2F 23 44 54 CF 6D 4A F AD F2 F4 91 1B A9 FF A6 0 0 0 1 A0 Milliseconds elapsed since last string: 12028

reportCallback:
The advEventType: 3
The peerAddrType: 0
The peerAddr: C F3 EE 9 3D A4
The rssi: -76
The ADV data: 2 1 6 1A FF 4C 0 2 15 2F 23 44 54 CF 6D 4A F AD F2 F4 91 1B A9 FF A6 0 0 0 1 A0 Milliseconds elapsed since last string: 3002

reportCallback:
The advEventType: 3
The peerAddrType: 0
The peerAddr: C F3 EE 9 3D A4
The rssi: -68
The ADV data: 2 1 6 1A FF 4C 0 2 15 2F 23 44 54 CF 6D 4A F AD F2 F4 91 1B A9 FF A6 0 0 0 1 A0 Milliseconds elapsed since last string: 32682

reportCallback:
The advEventType: 3
The peerAddrType: 0
The peerAddr: C F3 EE 9 3D A4
The rssi: -69
The ADV data: 2 1 6 1A FF 4C 0 2 15 2F 23 44 54 CF 6D 4A F AD F2 F4 91 1B A9 FF A6 0 0 0 1 A0 Milliseconds elapsed since last string: 2998

reportCallback:
The advEventType: 3
The peerAddrType: 0
The peerAddr: C F3 EE 9 3D A4
The rssi: -68
The ADV data: 2 1 6 1A FF 4C 0 2 15 2F 23 44 54 CF 6D 4A F AD F2 F4 91 1B A9 FF A6 0 0 0 1 A0 Milliseconds elapsed since last string: 6908

reportCallback:
The advEventType: 3
The peerAddrType: 0
The peerAddr: C F3 EE 9 3D A4
The rssi: -70
The ADV data: 2 1 6 1A FF 4C 0 2 15 2F 23 44 54 CF 6D 4A F AD F2 F4 91 1B A9 FF A6 0 0 0 1 A0 Milliseconds elapsed since last string: 2996

reportCallback:
The advEventType: 3
The peerAddrType: 0
The peerAddr: C F3 EE 9 3D A4
The rssi: -67
The ADV data: 2 1 6 1A FF 4C 0 2 15 2F 23 44 54 CF 6D 4A F AD F2 F4 91 1B A9 FF A6 0 0 0 1 A0 Milliseconds elapsed since last string: 6900

reportCallback:
The advEventType: 3
The peerAddrType: 0
The peerAddr: C F3 EE 9 3D A4
The rssi: -69
The ADV data: 2 1 6 1A FF 4C 0 2 15 2F 23 44 54 CF 6D 4A F AD F2 F4 91 1B A9 FF A6 0 0 0 1 A0 Milliseconds elapsed since last string: 9896

``


#12

Results with settings at 0/40/30:

Milliseconds elapsed since last scan result: 11723

Milliseconds elapsed since last scan result: 3000

Milliseconds elapsed since last scan result: 22800

Milliseconds elapsed since last scan result: 3000

Milliseconds elapsed since last scan result: 12886

Milliseconds elapsed since last scan result: 3004

Milliseconds elapsed since last scan result: 6924

Milliseconds elapsed since last scan result: 15882

Milliseconds elapsed since last scan result: 3004

I think there is a clue to the source of the problem in the too coincidental 3000-3004 millisecond results that pop up so frequently. Maybe something in the duo is getting disturbed and then it takes 3 seconds to reset??? I’ve fiddled with the settings at various numbers, but nothing seems to fix the problem.


#13

Sorry to keep spamming my own question thread, but check out this weirdness. I set the parameters at 0/0x2000/0x1900 and got these results (two suspicious numbers, roughly 6900 and 3000, keep popping up over and over again):

Milliseconds elapsed since last scan result: 8172

Milliseconds elapsed since last scan result: 5948

Milliseconds elapsed since last scan result: 3000

Milliseconds elapsed since last scan result: 6916

Milliseconds elapsed since last scan result: 2998

Milliseconds elapsed since last scan result: 22780

Milliseconds elapsed since last scan result: 2996

Milliseconds elapsed since last scan result: 6908

Milliseconds elapsed since last scan result: 2996

Milliseconds elapsed since last scan result: 6906

Milliseconds elapsed since last scan result: 2994

Milliseconds elapsed since last scan result: 6906

Milliseconds elapsed since last scan result: 2996

Milliseconds elapsed since last scan result: 6906

Milliseconds elapsed since last scan result: 2998

Milliseconds elapsed since last scan result: 6912


#14

Ah, that makes sense. I am connecting to the devices, setting up to receive notifications from them once the correct service is discovered. I used the lower scan interval and window to connect quicker.

I had to use the scan type 1 for the BLE Friends. Still scratching my head as to why on that one. I found the settings on the link below:

LE_Scan_Interval: This is defined as the time interval from when the Controller started its last LE scan until it begins the subsequent LE scan. ◦Range: 0x0004 to 0x4000
◦Default: 0x0010 (10 ms)
◦Time = N * 0.625 msec
◦Time Range: 2.5 msec to 10.24 seconds

•LE_Scan_Window: The duration of the LE scan. The scan window shall be less than or equal to the scan interval. ◦Range: 0x0004 to 0x4000
◦Default: 0x0010 (10 ms)
◦_Time = N * 0.625 msec_
◦Time Range: 2.5 msec to 10240 msec

What happens if you max out both of them - i.e. 0x4000?


#15

No worries on the spamming, learning as you are. :slight_smile:


#16

I am testing your sketch on my Duo.

brb.


#17

At 0/0x4000/0x4000, I get:

Milliseconds elapsed since last scan result: 10821

Milliseconds elapsed since last scan result: 3002

Milliseconds elapsed since last scan result: 22812

Milliseconds elapsed since last scan result: 3000

Milliseconds elapsed since last scan result: 12898

Milliseconds elapsed since last scan result: 8978

Milliseconds elapsed since last scan result: 22818

Milliseconds elapsed since last scan result: 3000

Same mysteriously consistent 3000 showing up a lot, but very slow on the other ones.


#18

I did some further reading and learned that there is such a thing as active scan. Basically, the central pings the peripheral to get it to send an ad. Someone said that if you use this method, and the interval is short, in effect your central will be driving your peripheral quickly to a dead battery (assuming your peripheral is using battery power).


#19

In my application, the devices are re-charged every day, so not an issue. I only needed it for the BLE Friends to test with my app, instead of expensive wristbands.

Test results using your settings:
Milliseconds elapsed since last scan result: 1172
Milliseconds elapsed since last scan result: 4
Milliseconds elapsed since last scan result: 612
Milliseconds elapsed since last scan result: 4
Milliseconds elapsed since last scan result: 582
Milliseconds elapsed since last scan result: 304
Milliseconds elapsed since last scan result: 304
Milliseconds elapsed since last scan result: 304
Milliseconds elapsed since last scan result: 2
Milliseconds elapsed since last scan result: 4
Milliseconds elapsed since last scan result: 2
Milliseconds elapsed since last scan result: 4
Milliseconds elapsed since last scan result: 294
Milliseconds elapsed since last scan result: 306
Milliseconds elapsed since last scan result: 300
Milliseconds elapsed since last scan result: 302
Milliseconds elapsed since last scan result: 580
Milliseconds elapsed since last scan result: 4
Milliseconds elapsed since last scan result: 2096
Milliseconds elapsed since last scan result: 2
Milliseconds elapsed since last scan result: 312
Milliseconds elapsed since last scan result: 2
Milliseconds elapsed since last scan result: 1478
Milliseconds elapsed since last scan result: 2
Milliseconds elapsed since last scan result: 314
Milliseconds elapsed since last scan result: 4
Milliseconds elapsed since last scan result: 1192
Milliseconds elapsed since last scan result: 4
Milliseconds elapsed since last scan result: 908


#20

0x4000 elapsed times makes sense too. More time between reportcallbacks, correct?


#21

Yeah, I think you are right. I think it does not come up for air to send report to serial monitor until the scan interval is over.

I’m envious of your scan result timing!

I’m assuming the ones that are super short (e.g. 4 milliseconds) are advertisement type 0 or 4. From my experience, if your peripheral is connected or in connectable mode, it sends out TWO ads almost simultaneously: type 0 and type 4. There is only a short 2-6 millisecond gap between the two ads. But once your peripheral is in regular beacon ad mode, it only sends out one ad: type 3.

By the way, I just did an experiment using the other RedBear sample sketch, SimpleBLE. In that sketch, you have an option to fill in a UUID so that the scanner only looks for one specific peripheral.

static uint8_t service1_uuid[16] = { 0x2F,0x23,0x44,0x54,0xCF,0x6D,0x4A,0x0F,0xAD,0xF2,0xF4,0x91,0x1B,0xA9,0xFF,0xA6 };

I read somewhere that this might speed up the scan time. But alas, the results were the same.

Still trying…