BLEScanner | Bluefruit NRF52 Feather Learning Guide

Skip to main content Bluefruit nRF52 Feather Learning Guide BLEScanner
  • Introduction
  • Device Pinout
  • Assembly
  • Power Management
  • Arduino Support Setup
  • Arduino Board Testing
  • Using the Bootloader
    • Updating the Bootloader
    • Flashing the Bootloader
  • Arduino BLE Examples
    • Advertising: Beacon
    • BLE UART: Controller
    • Custom: HRM
    • BLE Pin I/O
    • Central BLEUART
    • Dual Roles BLEUART
    • Custom: Central HRM
  • Arduino Bluefruit nRF52 API
    • AdafruitBluefruit
    • BLEGap
    • BLEAdvertising
    • BLEScanner
    • BLEService
    • BLECharacteristic
    • BLEClientService
    • BLEClientCharacteristic
    • BLEDiscovery
    • BLEDis
    • BLEUart
    • BLEClientUart
    • BLEBeacon
    • BLEMidi
    • BLEHidAdafruit
    • BLEAncs
    • BLEClientCts
    • BLECentral
  • nRF52 ADC
  • Memory Map
  • Software Resources
  • Downloads
  • FAQs
  • Single page
  • Feedback? Corrections?
  • Text View
Featured Products view all
  • Your browser does not support the video tag. Video of an LED ring assembled on a half-size breadboard and microcontroller. A white hand changes the color of the LED ring by tapping colors on an app on a smart phone. Adafruit Feather nRF52 Bluefruit LE $24.95 Add to Cart
  • Angled shot of SWD (2x5 1.27mm) Cable Breakout Board SWD (2x5 1.27mm) Cable Breakout Board $2.95 Add to Cart
  • SWD 0.05" Pitch SMT Box Header SWD 0.05" Pitch Connector - 10 Pin SMT Box Header $1.50 Add to Cart
  • SEGGER J-Link JTAG/SWD Debugger brick and JTAG cable SEGGER J-Link BASE - JTAG/SWD Debugger $499.95 Add to Cart
  • SEGGER J-Link JTAG/SWD Debugger brick and JTAG cable SEGGER J-Link EDU - JTAG/SWD Debugger No Longer Stocked
  • CMSIS-DAP JTAG/SWD Debug Adapter Kit with header, adapter, and SWD cable IBDAP - CMSIS-DAP JTAG/SWD Debug Adapter Kit No Longer Stocked
  • 10-pin 2x5 Socket-Socket 1.27mm IDC Cable 10-pin 2x5 Socket-Socket 1.27mm IDC (SWD) Cable - 150mm long $2.95 Add to Cart
135 Advanced Product guide

BLEScanner

The Bluefruit nRF52 BSP codebase is undergoing active development based on customer feedback and testing. As such, the class documentation here is incomplete, and you should consult the Github repo for the latest code and API developments: https://goo.gl/LdEx62 This documentation is based on BSP 0.7.0 and higher. Please make sure you have an up to date version before using the code below.

The BLEScanner class is used in Central Mode, and facilitates scanning for BLE peripherals in range and parsing the advertising data that is being sent out by the peripherals.

The BLEScanner class is normally accessed via the Bluefruit class (instantiated at startup), as shown below:

Download File Copy Code /* Start Central Scanning * - Enable auto scan if disconnected * - Filter for devices with a min RSSI of -80 dBm * - Interval = 100 ms, window = 50 ms * - Use active scan (requests the optional scan response packet) * - Start(0) = will scan forever since no timeout is given */ Bluefruit.Scanner.setRxCallback(scan_callback); Bluefruit.Scanner.restartOnDisconnect(true); Bluefruit.Scanner.filterRssi(-80); // Only invoke callback when RSSI >= -80 dBm Bluefruit.Scanner.setInterval(160, 80); // in units of 0.625 ms Bluefruit.Scanner.useActiveScan(true); // Request scan response data Bluefruit.Scanner.start(0); // 0 = Don't stop scanning after n seconds /* Start Central Scanning * - Enable auto scan if disconnected * - Filter for devices with a min RSSI of -80 dBm * - Interval = 100 ms, window = 50 ms * - Use active scan (requests the optional scan response packet) * - Start(0) = will scan forever since no timeout is given */ Bluefruit.Scanner.setRxCallback(scan_callback); Bluefruit.Scanner.restartOnDisconnect(true); Bluefruit.Scanner.filterRssi(-80); // Only invoke callback when RSSI >= -80 dBm Bluefruit.Scanner.setInterval(160, 80); // in units of 0.625 ms Bluefruit.Scanner.useActiveScan(true); // Request scan response data Bluefruit.Scanner.start(0); // 0 = Don't stop scanning after n seconds API

