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

Can a Peripheral device know the RSSI for a connected Central

Hello fellow Nordic community,

Assume that a given Peripheral (P) is advertising a BLE GAP signal which allows for multiple connections to be made.

In the vicinity to P we have two central devices (C1, C2) that hear the advertisement signal and connect to P.

(P) - - - - - - < 5 m > - - - - - - (C1)
 
|
  - - - - - - - - - - <  10m > - - - - - - - - - - - - - - - - - - - - - - - - - - - - (C2)

Is it possible to determine on the Peripheral side which connected Central (C1 or C2) that's signal-wise closest to the Peripheral. Hence in the above example determine that C1 is closer than C2?

Thanks for any help!

Cheers,
Kristian

Parents
  • Hi.

    You can use the two functions sd_ble_gap_rssi_get() and sd_ble_gap_rssi_start() to get the RSSI value between a given peripheral and a central.

    You can find more information about these functions in the infocenter under:

    nRF52 Series -> SoftDevices -> Your SoftDevice -> Your SoftDevice API -> Your SoftDevice version API -> API Reference -> Generic Access Profile (GAP)

    Here is the link to the infocenter.

    With RSSI you can't really state which device is closest in distance, since RSSI is a measurement of signal strength, and lots of factors play a part in that value.

    I can give you an example: If there is a wall between P and C1, but P and C2 are in line of sight with no obstacles, you might get a higher RSSI value for C2 then C1 even though C2 is 5 meter further away from P.

    - Andreas

Reply
  • Hi.

    You can use the two functions sd_ble_gap_rssi_get() and sd_ble_gap_rssi_start() to get the RSSI value between a given peripheral and a central.

    You can find more information about these functions in the infocenter under:

    nRF52 Series -> SoftDevices -> Your SoftDevice -> Your SoftDevice API -> Your SoftDevice version API -> API Reference -> Generic Access Profile (GAP)

    Here is the link to the infocenter.

    With RSSI you can't really state which device is closest in distance, since RSSI is a measurement of signal strength, and lots of factors play a part in that value.

    I can give you an example: If there is a wall between P and C1, but P and C2 are in line of sight with no obstacles, you might get a higher RSSI value for C2 then C1 even though C2 is 5 meter further away from P.

    - Andreas

Children
  • Thanks Andreas,

    I get that the actual distance is hard to estimate given a bunch of factors that affects the signal strength.

    I read from your answer that it is possible on the Peripheral side to know the RSSI to a given connected Central. Is that correct?

    Do you know of any examples that show how this could be done?

    Thank you so much for all the help!

  • Hi.

    I can show you how I did it.

    I used the examples\ble_peripheral\ble_app_uart example in SDK 15.0 for this. I did the following in main.c:

    To get a continuous RSSI value I created a timer, which I first defined in the header, like this:

    (Library and API for the timer)

    APP_TIMER_DEF(my_timer_id);

    I then created the timer in int main(void) with the following code (ADDED BY ME):

    int main(void)
    {
        bool erase_bonds;
    
        // Initialize.
        uart_init();
        log_init();
        timers_init();
        buttons_leds_init(&erase_bonds);
        power_management_init();
        ble_stack_init();
        gap_params_init();
        gatt_init();
        services_init();
        advertising_init();
        conn_params_init();
        uint32_t err_code = app_timer_create(&my_timer_id, APP_TIMER_MODE_REPEATED , timeout_handler); //ADDED BY ME
        APP_ERROR_CHECK(err_code);// ADDED BY ME
    
        // Start execution.
        printf("\r\nUART started.\r\n");
        NRF_LOG_INFO("Debug logging for UART over RTT started.");
        advertising_start();
    
        // Enter main loop.
        for (;;)
        {
            
            idle_state_handle();
        }
    }


    The timer required a timeout handler, which I created above int main(void), which looked like this:

    static void timeout_handler(void *timeoutpointer)
    {
                uint8_t rssi;
                uint8_t channel;
    
                uint32_t err_code = sd_ble_gap_rssi_get(m_conn_handle,&rssi,&channel);
                APP_ERROR_CHECK(err_code);
                NRF_LOG_INFO("RSSI: %d", rssi);
    }

    It was in the timeout_handler I collected and printed the RSSI values.

    I started the timer in the case BLE_GAP_EVT_CONNECTED found in static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)

    I added the following code before the switch case in the ble_evt_handler:

    static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
    {
        uint32_t err_code;
        ble_gap_evt_t const * p_gap_evt = &p_ble_evt->evt.gap_evt; // ADDED BY ME
    
        switch (p_ble_evt->header.evt_id)
        {
        .....
        ....
        ...
        ..
        .

    In the BLE_GAP_EVT_CONNECTED case i added the following code:

            case BLE_GAP_EVT_CONNECTED:
                NRF_LOG_INFO("Connected");
                err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
                APP_ERROR_CHECK(err_code);
                m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
                err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_conn_handle);
                APP_ERROR_CHECK(err_code);
                
    
                err_code = sd_ble_gap_rssi_start(p_ble_evt->evt.gap_evt.conn_handle,BLE_GAP_RSSI_THRESHOLD_INVALID,0); //ADDED BY ME
                APP_ERROR_CHECK(err_code); //ADDED BY ME
    
                err_code = app_timer_start(my_timer_id,APP_TIMER_TICKS(5000),0); //ADDED BY ME
                APP_ERROR_CHECK(err_code); //ADDED BY ME
    
                break;

    I then compiled programmed the example and got roughly the same RSSI in dBm as in nRF Connect between the two devices.

    Hope this helps.

    - Andreas

  • Awesome, thanks for the examples. I tried it myself and it seems to work fine. 

  • Hello, 

    Thank you for this example. It definitely works fine. 

    I had another doubt, is it possible to display the RSSI value on the Serial Interface ? I'm using PuTTY, and I wanted to display the RSSI values on it 

  • Hi ,

    Looks like this sd_ble_gap_rssi_get() API not works on sdk 16.0.0, I did the same thing but it returns with  err_code NRF_ERROR_INVALID_STATE

Related