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

How to get RSSI from a nRF52832 beacon using nRF52

Hello everyone,

I just started learning BLE. I want to develop an application that gets RSSI from a beacon and displays the magnitude of RSSI using 4 built-in LEDs.

     Beacon            |     Scanner(nRF52840)

-100 ~ -80 dBm    = no leds lit up

-80 ~ -60 dBm     = LED1 lit up

-60 ~ -40 dBm     = LED1, LED2 lit up

-80 ~ -20 dBm     = LED1, LED2, LED3 lit up

-20dBm ~            = LED1, LED2, LED3, LED4 lit up

I am using nRF52832 as a beacon flashed with ble_app_beacon example.

And I have another nRF52840 board for scanning the advertisement data.

But where should I get the RSSI? I feel kinda lost where to start. Please help me

Parents Reply Children
  • Hello, Einar,

    Thanks for your kind reply. I now have 3 questions.

    Q1. I want both devices(beacon, scanner) stay unconnected while the scanner is getting advertisement data from the beacon. Should then I use ble_gap_evt_adv_report_t command in scan_evt_handler, not ble_evt_handler?

    Q2. How can I use the ble_gap_evt_adv_report_t command in the handler? If I want to save RSSI value in a buffer, is it possible to use like this?

    static void scan_evt_handler(scan_evt_t const * p_scan_evt)
    {
        ret_code_t err_code;
    
        static int16_t rssi_buffer[100];
        static int idx = 0;
        
        switch(p_scan_evt->scan_evt_id)
        {
            case NRF_BLE_SCAN_EVT_FILTER_MATCH: 
                rssi_buffer[idx] = ble_gap_evt_adv_report_t->rssi;
                idx++;
                break;
        }
    }

    Q3. I am using ble_app_blinky_c example for the scanner device. If I do not want the connection, do I need the ble_evt_handler like below?

    static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
    {
        ret_code_t err_code;
    
        // For readability.
        ble_gap_evt_t const * p_gap_evt = &p_ble_evt->evt.gap_evt;
    
        switch (p_ble_evt->header.evt_id)
        {
            // Upon connection, check which peripheral has connected (HR or RSC), initiate DB
            // discovery, update LEDs status and resume scanning if necessary. */
            case BLE_GAP_EVT_CONNECTED:
            {
                NRF_LOG_INFO("Connected.");
                err_code = ble_lbs_c_handles_assign(&m_ble_lbs_c, p_gap_evt->conn_handle, NULL);
                APP_ERROR_CHECK(err_code);
    
                err_code = ble_db_discovery_start(&m_db_disc, p_gap_evt->conn_handle);
                APP_ERROR_CHECK(err_code);
    
                // Update LEDs status, and check if we should be looking for more
                // peripherals to connect to.
                bsp_board_led_on(CENTRAL_CONNECTED_LED);
                bsp_board_led_off(CENTRAL_SCANNING_LED);
            } break;
    
            // Upon disconnection, reset the connection handle of the peer which disconnected, update
            // the LEDs status and start scanning again.
            case BLE_GAP_EVT_DISCONNECTED:
            {
                NRF_LOG_INFO("Disconnected.");
                scan_start();
            } break;
    
            case BLE_GAP_EVT_TIMEOUT:
            {
                // We have not specified a timeout for scanning, so only connection attemps can timeout.
                if (p_gap_evt->params.timeout.src == BLE_GAP_TIMEOUT_SRC_CONN)
                {
                    NRF_LOG_DEBUG("Connection request timed out.");
                }
            } break;
    
            case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST:
            {
                // Accept parameters requested by peer.
                err_code = sd_ble_gap_conn_param_update(p_gap_evt->conn_handle,
                                            &p_gap_evt->params.conn_param_update_request.conn_params);
                APP_ERROR_CHECK(err_code);
            } break;
    
            case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
            {
                NRF_LOG_DEBUG("PHY update request.");
                ble_gap_phys_t const phys =
                {
                    .rx_phys = BLE_GAP_PHY_AUTO,
                    .tx_phys = BLE_GAP_PHY_AUTO,
                };
                err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
                APP_ERROR_CHECK(err_code);
            } break;
    
            case BLE_GATTC_EVT_TIMEOUT:
            {
                // Disconnect on GATT Client timeout event.
                NRF_LOG_DEBUG("GATT Client Timeout.");
                err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                APP_ERROR_CHECK(err_code);
            } break;
    
            case BLE_GATTS_EVT_TIMEOUT:
            {
                // Disconnect on GATT Server timeout event.
                NRF_LOG_DEBUG("GATT Server Timeout.");
                err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                APP_ERROR_CHECK(err_code);
            } break;
    
            default:
                // No implementation needed.
                break;
        }
    }
    

    Thank you all !

  • Hi,

    dalsee said:
    Q1. I want both devices(beacon, scanner) stay unconnected while the scanner is getting advertisement data from the beacon. Should then I use ble_gap_evt_adv_report_t command in scan_evt_handler, not ble_evt_handler?

    I did not fully understand the question. If you use the scanning module, then it makes sense to do it in the scan_evt_handler(). But it is actually the same event with the same information you get the ble_evt_handler. This is not related to connections etc.

    dalsee said:
    Q2. How can I use the ble_gap_evt_adv_report_t command in the handler? If I want to save RSSI value in a buffer, is it possible to use like this?

    The ble_gap_evt_adv_report_t struct is not a command, but a struct that is passed to the application from the SoftDevice when there is an advertising report event (BLE_GAP_EVT_ADV_REPORT). The way you try to use it is not correct, and it is not legal C code. You can refer to the example in this post if you want to see how to scan without the scan module (which is simpler if you don't need filtering). If you continue to use the scan module and get a hit, then you can access the rssi by replacing "ble_gap_evt_adv_report_t->rssi;" with "p_scan_evt->filter_match.p_adv_report->rssi".

    dalsee said:
    Q3. I am using ble_app_blinky_c example for the scanner device. If I do not want the connection, do I need the ble_evt_handler like below?

    Since you use the scan module, you just need to make sure you set connect_if_match to false instead of true when you initialize it (calling nrf_ble_scan_init()).

  • Hello,

    The below code resulted the compile error,

    int read_rssi = p_scan_evt->filter_match.p_adv_report->rssi;

    but I think I managed to resolve the issue by adding 'params.' in front of the struct and now it works :D

    int read_rssi = p_scan_evt->params.filter_match.p_adv_report->rssi;

    Thanks for you help. And now I want to filter the beacon's UUID because I want to read the target's RSSI only. Since my beacon device is using ble_app_beacon example, its UUID seems to be 128bit long.

    Q1. Now I am being confused, what should I define for the argument 'target_uuid'?

    err_code = nrf_ble_scan_filter_set(&m_scan, SCAN_UUID_FILTER, &target_uuid);
    APP_ERROR_CHECK(err_code);

  • Hi,

    dalsee said:
    Q1. Now I am being confused, what should I define for the argument 'target_uuid'?

    You can refer to the BLE UART central example to see how the scan module is used to filter on the 128 bit UUID (see the scan_init() function).

Related