BLEScanner has the following public API:

Download File Copy Code typedef void (*rx_callback_t) (ble_gap_evt_adv_report_t*); typedef void (*stop_callback_t) (void); BLEScanner(void); ble_gap_scan_params_t* getParams(void); bool isRunning(void); void useActiveScan(bool enable); void setInterval(uint16_t interval, uint16_t window); void setIntervalMS(uint16_t interval, uint16_t window); void restartOnDisconnect(bool enable); void filterRssi(int8_t min_rssi); void filterMSD(uint16_t manuf_id); void filterUuid(BLEUuid ble_uuid); void filterUuid(BLEUuid ble_uuid1, BLEUuid ble_uuid2); void filterUuid(BLEUuid ble_uuid1, BLEUuid ble_uuid2, BLEUuid ble_uuid3); void filterUuid(BLEUuid ble_uuid1, BLEUuid ble_uuid2, BLEUuid ble_uuid3, BLEUuid ble_uuid4); void filterUuid(BLEUuid ble_uuid[], uint8_t count); void clearFilters(void); bool start(uint16_t timeout = 0); bool stop(void); /*------------- Callbacks -------------*/ void setRxCallback(rx_callback_t fp); void setStopCallback(stop_callback_t fp); /*------------- Data Parser -------------*/ uint8_t parseReportByType(const uint8_t* scandata, uint8_t scanlen, uint8_t type, uint8_t* buf, uint8_t bufsize = 0); uint8_t parseReportByType(const ble_gap_evt_adv_report_t* report, uint8_t type, uint8_t* buf, uint8_t bufsize = 0); bool checkReportForUuid(const ble_gap_evt_adv_report_t* report, BLEUuid ble_uuid); bool checkReportForService(const ble_gap_evt_adv_report_t* report, BLEClientService svc); bool checkReportForService(const ble_gap_evt_adv_report_t* report, BLEService svc); typedef void (*rx_callback_t) (ble_gap_evt_adv_report_t*); typedef void (*stop_callback_t) (void); BLEScanner(void); ble_gap_scan_params_t* getParams(void); bool isRunning(void); void useActiveScan(bool enable); void setInterval(uint16_t interval, uint16_t window); void setIntervalMS(uint16_t interval, uint16_t window); void restartOnDisconnect(bool enable); void filterRssi(int8_t min_rssi); void filterMSD(uint16_t manuf_id); void filterUuid(BLEUuid ble_uuid); void filterUuid(BLEUuid ble_uuid1, BLEUuid ble_uuid2); void filterUuid(BLEUuid ble_uuid1, BLEUuid ble_uuid2, BLEUuid ble_uuid3); void filterUuid(BLEUuid ble_uuid1, BLEUuid ble_uuid2, BLEUuid ble_uuid3, BLEUuid ble_uuid4); void filterUuid(BLEUuid ble_uuid[], uint8_t count); void clearFilters(void); bool start(uint16_t timeout = 0); bool stop(void); /*------------- Callbacks -------------*/ void setRxCallback(rx_callback_t fp); void setStopCallback(stop_callback_t fp); /*------------- Data Parser -------------*/ uint8_t parseReportByType(const uint8_t* scandata, uint8_t scanlen, uint8_t type, uint8_t* buf, uint8_t bufsize = 0); uint8_t parseReportByType(const ble_gap_evt_adv_report_t* report, uint8_t type, uint8_t* buf, uint8_t bufsize = 0); bool checkReportForUuid(const ble_gap_evt_adv_report_t* report, BLEUuid ble_uuid); bool checkReportForService(const ble_gap_evt_adv_report_t* report, BLEClientService svc); bool checkReportForService(const ble_gap_evt_adv_report_t* report, BLEService svc);

setRxCallback(rx_callback_t fp)

