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

BLE transmission method of multiple data

Hello

I am using Android and BLE communication with nRF52832 (BLENano2) now.

I am using SDK 15.0.0 with keil uversion.

Central is Android and peripheral is nRF52832.

Use the SDK "ble_app_blinky".

I now want to send arbitrary data from peripheral to central.

By calling the following code "send_data" in the main for loop, it was possible to send the value to central.

uint32_t send_value(uint16_t conn_handle, ble_lbs_t * p_lbs, uint8_t sensor_value)
{
	
	if (p_lbs == NULL)
    {
        return NRF_ERROR_NULL;
    }
		
	
	uint32_t err_code = NRF_SUCCESS;
	ble_gatts_value_t gatts_value;
	
	// Initialize value struct.
  memset(&gatts_value, 0, sizeof(gatts_value));

	gatts_value.len     = sizeof(uint8_t);
  gatts_value.offset  = 0;
  gatts_value.p_value = &sensor_value;

	// Update database.
  err_code = sd_ble_gatts_value_set(BLE_CONN_HANDLE_ALL,////////////
                                      p_lbs->sensor_char_handles.value_handle,
                                      &gatts_value);

	
		
		if (err_code != NRF_SUCCESS)
		{
				return err_code;
		}


	
	// Send value if connected and notifying.
    if ((conn_handle != BLE_CONN_HANDLE_INVALID)) 
    {
        ble_gatts_hvx_params_t hvx_params;

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

        hvx_params.handle = p_lbs->sensor_char_handles.value_handle;
        hvx_params.type   = BLE_GATT_HVX_NOTIFICATION;
        hvx_params.offset = gatts_value.offset;
        hvx_params.p_len  = &gatts_value.len;
        hvx_params.p_data = gatts_value.p_value;

        err_code = sd_ble_gatts_hvx(conn_handle, &hvx_params);
    }
    else
    {
        err_code = NRF_ERROR_INVALID_STATE;
    }
		return err_code;
}

I am currently sending uint8_t data, but I want to be able to send multiple data.

Since we are transmitting the output value of the acceleration sensor, we want to transmit a total of 6 bytes of data.

The problem here is that even if uint16_t is executed with uint8_t as the argument of "send_data" in order to send multiple data at once, the data was not sent.

What should I do to send multiple data?

As a possible way,
1) Separate the characteristic for each data you want to send and send each.
2) As I said earlier, prepare a larger sized variable instead of uint8_t.

I thought that.

I tried to increase the characteristic, but only one characteristic worked.

If you know the solution please tell me.

Thank you.

