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.

Parents
  • 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

Reply
  • 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

Children
No Data
Related