Scanning BLE devices

The way of detect other Bluetooth nodes is making a scan looking for slave messages (called advertisements). Some parameters should be configured to allow scanning in the desired way. Besides that, some scanning functions have been implemented to easy scan for other devices, defining time, number of devices to discover, etc.

Configuring a scan

Next parameters can be configured before doing a scan. The parameters are defined inside the General Access Profile (GAP) of the module. It is not possible to change scanning parameters while scanning, so the user must stop scanning before making any change.

General Access Profile mode:

There are three possible states regarding visibility of BLE devices, so the scan can filter the devices by this state. The function setDiscoverMode() is used to manage them. The possible choices are:

  • Limited discoverable: Discover only slaves which have the limited discoverable mode enabled.

  • Generic discoverable: Discover slaves which have limited discoverable mode or generic discoverable mode enabled.

  • Observation: Discover all devices (default).

Example of use:

{
    BLE.setDiscoverMode(BLE_GAP_DISCOVER_OBSERVATION);
}

Scan Interval

Defines at what intervals scanner is started. This variable is defined in units of 625us and has a range between 4 and 16384. By default is set to 75, which is equivalent to 75 * 625 us = 46.875 ms. The SetScanningParameters() function is used for this purpose.

Example of use:

{
    // set scan interval to 100 ms (160 * 0.625 = 100)
    BLE.setScanningParameters(160, 80, 0);
}

Scan Window

Defines how long to scan at each interval. This variable is defined in units of 625us and and has a range between 4 and 16384. By default is set to 50, which is equivalent to 50 * 625 us = 31.250 ms. It must be equal or smaller than scan interval.

Example of use:

{
    // set scan window to 50 ms (80 * 0.625 = 50)
    BLE.setScanningParameters(160,80,0);
}

Passive / Active scanning

This parameter selects between two types of scanning: passive and active.

In passive scanning, the BLE module just listens to other node advertisements. When one of these advertisements is detected, the module reports to Waspmote the discovered device. Normally, the advertisement contains information like discoverability and connectability modes, TX power level, MAC address of the node (called advertiser) or application data.

On the other hand, in active scanning the module will request more information once an advertisement is received, and the advertiser will answer with information like friendly name and supported profiles. The advertisement packets are configurable as is described in next sections.

Another prototype of setScanningParameters() is defined if only scanning is being changed.

Example of use:

{
    // setting active scanning
    BLE.setScanningParameters(BLE_ACTIVE_SCANNING);
}

MAC filtering and scan policy

The BLE module offers the possibility of sending one report for each node detected (MAC filter enabled) or, on the other hand, send multiple events for each node detected. By default, MAC filter is enabled for all scanning functions.

Besides that, the module has the possibility to accept advertisements only of specific nodes defined inside a list (called "white list"), by defining a scan policy. By default, the scan policy accepts all incoming advertisements. The API function which allows this configuration is setFiltering(). The second parameter, called advertising policy, is described later, because it is related with advertisements.

Example of use:

{
    // enabling MAC filter and setting scan policy to allow scan all devices.
    BLE.setFiltering(BLE_GAP_SCAN_POLICY_ALL, advertisement_policy, BLE_MAC_FILTER_ENABLED);
}

TX power

The transmitting power can be set with the function setTXPower(), using a value between 0 and 15 which give the real TX power from -23 to +3 dBm, according to the hardware of the module. Next graph from the manufacturer shows this relation.

Example of use:

{
    // setting maximum TX power (+3 dBm)
    BLE.setTXPower(TX_POWER_MAX);
}

In order to know the current scanning parameters, the function getScanningParameters() prints by USB all parameters involved in scanning BLE modules. Some examples of scan configurations are listed below.

Example 1

Making a scan with default parameters: Observation scan, interval scan of 46.875 ms, scan window of 31.250 ms, passive scanning, MAC filter enabled and maximum TX power.

{
    // It is not necessary to configure anything
    BLE.scanNetwork(5);
}

Example 2

Configuring a generic scan of 10 seconds with TX power of -5 dBm, active scanning enabled, MAC filter enabled, with a scan interval of 100 ms and a scan window of 50 ms.

{
    BLE.setDiscoverMode(BLE_GAP_DISCOVER_GENERIC);
    BLE.setTXPower(10);
    BLE.setScanningParameters(160, 80, BLE_ACTIVE_SCANNING);
    BLE.scanNetwork(10);
}

Scan functions

There are some predefined functions to make scans, like in the BT_Pro module, allowing to specify time for scanning or a device to find. These functions automatically parses other node advertisements detected by the BLE module and save the data if necessary. See below the data structure of an advertisement detected by the BLE module, and the description of the scanning functions.

Advertisement

Msg type

Payload

Msg Class

Msg ID

RSSI

Packet type

Sender

Address type

Bond

Data

Table: Advertisement structure reported by the BLE module acting as a scanner

ScanNetwork()

This function allows a simple scan of the network. The time of the scan duration must be specified in seconds. Besides that, another prototype has been defined to allow specifying also the TX power for the scan.

If EEPROM usage is enabled by the label ENABLE_EEPROM_SAVING, the scan results will be saved into it, and they can be shown using the function printInquiry(), which prints by USB the data of the last scan. The EEPROM addresses used are defined by the labels SCAN_EEPROM_START_ADDRESS, SCAN_EEPROM_LIMIT_ADDRESS and SCAN_END. If the user does not want to use the EEPROM for this purpose, then a new storing way has to be defined (by global buffers, using SD card, etc). More information about EEPROM usage is provided in next sections. Besides that, the variable numberOfDevices stores the total number of discovered devices during the scan.

