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

regarding about enhance the distance of range between the ble_app_uart_c_central and ble_app_uart_peripheral

I am using the two units talking with each other for the BLE uart. 

One is running with the example ble_app_uart_c_central. The other is running with the ble_app_uart_peripheral. Both example based on the SDK version nRF5_SDK_17.0.2_d674dde.

Also I am using the S140 softdevice. Both examples are running on the nrf52840 development boards as a pair. 

I want to use them for communication in as long distance as possible. Is there anyway can make it by setting up the TX power for the connection.  I am using your advice as the link below and did some changes to my code in the ble_app_uart_peripheral example side. But seems the distance for communication still around 10 meters, else the connection will lost. My aim is try to make it works for more than 250 meters.

Based on my changes: 1. Does it means the TX power for 8dBm only works for the advertisement mode and not working for the connection mode? 2. Do I need to do any modification for the  ble_app_uart_c_central  example side to improve the communication distance? 3. Do I need to change the S140 softdvice into other softdivce version to make the long distance communication? Does the S340 better for the long distance communication  4. Do I need to make any changes for the hardware side to make it long distance communication?

devzone.nordicsemi.com/.../282647

my modification for the code for the ble_app_uart_peripheral example side is lised below. 

static void advertising_init(void)
{
    uint32_t               err_code;
    ble_advertising_init_t init;
    int8_t tx_power = 8; 

    memset(&init, 0, sizeof(init));

    init.advdata.name_type          = BLE_ADVDATA_FULL_NAME;
    init.advdata.include_appearance = false;
    init.advdata.flags              = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE;

    init.srdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
    init.srdata.uuids_complete.p_uuids  = m_adv_uuids;

    init.config.ble_adv_fast_enabled  = true;
    init.config.ble_adv_fast_interval = APP_ADV_INTERVAL;
    init.config.ble_adv_fast_timeout  = APP_ADV_DURATION;
    init.evt_handler = on_adv_evt;

    err_code = ble_advertising_init(&m_advertising, &init);
    APP_ERROR_CHECK(err_code);

    ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG);

    err_code = sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_ADV , m_advertising.adv_handle, tx_power);
    APP_ERROR_CHECK(err_code);
}

static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
{
    uint32_t err_code;
	int8_t tx_power = 8; //niklas

    switch (p_ble_evt->header.evt_id)
    {
        case BLE_GAP_EVT_CONNECTED:
            //NRF_LOG_INFO("Connected"); 
			status=1;
			status_connected=1;
			printf("Connected");nrf_delay_ms(1);
            err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
            APP_ERROR_CHECK(err_code);
            //reference https://jimmywongiot.com/2019/11/30/how-to-get-the-rssi-change-on-the-nrf5-sdk/
            //https://devzone.nordicsemi.com/f/nordic-q-a/69366/regarding-about-the-connection-rssi-for-signal-strength
            err_code = sd_ble_gap_rssi_start(p_ble_evt->evt.gap_evt.conn_handle,1,2);//niklas
            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_tx_power_set(BLE_GAP_TX_POWER_ROLE_CONN, m_conn_handle, tx_power); //niklas
			APP_ERROR_CHECK(err_code);
            break;

        //case BLE_GAP_EVT_RSSI_CHANGED:
        //     rssi_value=p_ble_evt->evt.gap_evt.params.rssi_changed.rssi;
        //     printf("RSSI=%d\n",p_ble_evt->evt.gap_evt.params.rssi_changed.rssi);

        case BLE_GAP_EVT_DISCONNECTED:
		    status=2;
			status_connected=2;
            //NRF_LOG_INFO("Disconnected");
			printf("Disconnected");nrf_delay_ms(1);
            // LED indication will be changed when advertising starts.
            m_conn_handle = BLE_CONN_HANDLE_INVALID;
            break;

        case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
        {
            status=3;
			//NRF_LOG_DEBUG("PHY update request.");
			printf("PHY update request.");nrf_delay_ms(1);
            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_GAP_EVT_SEC_PARAMS_REQUEST:
		     status=5;
            // Pairing not supported
            err_code = sd_ble_gap_sec_params_reply(m_conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL);
            APP_ERROR_CHECK(err_code);
            break;

        case BLE_GATTS_EVT_SYS_ATTR_MISSING:
		    status=6;
            // No system attributes have been stored.
            err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0);
            APP_ERROR_CHECK(err_code);
            break;

        case BLE_GATTC_EVT_TIMEOUT:
            // Disconnect on GATT Client timeout event.
			status=7;
            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:
		    status=8;
            // Disconnect on GATT Server timeout event.
            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:
		    status=9;
            // No implementation needed.
            break;
    }
}

