This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

with nrf52840 how to detect (scan/sniff) a beacon, identify UUID and aftet go to sleep for one second

I have already developed a beacon with nrf52840, but now I need to detect it with another nrf52840, but my problem is taht I need to use less power as possible, so I need to detect it for one second and after go to sleep for a defined time. 

Problem is that I must disable all possible peripheral (for example UART) and system for many seconds to save power beacuse system must be powered by a small batteries (100mA) for almost one year.

Is there some sample code ready to use?
Can anyone tell me ho to configures scanning and read UUID and RSSI fileds?

Thanks in advance to anyone that could help me.

  • Hi

    sorry for my bad english, I'm working on a central (scanner) and pratically I need only to detect an external beacon with a specific UUID that my central knows. when the beacon with UUID is near to the scannel, that is when signal level (RSSI) is over a value, I must set an output pin (I/O) at high level. When beacon is far and signal level (RSSI) under a value, or not detectable (lost), then that output pin must set low.

    The work is simple, but there is also another small problem, the system must go in sleep (under 2uA), or wake up, by the level of another I/O (an input pin). When nrf52 is active (Input pin externally kept high) the detect state must continue for 3 seconds and after has to go sleep for 2 seconds, and so on until input pin will be pulled low. 

    Best regards,

    yahdar

  • And what exactly are you struggling with? Are you able to scan and detect the beacon? If the device only is scanning for 3 seconds before going to sleep, There won't be a guarantee that it will be able to detect the device every time. What's the advertising interval of the beacon?

    Best regards,

    Simon

  • Hi Simon,

    I work for a company that ask to me to make firmware for a beacon detector (beacon already created and is capable to send advertise every 1 second consuming only 3uA ) in few work days; in the menawhile I also must follow other activities with greater priorities, so as you can image I can devote few time to understand libraries and BSP. 

    The beacon, for power saving, send an advertise every 1 second.

    With one seconds beacon transmission, in my mind with the scanner that listen for 3 seconds, the scanner should be able to detect the beacon in every situation, also after a long sleep. Is this right?

    If 3 second are too few, by your expirience, how many seconds the scanner need as a minimun to detect beacon?

    I hope these informations are useful and you can help me.

    Best regards
        Yahdar

  • Hi

    Thank you for the clarification! Okay, so a beacon transmitting every 1 second, should mean that scanning for 3 seconds at a time will be sufficient for detecting at an advertisement each scanning interval. So, setting the scan duration to 3 seconds should be sufficient there. Then, when you're done, tell the device to go to system idle mode for 2 seconds or so. The attached file just need to set the time you're asleep for to 2 seconds. You can do this by using the RTC. Enable RTC with something a function similar to this.

    void rtc_enable(void)
    {
    	nrf_drv_rtc_counter_clear(&rtc);
        nrf_drv_rtc_tick_enable(&rtc,true);
    	mcuInSleep = true;
    }

    Attached is a main.c file that should work as a beacon scanner going to sleep after the scan duration is over, so you just have to implement the RTC to sleep for the desired amount of time.

    /***************************************************************************************/
    /*
     * beacon_scanner
     * Created by Manuel Montenegro, Sep 7, 2018.
     *
     *  This is a Bluetooth 5 scanner. This code reads every advertisement from beacons
     *  and sends its data through serial port.
     *
     *  This code has been developed for Nordic Semiconductor nRF52840 PDK.
    */
    /***************************************************************************************/
    
    #include <stdint.h>
    #include <stdio.h>
    #include <string.h>
    #include "nordic_common.h"
    #include "nrf_sdm.h"
    #include "ble.h"
    #include "ble_hci.h"
    #include "ble_db_discovery.h"
    #include "ble_srv_common.h"
    #include "nrf_sdh.h"
    #include "nrf_sdh_ble.h"
    #include "nrf_sdh_soc.h"
    #include "nrf_pwr_mgmt.h"
    #include "app_util.h"
    #include "app_error.h"
    #include "ble_dis_c.h"
    #include "ble_rscs_c.h"
    #include "app_util.h"
    #include "app_timer.h"
    #include "bsp_btn_ble.h"
    #include "peer_manager.h"
    #include "peer_manager_handler.h"
    #include "fds.h"
    #include "nrf_fstorage.h"
    #include "ble_conn_state.h"
    #include "nrf_ble_gatt.h"
    #include "nrf_pwr_mgmt.h"
    #include "nrf_ble_scan.h"
    
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    
    
    #define APP_BLE_CONN_CFG_TAG        1                                   /**< Tag that identifies the BLE configuration of the SoftDevice. */
    #define APP_BLE_OBSERVER_PRIO       3                                   /**< BLE observer priority of the application. There is no need to modify this value. */
    #define APP_SOC_OBSERVER_PRIO       1                                   /**< SoC observer priority of the application. There is no need to modify this value. */
    
    #define SCAN_INTERVAL               0x0320                              /**< Determines scan interval in units of 0.625 millisecond. */
    #define SCAN_WINDOW                 0x0320                              /**< Determines scan window in units of 0.625 millisecond. */
    #define SCAN_DURATION           	0x0000                              /**< Duration of the scanning in units of 10 milliseconds. If set to 0x0000, scanning continues until it is explicitly disabled. */
    
    NRF_BLE_SCAN_DEF(m_scan);                                   /**< Scanning Module instance. */
    
    static bool                  m_memory_access_in_progress;   /**< Flag to keep track of ongoing operations on persistent memory. */
    
    static ble_gap_scan_params_t m_scan_param =                 /**< Scan parameters requested for scanning and connection. */
    {
        .active        = 0x00,
        .interval      = SCAN_INTERVAL,
        .window        = SCAN_WINDOW,
        .filter_policy = BLE_GAP_SCAN_FP_ACCEPT_ALL,
        .timeout       = SCAN_DURATION,
    //    .scan_phys     = BLE_GAP_PHY_CODED,                                 // Choose only one of the following scan_phys
        .scan_phys     = BLE_GAP_PHY_1MBPS,
    //    .scan_phys     = BLE_GAP_PHY_2MBPS,
        .extended      = 1,
    };
    
    static void scan_start(void);
    
    
    /**@brief Function for handling BLE events.
     *
     * @param[in]   p_ble_evt   Bluetooth stack event.
     * @param[in]   p_context   Unused.
     */
    static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
    {
    
        switch (p_ble_evt->header.evt_id)
        {
            case BLE_GAP_EVT_ADV_REPORT:
            {
                NRF_LOG_RAW_HEXDUMP_INFO (m_scan.scan_buffer.p_data, m_scan.scan_buffer.len);
                NRF_LOG_RAW_INFO ("----------------------------------\r\n");
            }
    
            default:
                break;
        }
    }
    
    
    /**
     * @brief SoftDevice SoC event handler.
     *
     * @param[in] evt_id    SoC event.
     * @param[in] p_context Context.
     */
    static void soc_evt_handler(uint32_t evt_id, void * p_context)
    {
        switch (evt_id)
        {
            case NRF_EVT_FLASH_OPERATION_SUCCESS:
            /* fall through */
            case NRF_EVT_FLASH_OPERATION_ERROR:
    
                if (m_memory_access_in_progress)
                {
                    m_memory_access_in_progress = false;
                    scan_start();
                }
                break;
    
            default:
                // No implementation needed.
                break;
        }
    }
    
    
    /**@brief Function for initializing the BLE stack.
     *
     * @details Initializes the SoftDevice and the BLE event interrupt.
      */
    static void ble_stack_init(void)
    {
        ret_code_t err_code;
    
        err_code = nrf_sdh_enable_request();
        APP_ERROR_CHECK(err_code);
    
        // Configure the BLE stack using the default settings.
        // Fetch the start address of the application RAM.
        uint32_t ram_start = 0;
        err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
        APP_ERROR_CHECK(err_code);
    
        // Enable BLE stack.
        err_code = nrf_sdh_ble_enable(&ram_start);
        APP_ERROR_CHECK(err_code);
    
        // Register handlers for BLE and SoC events.
        NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
        NRF_SDH_SOC_OBSERVER(m_soc_observer, APP_SOC_OBSERVER_PRIO, soc_evt_handler, NULL);
    }
    
    
    /**@brief Function for handling Scanning Module events.
     */
    static void scan_evt_handler(scan_evt_t const * p_scan_evt)
    {
        switch(p_scan_evt->scan_evt_id)
        {
            case NRF_BLE_SCAN_EVT_SCAN_TIMEOUT:
            {
                NRF_LOG_INFO("Scan timed out.");
                scan_start();
            } break;
    
            default:
              break;
        }
    }
    
    
    /**@brief Function for initializing the scanning and setting the filters.
     */
    static void scan_init(void)
    {
        ret_code_t          err_code;
        nrf_ble_scan_init_t init_scan;
    
        memset(&init_scan, 0, sizeof(init_scan));
    
        init_scan.connect_if_match = false;
        init_scan.conn_cfg_tag     = APP_BLE_CONN_CFG_TAG;
        init_scan.p_scan_param     = &m_scan_param;
    
        err_code = nrf_ble_scan_init(&m_scan, &init_scan, scan_evt_handler);
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for starting scanning.
     */
    static void scan_start(void)
    {
        ret_code_t err_code;
    
        // If there is any pending write to flash, defer scanning until it completes.
        if (nrf_fstorage_is_busy(NULL))
        {
            m_memory_access_in_progress = true;
            return;
        }
    
        err_code = nrf_ble_scan_start(&m_scan);
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for initializing logging. */
    static void log_init(void)
    {
        ret_code_t err_code = NRF_LOG_INIT(NULL);
        APP_ERROR_CHECK(err_code);
    
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    }
    
    
    /**@brief Function for initializing the timer. */
    static void timer_init(void)
    {
        ret_code_t err_code = app_timer_init();
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for initializing power management.
     */
    static void power_management_init(void)
    {
        ret_code_t err_code;
        err_code = nrf_pwr_mgmt_init();
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for handling the idle state (main loop).
     *
     * @details Handles any pending log operations, then sleeps until the next event occurs.
     */
    static void idle_state_handle(void)
    {
        if (NRF_LOG_PROCESS() == false)
        {
            nrf_pwr_mgmt_run();
        }
    }
    
    
    
    int main(void)
    {
    
        // Initialize.
        log_init();
        timer_init();
        power_management_init();
        ble_stack_init();
        scan_init();
    
        // Start execution.
        NRF_LOG_RAW_INFO(    " ----------------\r\n");
        NRF_LOG_RAW_INFO(	 "| Beacon scanner |");
        NRF_LOG_RAW_INFO("\r\n ----------------\r\n");
        
        scan_start();
    
    
        // Enter main loop.
        for (;;)
        {
            idle_state_handle();
        }
    }
    

    Best regards,

    Simon

Related