Example:

{
    // scan network during five seconds
    BLE.scanNetwork(5);
    // scan network specifying also the TX power
    BLE.scanNetwork(5, TX_POWER_MAX)
}

In the Waspmote Development section you can find a complete example about using this function.

Go to: https://development.libelium.com/ble-01-normal-scan/

ScanNetworkName()

This function scans the network to find other BLE modules, including friendly name of each module. It uses active scanning, because the friendly name is not sent by default on the passive advertisements. The time of the scan duration must be specified in seconds. Besides that, another prototype has been defined to allow specifying also the TX power for the scan.

Example:

{
    // scan network during five seconds, including friendly name
    BLE.scanNetworkName(5);
    // scan network specifying the TX power, including friendly name
    BLE.scanNetworkName(5, TX_POWER_MAX);
}

If the scanned devices have no friendly name available, the friendly name field will be empty.

In the Waspmote Development section you can find a complete example about using this function.

Go to: https://development.libelium.com/ble-02-name-scan/

ScanNetworkLimited()

This function scans the network in the same way of scanNetwork(), but now you can limit your scan to a specific number of BLE modules. If this number is reached, the inquiry stops. However, if maximum is not reached, the module continues inquiring until DEFAULT_SCAN_TIME.

The number of devices to discover must be specified. Besides that, another prototype has been defined to allow specifying also the TX power for the scan.

Example:

{
    // scan network till find two devices
    BLE.scanNetworkLimited(2);
    // scan network till find two devices, setting also TX power
    BLE.scanNetworkName(5, TX_POWER_MAX);
}

In the Waspmote Development section you can find a complete example about using this function.

Go to: https://development.libelium.com/ble-03-limited-scan/

ScanDevice()

This function makes a scan to discover a specific BLE device by its MAC address. This function is used to know if a specific device is present inside detection area of the BLE module. Devices are commonly identified by its MAC address, which is a number of 12 digits, for example \"00078053C1B9\".

The node MAC address must be specified as a parameter, but it has been defined another prototype to specify also the maximum scanning time and the TX power. If the user does not specify these parameters, default values will be used.

Example:

{
    // scan network till find specified device
    BLE.scanDevice("00078053C1B9");
    // Look for a specified device, during given time and using given TX power
    BLE.scanDevice("00078053C1B9", 5, TX_POWER_MAX);
}

In the Waspmote Development section you can find a complete example about using this function.

Go to: https://development.libelium.com/ble-04-scan-device/

PrintInquiry()

By default, discovered devices are not shown through USB because they are only saved on EEPROM memory (if enabled). If the user wants to view discovered devices just use the printInquiry() function after the scan function and the discovered devices in the last inquiry will be shown. It also returns the number of devices printed.

Example:

{
    // scan network for 5 seconds
    BLE.scanNetwork(5);
    USB.printf(\"discovered devices: %d\r\n\", BLE.numberOfDevices);
    // Now print last inquiry saved on EEPROM
    USB.println(\"Printing Last inquiry saved on EEPROM:\");
    uint8_t dummy = BLE.printInquiry();
    USB.printf(\"devices printed:%d\r\n\r\n\",dummy);
}

Finally, if the user wants to cancel an inquiry on a certain moment, the scanNetworkCancel() function will stop any scan in course.

EEPROM management

The EEPROM memory of Waspmote can be used to store scan results. By default, this feature is enabled, so the user should take into account if other parts of the application are using it. A certain zone of the EEPROM memory is reserved for BLE module usage, defined with the next labels:

  • SCAN_EEPROM_START_ADDRESS

  • SCAN_EEPROM_LIMIT_ADDRESS

By default, 800 bytes are reserved (enough for 20 devices), starting on position 1024 and ending at 1823, but the user is free to enlarge or move the reserved space to other EEPROM zones, even change the way of storing scanned devices to select only certain information. Moreover, the user can easily disable this feature by setting the label ENABLE_EEPROM_SAVING to 0.

More in detail, a scan network is saved using the structure discoveredDevice() shown below:

struct discoveredDevice
    {
        uint8_t mac[6]; // MAC Address of the BLE device
        int8_t rssi; // Received signal strength of the BLE device
        uint8_t friendlyName[31]; // Friendly name of the BLE device
        uint8_t advData[33]; // Advertisement data of the BLE device
    };

Where each field contains information about the last scanned BLE device, like the MAC address, the RSSI (Received Signal Strength Indicator, in dBm and with a range from -103 to -38), the friendly name and the advertisement data. An end sequence is used to know the scan data length. The friendly name is filled with either short friendly name or large friendly name, as defined in the Bluetooth 4.0 standard. If no friendly name is found for the scanned device, the field will be empty. Each scan can be easily printed by the function printInquiry(), which prints by USB the last scan saved.

Finally, the advertisement data stored in advData is not saved in memory. The user will have to develop its own application and use this data in the preferred way.

Relationship between RSSI and distance

As described in previous section, each scanned device has an associated RSSI value in dBm. This value is directly related with the distance of the scanned node from the scanner.

Besides that, the user can modify the TX power used for the scan, and using both properties, the Waspmote BLE module can be used to know if a BLE device is too close to the scanner, in a middle range or far from the scanner, performing different actions on them. Next graph shows this relationship, where a BLE node is approaching the BLE scanner. Average RSSI values of a BLE node are faced to the distance from the BLE scanner.

Indoor location

The relationship between the RSSI and the distance between two BLE nodes can be used for indoor location applications. Placing various BLE nodes inside a room, it is easy to obtain some RSSI values of the same BLE device, allowing the estimation of the BLE exact location inside the room.

Last updated