Home > Blockchain >  Float into uint8_t array
Float into uint8_t array

Time:12-02

I want to make 4 different ADC measurements. I want to be that those readed values are floats. After that I want to put those 4 float values in an uint8_t to send it over the function:

uint32_t ble_nus_data_send(ble_nus_t * p_nus,
                           uint8_t   * p_data,
                           uint16_t  * p_length,
                           uint16_t    conn_handle)

This minimal code works:

static void app_timer_handler(void * p_context)
{
  uint8_t p_dat[] = "hi";
  uint16_t len = sizeof(p_dat)-1;

  ret_code_t err_code = ble_nus_data_send(&m_nus, p_dat, &len, m_conn_handle);
  APP_ERROR_CHECK(err_code);
}

But when I try to send a val it goes wrong:

static void app_timer_handler(void * p_context)
{
  if(m_conn_handle != BLE_CONN_HANDLE_INVALID)
  {
    uint8_t values[20];

    ret_code_t err_code;

    err_code = nrfx_saadc_sample_convert(0, &m_sample);
    APP_ERROR_CHECK(err_code);
    float value1 = m_sample * 3.0 / 4096;

    sprintf((char*)values, "%.2f", value1);
    uint16_t len = sizeof(values);

    err_code = ble_nus_data_send(&m_nus, values, &len, m_conn_handle); 
    APP_ERROR_CHECK(err_code);
  }
}

After getting the sample value of the ADC I will make calculations to get the voltage. I read it out with a 12-bit adc.

The expected received output of the uint8_t must be like [float1 float2 float3 float4]. This because I want to process the values in Python and plot them in a graph.

To receive the sended data I do use a dongle.

I did try this:

static void app_timer_handler(void * p_context)
{
  if(m_conn_handle != BLE_CONN_HANDLE_INVALID)
  {
    float values[4];

    ret_code_t err_code;

    err_code = nrfx_saadc_sample_convert(0, &m_sample);
    APP_ERROR_CHECK(err_code);
    values[0] = m_sample * 3.0 / 4096;

    err_code = nrfx_saadc_sample_convert(1, &m_sample);
    APP_ERROR_CHECK(err_code);
    values[1] = m_sample * 3.0 / 4096;

    err_code = nrfx_saadc_sample_convert(2, &m_sample);
    APP_ERROR_CHECK(err_code);
    values[2] = m_sample * 3.0 / 4096;

    err_code = nrfx_saadc_sample_convert(3, &m_sample);
    APP_ERROR_CHECK(err_code);
    values[3] = m_sample * 3.0 / 4096;

    uint16_t len = sizeof(values);

    err_code = ble_nus_data_send(&m_nus, (uint8_t*)values, &len, m_conn_handle); 
    APP_ERROR_CHECK(err_code);
  }
}

Received values1

And also tried this:

static void app_timer_handler(void * p_context)
{
  if(m_conn_handle != BLE_CONN_HANDLE_INVALID)
  {
    uint8_t values[4];

    ret_code_t err_code;

    err_code = nrfx_saadc_sample_convert(0, &m_sample);
    APP_ERROR_CHECK(err_code);
    float value1 = m_sample * 3.0 / 4096;

    err_code = nrfx_saadc_sample_convert(1, &m_sample);
    APP_ERROR_CHECK(err_code);
    float value2 = m_sample * 3.0 / 4096;

    err_code = nrfx_saadc_sample_convert(2, &m_sample);
    APP_ERROR_CHECK(err_code);
    float value3 = m_sample * 3.0 / 4096;

    err_code = nrfx_saadc_sample_convert(3, &m_sample);
    APP_ERROR_CHECK(err_code);
    float value4 = m_sample * 3.0 / 4096;

    sprintf(values, "%.2f %.2f %.2f %.2f\n", value1, value2, value3, value4);
    uint16_t len = sizeof(values);

    err_code = ble_nus_data_send(&m_nus, (uint8_t*)values, &len, m_conn_handle); 
    APP_ERROR_CHECK(err_code);
  }
}

Received values2

Both ways didn't worked out for the output.

The output expected on Python is [val1 val2 val3 val4]. So the values can be seperated.

This is the function that handles the received data on the dongle.

static void ble_nus_chars_received_uart_print(uint8_t * p_data, uint16_t data_len)
{
    bsp_board_led_invert(LED_BLE_NUS_RX);
    NRF_LOG_DEBUG("Received data from BLE NUS. Writing data on CDC ACM.");
    NRF_LOG_HEXDUMP_DEBUG(p_data, data_len);
    memcpy(m_nus_data_array, p_data, data_len);

    // Add endline characters
    uint16_t length = data_len;
    if (length   sizeof(ENDLINE_STRING) < BLE_NUS_MAX_DATA_LEN)
    {
        memcpy(m_nus_data_array   length, ENDLINE_STRING, sizeof(ENDLINE_STRING));
        length  = sizeof(ENDLINE_STRING);
    }

    // Send data through CDC ACM
    ret_code_t ret = app_usbd_cdc_acm_write(&m_app_cdc_acm,
                                            m_nus_data_array,
                                            length);
    if(ret != NRF_SUCCESS)
    {
        NRF_LOG_INFO("CDC ACM unavailable, data received: %s", m_nus_data_array);
    }
}

The received values are random chars. I think this might be because the receiving function. Do I have to make changes there or somewhere else?

CodePudding user response:

You could send the float array as raw data, ie, the bytes they already are:

float values[4];

values[0] = sample * ...
values[1] = sample * ...
values[2] = sample * ...
values[3] = sample * ...

uint16_t d_len = sizeof(values);

err_code = ble_nus_data_send(&m_nus, (uint8_t *)values, &d_len, m_conn_handle); 
APP_ERROR_CHECK(err_code);

Note that a typical size of float is 4 bytes. Also, sending raw float values will work fine if the receiver is using the SAME floating point representation.

CodePudding user response:

This is not a full solution but shows errors in your code and a possible fix.

    uint8_t values[4];

This is an array of 4 bytes. It can hold a string of 3 characters and a terminating NUL ('\0') character.

    sprintf(values, "%.2f %.2f %.2f %.2f\n", value1, value2, value3, value4);

This will write many more characters, so it will write past the end of the array which is undefined behavior.

    uint16_t len = sizeof(values);

This is the size of the array which is 4. You probably need the number of characters which would be the return value from sprintf or could be obtained with strlen.

Incomplete and untested example:

    /* I did not check the maximum size for the format string.
     * Can probably be smaller. */
    uint8_t values[100];

/* ... */

    /* In contrast to sprintf, snprintf limits the number of characters including
     * the terminating '\0' to the specified size. Might not be necessary if you
     * correctly calculate the maximum possible string length and define the 
     * array size accordingly. */
    int bytes = snprintf(values, sizeof(values),
                         "%.2f %.2f %.2f %.2f\n", value1, value2, value3, value4);

    if(bytes < 0)
    {
        /* error occurred */
        bytes = 0;
    }
    else if(bytes >= sizeof(values))
    {
       /* output was truncated */
       bytes = sizeof(values) - 1;
    }
    uint16_t len = bytes;

    err_code = ble_nus_data_send(&m_nus, (uint8_t*)values, &len, m_conn_handle); 
  •  Tags:  
  • c
  • Related