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.

  • Hello,

    Nats said:
    Sorry, if i wasn't clear, I'm very new to this whole concept

    No problem at all, do not worry. I did not mean to sound crass in my last reply, I just did not understand everything you were asking at first.

    Nats said:

    With regards to Question 1 snapshot, It is was just a demo code, to explain what i meant, when i said, sending three values in the same characteristics.

    (I thought of sending X and Y and Z, one after the other in this format, until the concept of packing was introduced.)

    Now I understand, thank you for explaining what you meant. Indeed it sounds like packing them into one characteristic is the best method to proceed with for your application.

    Nats said:
    In regards to Question2, Is there any other reference to explain more in detail regarding sending packed data. What are the functions in which the modifications have to be made, in order to achieve sending more than 8 bits. or array.

    I suppose the easiest way to proceed would be to leave it as is, and instead just have p_len point to the length of the data you are sending in bytes. So, for sending a uint64_t, you would need to have:

    uint16_t len = sizeof(uint64_t);
    hvx_params.p_len = &len;

    To see an example of how this can be done, you could check out the block starting on line 343 in the ble_bas.c source file.

    Best regards,
    Karl

  • Thank you, I tried editing this as per the tutorial you had sent. But it was not working. I am using custom ble code 128 bit UUID. And the function is as below,

    uint32_t ble_cus_custom_value_update(ble_cus_t * p_cus, uint8_t cust_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(uint8_t);
        gatts_value.offset  = 0;
        gatts_value.p_value = &cust_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;
        }

    And the calling function is as below,

    static void notification_timeout_handler(void * p_context)
    {
        UNUSED_PARAMETER(p_context);
        ret_code_t err_code;
        
        // Increment the value of m_custom_value before notifing it.
        m_custom_value+=2;
        err_code = ble_cus_custom_value_update(&m_cus, m_custom_value);
        APP_ERROR_CHECK(err_code);
    }

    I tried editing,    

    gatts_value.len     = sizeof(uint8_t);             --> gatts_value.len     = sizeof(uint64_t);   

    It dint work.

    So i changed only the 

      hvx_params.p_len  = &gatts_value.len;

    as per your suggestion, but once i make the changes, i dont get any notifications.

  • Hello,

    Sorry for my late reply - I was out of office yesterday due to travel.

    Could you show me the declaration of your m_custom_value variable?
    From your description and usage I would guess it is a global uint64_t.

    Nats said:

    I tried editing,    

    gatts_value.len     = sizeof(uint8_t);             --> gatts_value.len     = sizeof(uint64_t);   

    It dint work.

    What do you mean by "didnt work", please elaborate.
    Did you receive an error when compiling, or unexpected behavior at runtime?

    Nats said:

    So i changed only the 

      hvx_params.p_len  = &gatts_value.len;

    I do not understand exactly what you did here. You started with the code snippets you included in the comment, than you made the changes to gatts_value.len = sizeof(uint64_t) and it didnt work, so you only changed the hvx_params.p_len = &gatts_value.len?
    If so, the last change wont be any different, since you reverted the change to the gatts_value.len already.

    How often is your notification_timeout_handler being called?
    If you could share your entire project folder(as a .zip) file, or the entire main.c file, I could gain a better understanding of what you are attempting to do, and why it is not working.

    Looking forward to resolving this issue together,

    Best regards,
    Karl

  • Thank you  for your guidance,along with your suggestions, the attribute section also needed to be changed (the max.len) and now it works fine. 

    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. 
    I have attached the project.

    sending packed data.zip

  • 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

Related