Whenever a valid advertising packet is detected (based on any optional filters that are applied in the BLEScanner class), a dedicated callback function (see rx_callback_t) will be called.

The callback function has the following signature:

NOTE: ble_gap_evt_adv_report_t is part of the Nordic nRF52 SD and is defined in ble_gap.h

Download File Copy Code void scan_callback(ble_gap_evt_adv_report_t* report) { /* Display the timestamp and device address */ if (report->scan_rsp) { /* This is a Scan Response packet */ Serial.printf("[SR%10d] Packet received from ", millis()); } else { /* This is a normal advertising packet */ Serial.printf("[ADV%9d] Packet received from ", millis()); } Serial.printBuffer(report->peer_addr.addr, 6, ':'); Serial.print("\n"); /* Raw buffer contents */ Serial.printf("%14s %d bytes\n", "PAYLOAD", report->dlen); if (report->dlen) { Serial.printf("%15s", " "); Serial.printBuffer(report->data, report->dlen, '-'); Serial.println(); } /* RSSI value */ Serial.printf("%14s %d dBm\n", "RSSI", report->rssi); /* Adv Type */ Serial.printf("%14s ", "ADV TYPE"); switch (report->type) { case BLE_GAP_ADV_TYPE_ADV_IND: Serial.printf("Connectable undirected\n"); break; case BLE_GAP_ADV_TYPE_ADV_DIRECT_IND: Serial.printf("Connectable directed\n"); break; case BLE_GAP_ADV_TYPE_ADV_SCAN_IND: Serial.printf("Scannable undirected\n"); break; case BLE_GAP_ADV_TYPE_ADV_NONCONN_IND: Serial.printf("Non-connectable undirected\n"); break; } /* Check for BLE UART UUID */ if ( Bluefruit.Scanner.checkReportForUuid(report, BLEUART_UUID_SERVICE) ) { Serial.printf("%14s %s\n", "BLE UART", "UUID Found!"); } /* Check for DIS UUID */ if ( Bluefruit.Scanner.checkReportForUuid(report, UUID16_SVC_DEVICE_INFORMATION) ) { Serial.printf("%14s %s\n", "DIS", "UUID Found!"); } Serial.println(); } void scan_callback(ble_gap_evt_adv_report_t* report) { /* Display the timestamp and device address */ if (report->scan_rsp) { /* This is a Scan Response packet */ Serial.printf("[SR%10d] Packet received from ", millis()); } else { /* This is a normal advertising packet */ Serial.printf("[ADV%9d] Packet received from ", millis()); } Serial.printBuffer(report->peer_addr.addr, 6, ':'); Serial.print("\n"); /* Raw buffer contents */ Serial.printf("%14s %d bytes\n", "PAYLOAD", report->dlen); if (report->dlen) { Serial.printf("%15s", " "); Serial.printBuffer(report->data, report->dlen, '-'); Serial.println(); } /* RSSI value */ Serial.printf("%14s %d dBm\n", "RSSI", report->rssi); /* Adv Type */ Serial.printf("%14s ", "ADV TYPE"); switch (report->type) { case BLE_GAP_ADV_TYPE_ADV_IND: Serial.printf("Connectable undirected\n"); break; case BLE_GAP_ADV_TYPE_ADV_DIRECT_IND: Serial.printf("Connectable directed\n"); break; case BLE_GAP_ADV_TYPE_ADV_SCAN_IND: Serial.printf("Scannable undirected\n"); break; case BLE_GAP_ADV_TYPE_ADV_NONCONN_IND: Serial.printf("Non-connectable undirected\n"); break; } /* Check for BLE UART UUID */ if ( Bluefruit.Scanner.checkReportForUuid(report, BLEUART_UUID_SERVICE) ) { Serial.printf("%14s %s\n", "BLE UART", "UUID Found!"); } /* Check for DIS UUID */ if ( Bluefruit.Scanner.checkReportForUuid(report, UUID16_SVC_DEVICE_INFORMATION) ) { Serial.printf("%14s %s\n", "DIS", "UUID Found!"); } Serial.println(); }

void useActiveScan(bool enable);

Enabling 'Active Scan' by setting the enable parameter to 1 will cause the device to request the optional Scan Response advertising packet, which is a second 31 byte advertising packet that can be used to transmit additional information.

