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

Multiple value in one characteristic

Hello,

My project requires me to send acceleration data to phone. So, i have started with Custom BLE app.

Since i need to send 3 values, of x, y and z-axis. So i need to send multiple values to same characteristic. Can you guide me regarding this?

If any other approach serves me better, kindly do suggest me.

Parents
  • The definition of a "Characteristic", from the Bluetooth SIG website, is:

    "Characteristics are defined attribute types that contain a single logical value."

    https://www.bluetooth.com/specifications/gatt/characteristics/

    (my emphasis)

    However, there's nothing to stop you having a 3-byte value - where the 1st byte represents X, the 2nd byte represents Y, and the 3rd byte represents Z

    Or have a 6-byte value - where the 1st two bytes represent X, the 2nd two bytes represent Y, and the 3rd two bytes represent Z

    etc, etc, ...

    Or, as  says, have a characteristic for X, and characteristic for Y, and a characteristic for Z.

    See those tutorials.

    EDIT

    The Thingy:52 adopts the scheme of "packing" multiple values into a single Characteristic; eg, see the "Raw Data" Characteristic:

    https://nordicsemiconductor.github.io/Nordic-Thingy52-FW/documentation/firmware_architecture.html#arch_motion

  • Thank you so much,  and  for your suggestions.

    So,

    Question 1

    a. Sending 3 values, one after the other , through the same value and characteristics (This would consume power for all 3 transmissions)

    b. Sending 3 values to 3 different characteristics (Would this also means im trying to send the data in 3 transmissions?)

    c. Sending all 3 values packed would save power and could send all data in one transmission.

    Kindly correct me, if I'm wrong.

    ------------------------------------------------------------------------------------------------------------------------------------------------------

    Question 2

    So, currently my code is pushing 8 bits of data . To change this to 64bits, i tried following corrections, Kindly let me know, if this is okay and if anything else has to be changed

           a. change the size of custom value (main.c)

                           

           b. change the argument size and gatts_value.len (ble_cus.c)

    uint32_t ble_cus_custom_value_update(ble_cus_t * p_cus, uint64_t custom_value){
        NRF_LOG_INFO("In ble_cus_custom_value_update. \r\n"); 
         
        if (p_cus == 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(uint64_t);
        gatts_value.offset  = 0;
        gatts_value.p_value = &custom_value;
    
        // Update database.
        err_code = sd_ble_gatts_value_set(p_cus->conn_handle,
                                            p_cus->custom_value_handles.value_handle,
                                            &gatts_value);
        if (err_code != NRF_SUCCESS)
        {
            return err_code;
        }
    
            // Send value if connected and notifying.
        if ((p_cus->conn_handle != BLE_CONN_HANDLE_INVALID)) 
        {
            ble_gatts_hvx_params_t hvx_params;
    
            memset(&hvx_params, 0, sizeof(hvx_params));
    
            hvx_params.handle = p_cus->custom_value_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(p_cus->conn_handle, &hvx_params);
            NRF_LOG_INFO("sd_ble_gatts_hvx result: %x. \r\n", err_code);
        }
            else
        {
            err_code = NRF_ERROR_INVALID_STATE;
            NRF_LOG_INFO("sd_ble_gatts_hvx result: NRF_ERROR_INVALID_STATE. \r\n"); 
        }
    
        return err_code;
        }

             c. Change the size of custom value in prototype declaration. (ble_cus.h)

             d. Change the value of structure of GATT attribute value and HVx value as below (ble_gatts.h)

    /**@brief GATT Attribute Value. */
    typedef struct
    {
      uint64_t  len;        /**< Length in bytes to be written or read. Length in bytes written or read after successful return.*/
      uint64_t  offset;     /**< Attribute value offset. */
      uint64_t  *p_value;    /**< Pointer to where value is stored or will be stored.
                                 If value is stored in user memory, only the attribute length is updated when p_value == NULL.
                                 Set to NULL when reading to obtain the complete length of the attribute value */
    } ble_gatts_value_t;
    
    
    /**@brief GATT HVx parameters. */
    typedef struct
    {
      uint64_t          handle;             /**< Characteristic Value Handle. */
      uint64_t           type;               /**< Indication or Notification, see @ref BLE_GATT_HVX_TYPES. */
      uint64_t          offset;             /**< Offset within the attribute value. */
      uint64_t         *p_len;              /**< Length in bytes to be written, length in bytes written after return. */
      uint64_t const    *p_data;             /**< Actual data content, use NULL to use the current attribute value. */
    } ble_gatts_hvx_params_t;

  • Hello,

    Nats said:
    Thank you Karl for your guidance

    No problem at all, I am happy to help!

    Nats said:
    along with your suggestions, the attribute section also needed to be changed (the max.len) and now it works fine. 

    Could you link exactly where you made the change, and how you changed it?
    My apologies for overlooking this. I am happy you were able to resolve the issue!

    Nats said:
    Now, my query is, what are the corrections to be made, if i want to send a signed integer of 64 bit, instead of unsigned. 

    Both uint64_t and int64_t consists of exactly 64 bit - the only difference is their range of possible numbers to represent.
    As long as your central knows what to expect the approach for sending the value using the Nordic UART example is exactly the same.

    Best regards,
    Kar

  • Taking a quick look on the code you have shared, it seems to me that the ble_cus_custom_value_update is not part of the main.c project file, which leads me to believe that you have either added it to one of the drivers already included in the SDK, or in a driver you have made yourself - but placed in a location probably close to the other drivers.

    If this is the case, I would like to recommend to you that you do not make changes directly to the drivers included in the SDK(to avoid non-compatibility / breakage of the other examples or drivers).
    Instead, I would suggest that you make your own copy of the driver you would like to modify, and rename it to reflect that. Ideally, you would also place your modified / custom code in a separate directory, for easy differentiation. Borrowing naming conventions from the SDK might also lead to confusion.
    It will make it easier to share your project in the future, and it will avoid confusion when working with someone already familiar with the unmodified SDK code.

    This is of course just a suggestion, and you may of course organize the project as you would like.

    Have a great weekend!

    Best regards,
    Karl

  • This is of course just a suggestion

    But a very good suggestion!

    And it is not specific to the Nordic SDK - this would be Good Practice with any SDK, or any other 3rd-party library, etc.

  • Hey, Thank you so much, but i followed the tutorial of https://github.com/NordicPlayground/nRF52-Bluetooth-Course. Custom BLE tutorial. Is this not from Nordic? 

  • Hello again,

    i followed the tutorial of https://github.com/NordicPlayground/nRF52-Bluetooth-Course. Custom BLE tutorial. Is this not from Nordic? 

    Yes it is from Nordic - but be advised that all NordicPlayground repos are officially unsupported.
    However, in this case that does not matter, since it is code for a tutorial.

    If you see the structure of the repository from the tutorial, you will notice that the associated ble_cus.* files are both located next to the main.c file - they are not located with the other official BLE services.

    Separating your custom code from the official code is good practice when working with any SDK, as @Awneil mentions. I would even argue it is the best practice, especially if you intend to work with others that are already familiar with the drivers you are modifying.

    Best regards,
    Karl

Reply
  • Hello again,

    i followed the tutorial of https://github.com/NordicPlayground/nRF52-Bluetooth-Course. Custom BLE tutorial. Is this not from Nordic? 

    Yes it is from Nordic - but be advised that all NordicPlayground repos are officially unsupported.
    However, in this case that does not matter, since it is code for a tutorial.

    If you see the structure of the repository from the tutorial, you will notice that the associated ble_cus.* files are both located next to the main.c file - they are not located with the other official BLE services.

    Separating your custom code from the official code is good practice when working with any SDK, as @Awneil mentions. I would even argue it is the best practice, especially if you intend to work with others that are already familiar with the drivers you are modifying.

    Best regards,
    Karl

Children
Related