Parents
  • This piece of code is what sets the length to 1 byte. Note also that you can't send data longer than the negotiated MTU size - 3 in one operation.

    uint8_t sensor_value;
    
    gatts_value.len     = sizeof(uint8_t);
    gatts_value.offset  = 0;
    gatts_value.p_value = &sensor_value;

    So, you can modify this to instead of taking a uint8_t as value argument, take a pointer and a length. Then you define the data format elsewhere, this just sends the data.

  • Thank you for reply!

    uint32_t send_value(uint16_t conn_handle, ble_lbs_t * p_lbs, uint16_t sensor_value)
    {
    	
    	if (p_lbs == NULL)
        {
            return NRF_ERROR_NULL;
        }
    		
    	
    	uint32_t err_code = NRF_SUCCESS;
    	ble_gatts_value_t gatts_value;
    	
    	// Initialize value struct.
      memset(&gatts_value, 0, sizeof(gatts_value));
    
    	gatts_value.len     = sizeof(uint16_t);
      gatts_value.offset  = 0;
      gatts_value.p_value = &sensor_value;
    
    	// Update database.
      err_code = sd_ble_gatts_value_set(BLE_CONN_HANDLE_ALL,////////////
                                          p_lbs->sensor_char_handles.value_handle,
                                          &gatts_value);
    
    	
    		
    		if (err_code != NRF_SUCCESS)
    		{
    				return err_code;
    		}
    
    
    	
    	// Send value if connected and notifying.
        if ((conn_handle != BLE_CONN_HANDLE_INVALID)) 
        {
            ble_gatts_hvx_params_t hvx_params;
    
            memset(&hvx_params, 0, sizeof(hvx_params));
    
            hvx_params.handle = p_lbs->sensor_char_handles.value_handle;
            hvx_params.type   = BLE_GATT_HVX_NOTIFICATION;
            hvx_params.offset = gatts_value.offset;
            hvx_params.p_len  = &gatts_value.len;
            hvx_params.p_data = gatts_value.p_value;
    
            err_code = sd_ble_gatts_hvx(conn_handle, &hvx_params);
        }
        else
        {
            err_code = NRF_ERROR_INVALID_STATE;
        }
    		return err_code;
    }
    

    Should I make this change?

    Also, as settings, ble_gatts_value_t of "ble_gatts.h" and * p_value of ble_gatts_hvx_params_t have been changed to uint16_t.

    After making these changes, nRFConnect did not receive a value when trying to send 2 bytes worth of data.

  • What return code did you get from send_value? Did you enable notifications from nRFConnect?

    I have successfully done like this:

    uint32_t ble_tx(uint16_t conn_key, const uint8_t *p_data, uint16_t length)
    {
        le_client_internal_t *p_client = NULL;
        ble_gatts_hvx_params_t hvx_params;
    
        ret_code_t err_code = blcm_link_ctx_get(m_ble.p_link_ctx_storage,
                                     conn_key,
                                     (void *) &p_client);
    
        if (err_code != NRF_SUCCESS)
        {
            NRF_LOG_ERROR("Link context for 0x%02X connection handle could not be fetched.",
                          conn_key);
            return NRF_ERROR_INVALID_STATE;
        }
    
        if (p_client == NULL)
        {
            return NRF_ERROR_INVALID_STATE;
        }
    
        if (length > p_client->data_size)
        {
            /* TODO: Compare against the actual MTU negotiated. */
            return NRF_ERROR_INVALID_PARAM;
        }
    
        memset(&hvx_params, 0, sizeof(hvx_params));
    
        hvx_params.handle = m_ble.tx_char_handle.value_handle;
        hvx_params.p_data = p_data;
        hvx_params.p_len  = &length;
        hvx_params.type   = BLE_GATT_HVX_NOTIFICATION;
    
        return sd_ble_gatts_hvx(conn_key, &hvx_params);
    }

    I also have an internal structure that keeps track of if the MTU size is renegotiated. Another layer actually checks that so I never end up in the (lengt > p_client->data_size) branch.

Reply
  • What return code did you get from send_value? Did you enable notifications from nRFConnect?

    I have successfully done like this:

    uint32_t ble_tx(uint16_t conn_key, const uint8_t *p_data, uint16_t length)
    {
        le_client_internal_t *p_client = NULL;
        ble_gatts_hvx_params_t hvx_params;
    
        ret_code_t err_code = blcm_link_ctx_get(m_ble.p_link_ctx_storage,
                                     conn_key,
                                     (void *) &p_client);
    
        if (err_code != NRF_SUCCESS)
        {
            NRF_LOG_ERROR("Link context for 0x%02X connection handle could not be fetched.",
                          conn_key);
            return NRF_ERROR_INVALID_STATE;
        }
    
        if (p_client == NULL)
        {
            return NRF_ERROR_INVALID_STATE;
        }
    
        if (length > p_client->data_size)
        {
            /* TODO: Compare against the actual MTU negotiated. */
            return NRF_ERROR_INVALID_PARAM;
        }
    
        memset(&hvx_params, 0, sizeof(hvx_params));
    
        hvx_params.handle = m_ble.tx_char_handle.value_handle;
        hvx_params.p_data = p_data;
        hvx_params.p_len  = &length;
        hvx_params.type   = BLE_GATT_HVX_NOTIFICATION;
    
        return sd_ble_gatts_hvx(conn_key, &hvx_params);
    }

    I also have an internal structure that keeps track of if the MTU size is renegotiated. Another layer actually checks that so I never end up in the (lengt > p_client->data_size) branch.

Children
Related