By default active scanning is disabled, so no Scan Response packets will be received by BLEScanner unless this function is called and set to 1 before calling Bluefruit.Scanner.start(0).

void filterRssi(int8_t min_rssi);void filterMSD(uint16_t manuf_id);void filterUuid(BLEUuid ble_uuid);void filterUuid(BLEUuid ble_uuid1, BLEUuid ble_uuid2);void filterUuid(BLEUuid ble_uuid1, BLEUuid ble_uuid2, BLEUuid ble_uuid3);void filterUuid(BLEUuid ble_uuid1, BLEUuid ble_uuid2, BLEUuid ble_uuid3, BLEUuid ble_uuid4);void filterUuid(BLEUuid ble_uuid[], uint8_t count);

Filters can be applied to BLEScanner to narrow down the data sent to the callback handler, and make processing advertising packets easier for you.

As of BSP 0.7.0 the following three filters are present:

  • filterRssi(int8_t min_rssi): Filters advertising results to devices with at least the specified RSSI value, which allows you to ignore devices that are too far away or whose signal is too weak. The higher the number, the strong the signal so -90 is a very weak signal, and -60 is a much stronger one.
  • filterUuid(BLEUuid ble_uuid): Filters advertising results to devices that advertise themselves as having the specified service UUID. If multiple UUIDs are entered, they will be filtered with boolean OR logic, meaning any single UUID present will be considered a match.
  • void filterMSD(uint16_t manuf_id): Fitlers advertising results to devices that contain a Manufacturer Specific Data data type, and who use the specifed Bluetooth Customer ID (manuf_id). This can be useful to filter iBeacon versus Eddystone devices, for example, which both used the MSD field, or to look for custom MSD data matching your own CID.
When multiple UUIDs are added via one of the .filterUuid(...) functions, they UUIDs will be filtered using boolean 'OR' logic, meaning that the callback will fire when ANY of the specified UUIDs are detected in the advertising packet.

void clearFilters(void);

This function clears and filter values set using the functions above.

bool start(uint16_t timeout = 0); bool stop(void);

The .start and .stop functions can be used to start and stop scanning, and should be called after all of the main parameters (timing, filters, etc.) have been set.

The .start function has a single parameter called timeout, which sets the number of seconds to scan for advertising packets. Setting this to '0' (the default value) will cause the device to scan forever.

Make sure you set any filters of BLEScanner parameters before calling .start!

void restartOnDisconnect(bool enable);

Setting this function to '1' will cause the scanning process to start again as soon as you disconnect from a peripheral device. The default behaviour is to automatically restart scanning on disconnect.

Examples

For an example that uses almost all of the BLEScanner and advertising API in Central mode, see central_scan_advanced.ino in the Central examples folder.

central_scan_advanced.ino on Github This example is only available in BSP 0.7.0 and higher!

Page last edited March 08, 2024

Text editor powered by tinymce.

BLEAdvertising BLEService Related Guides Debug Header for the Feather [M0] By Mikey Sklar intermediate How to Program SAMD Bootloaders By Brent Rubell intermediate All the Internet of Things - Episode Four: Adafruit IO By Biniam Tekola beginner Your browser does not support the video tag. This links to the guide 3D Printed Truck Risers with NeoPixel LEDs. 3D Printed Truck Risers with NeoPixel LEDs By Ruiz Brothers intermediate Proper Debugging of ATSAMD21 Processors By lady ada intermediate Debugging CircuitPython On SAMD w/Atmel Studio 7 By Michael Schroeder intermediate Programming an M0 using an Arduino By Dean Miller intermediate 3D Printed Case for Adafruit Feather By Ruiz Brothers beginner Build a Bluetooth App using Swift 5 By Trevor Beaton advanced All the Internet of Things - Episode Three: Services By Biniam Tekola intermediate Introduction to Bluetooth Low Energy By Kevin Townsend beginner AtariFruit 2600 Joystick By John Park intermediate Programming Microcontrollers using OpenOCD on a... By lady ada intermediate What is Web MIDI & BLE MIDI? By Collin Cunningham intermediate Adafruit seesaw By Dean Miller advanced
Create Wishlist
× Title Description Close Search Search
Categories

Tag » Arduino Ble Rssi Example