int main(void)
{
    bool erase_bonds;
    uint8_t find_flag;
        
    // Initialize.
    uart_init();
    log_init();
    timers_init();
    bsp_board_init(BSP_INIT_LEDS);



    power_management_init();
    ble_stack_init();
    gap_params_init();
    gatt_init();
    services_init();
    advertising_init();
    conn_params_init();

    // Start execution.
    advertising_start();

my modification for the code for the ble_app_uart_c_central example side is lised below. 

static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
{
    uint32_t err_code;
	int8_t tx_power = 8; //niklas

    switch (p_ble_evt->header.evt_id)
    {
        case BLE_GAP_EVT_CONNECTED:
            //NRF_LOG_INFO("Connected"); 
			status=1;
			status_connected=1;
			printf("Connected");nrf_delay_ms(1);
            err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
            APP_ERROR_CHECK(err_code);
            //reference https://jimmywongiot.com/2019/11/30/how-to-get-the-rssi-change-on-the-nrf5-sdk/
            //https://devzone.nordicsemi.com/f/nordic-q-a/69366/regarding-about-the-connection-rssi-for-signal-strength
            err_code = sd_ble_gap_rssi_start(p_ble_evt->evt.gap_evt.conn_handle,1,2);//niklas
            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_tx_power_set(BLE_GAP_TX_POWER_ROLE_CONN, m_conn_handle, tx_power); //niklas
			APP_ERROR_CHECK(err_code);
            break;

        //case BLE_GAP_EVT_RSSI_CHANGED:
        //     rssi_value=p_ble_evt->evt.gap_evt.params.rssi_changed.rssi;
        //     printf("RSSI=%d\n",p_ble_evt->evt.gap_evt.params.rssi_changed.rssi);

        case BLE_GAP_EVT_DISCONNECTED:
		    status=2;
			status_connected=2;
            //NRF_LOG_INFO("Disconnected");
			printf("Disconnected");nrf_delay_ms(1);
            // LED indication will be changed when advertising starts.
            m_conn_handle = BLE_CONN_HANDLE_INVALID;
            break;

        case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
        {
            status=3;
			//NRF_LOG_DEBUG("PHY update request.");
			printf("PHY update request.");nrf_delay_ms(1);
            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_GAP_EVT_SEC_PARAMS_REQUEST:
		     status=5;
            // Pairing not supported
            err_code = sd_ble_gap_sec_params_reply(m_conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL);
            APP_ERROR_CHECK(err_code);
            break;

        case BLE_GATTS_EVT_SYS_ATTR_MISSING:
		    status=6;
            // No system attributes have been stored.
            err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0);
            APP_ERROR_CHECK(err_code);
            break;

        case BLE_GATTC_EVT_TIMEOUT:
            // Disconnect on GATT Client timeout event.
			status=7;
            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:
		    status=8;
            // Disconnect on GATT Server timeout event.
            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:
		    status=9;
            // No implementation needed.
            break;
    }
}

Thank you in advance. 

Parents
  • Hi.

    In order to be able to achieve the range you desire, I think you need to look at using Coded PHY (BLE Long range).

    1. Yes, you will need to make some changes to the code in order to increase the range significantly. There should be a lot of threads already on the forum on how to enable Coded PHY. Note that you also need to use extended advertising for this.

    2. Softdevice S140 that is compatible with nRF5 SDK v.17.0.2 is suitable for long range. S340 is not better suited for long range, S340 is pretty much the same as S140 but with added support for ANT.

    3. The nRF52840 development kits can be used for long range. No need to make any HW changes.

    Br,
    Joakim

  • Thank you for the reply. For "2" and "3", I am clear now.

    For the "1".enable Coded PHY, do you have recommend link or reference code? 

    I did the both change to the  and examples for the connection mode for the testing, is this way correct or not?

    BLE_GAP_PHY_AUTO change into BLE_GAP_PHY_CODE

    case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
    {
    NRF_LOG_DEBUG("PHY update request.");
    ble_gap_phys_t const phys =
    {
    .rx_phys = BLE_GAP_PHY_CODED,//BLE_GAP_PHY_AUTO,
    .tx_phys = BLE_GAP_PHY_CODED,//BLE_GAP_PHY_AUTO,
    //rx_phys

    };
    err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
    APP_ERROR_CHECK(err_code);
    } break;

Reply
  • Thank you for the reply. For "2" and "3", I am clear now.

    For the "1".enable Coded PHY, do you have recommend link or reference code? 

    I did the both change to the  and examples for the connection mode for the testing, is this way correct or not?

    BLE_GAP_PHY_AUTO change into BLE_GAP_PHY_CODE

    case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
    {
    NRF_LOG_DEBUG("PHY update request.");
    ble_gap_phys_t const phys =
    {
    .rx_phys = BLE_GAP_PHY_CODED,//BLE_GAP_PHY_AUTO,
    .tx_phys = BLE_GAP_PHY_CODED,//BLE_GAP_PHY_AUTO,
    //rx_phys

    };
    err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
    APP_ERROR_CHECK(err_code);
    } break;

Children
Related