BLE Scan interval and window

There is another aspect to this that is being missed in the other answers. As per the Core BLE specification, only one advertising channel is being looked at during each scanInterval and is rotated to the next of 3 channels with each interval. So if there is RF interference on that channel you might not see the device even if you have the scanWindow equal to the scanInterval in order to do continuous scanning.

The BLE peripheral device that does advertising would normally rotate through all three advertising channels in sequence very quickly during each advertising blip of time. So the best central device scanning algorithm would have shorter windows and intervals in order to sequentially check each advertising channel. Apple apparently uses a 30 ms scanWindow with 40 ms scanInterval in iOS with apps in foreground mode. That means that each advertising channel will be checked every 40 ms. Per the BLE Core Specification:

Each advertising event is composed of one or more advertising PDUs sent on used advertising channel indices. The advertising event shall be closed after one advertising PDU has been sent on each of the used advertising channel indices (see Section 4.4.2.1) or the advertiser may close an advertising event earlier to accommodate other functionality.

Another very important aspect is to have the Peripheral device set an advertising interval that is relatively prime compared to the scanInterval on the Central device. This is why Apple specifies specific advertising intervals. If you were to pick a scanInterval of 100 ms with a scanWindow that was smaller, say 80 ms and had an advertising interval of 1000 ms (1 second), then you could get unlucky and always be advertising during the 20 ms when the Central device was not scanning during each scanInterval. In reality, the BLE core specification adds a random 0-10 ms to the advertising interval which helps slew to prevent a complete deadlock, but it's really done more to avoid multiple devices advertising at nearly exactly the same time from interfering with each other forever.

For all undirected advertising events or connectable directed advertising events used in a low duty cycle mode, the time between the start of two consecutive advertising events (T_advEvent) is computed as follows for each advertising event:

T_advEvent = advInterval + advDelay

The advInterval shall be an integer multiple of 0.625 ms in the range of 20 ms to 10.24 s. If the advertising event type is either a scannable undirected event type or a non-connectable undirected event type, the advInterval shall not be less than 100 ms. If the advertising event type is a connectable undirected event type or connectable directed event type used in a low duty cycle mode, the advInterval can be 20 ms or greater. The advDelay is a pseudo-random value with a range of 0 ms to 10 ms generated by the Link Layer for each advertising event.

Think of having two frequencies near each other and how you get a beat frequency of their difference. That is essentially what can happen between the scanInterval and the advertising interval. Apple did a decent job with their settings for this so following their standards would not only work well for iOS but also for Android. Apple's foreground mode of 30 ms scanWindow with 40 ms scanInterval means that for a base advertising interval of 1022.5 ms that you see the device within 1 second about 3/4ths of the time and always within 2 seconds, assuming no RF interference obscuring the advertising packet. In background mode with a 30 ms scanWindow and 300 ms scanInterval, the median time becomes 5 seconds and the usual maximum becomes 19 seconds though with very bad luck of the random shifts it could be a little longer.

https://developer.apple.com/hardwaredrivers/BluetoothDesignGuidelines.pdf

The Apple recommended peripheral advertising intervals are 152.5, 211.25, 318.75, 417.5, 546.25, 760, 852.5, 1022.5, 1285 ms.


According to the Bluetooth 4.0 core specification the time period of 'advertising events' are as shown below for the different types of advertising packets:

ADV_IND: General connectable and scannable advertisement packets' time period ranges from 20 ms to 10.24s in steps of 0.625ms.

ADV_DIRECT_IND: Directed advertisement packets' time period is less than or equal to 3.75 ms. This kind of advertisement events can happen consecutively only for 1.28s. This is for a establishing a quick connection (if there is a device listening).

ADV_NONCONN_IND: Non-connectable and non-scannable advertisement packets' time period ranges from 100 ms to 10.24s in steps of 0.625ms.

ADV_SCAN_IND: Scannable advertisement packets' time period ranges from 100 ms to 10.24s in steps of 0.625ms.

So, unless you know the kind of device you are scanning for a good approach would be continuously to scan for around 11 (max) seconds to see if there are any advertising devices around. How often to do this will depend on the amount of battery or power available.

Hope this helps.