TWI Bluetooth transmittion problem.

Hi everyone,

I'm trying to send updated gyro and acceleration values from MPU6050 continuously by BLE function from nrf52832. I'm currently using the nrf52 development kit board to run this code. However, I'm getting a NRF_ERROR_DATA_SIZE.

This is the code:

#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include "nordic_common.h"
#include "nrf.h"
#include "app_error.h"
#include "ble.h"
#include "ble_hci.h"
#include "ble_srv_common.h"
#include "ble_advdata.h"
#include "ble_advertising.h"
#include "ble_conn_params.h"
#include "nrf_sdh.h"
#include "nrf_sdh_soc.h"
#include "nrf_sdh_ble.h"
#include "app_timer.h"
#include "nrf_pwr_mgmt.h"
#include "app_util_platform.h"
#include "nrf_drv_twi.h"
#include "nrf_delay.h"
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
#include "mpu6050.h"

#define DEVICE_NAME                     "MPU"                          
#define APP_ADV_INTERVAL                300                             
#define APP_ADV_DURATION                0                               
#define APP_BLE_CONN_CFG_TAG            1                               

#define TWI_SCL_PIN                     25                              
#define TWI_SDA_PIN                     24                              

BLE_ADVERTISING_DEF(m_advertising);                                      

static uint8_t m_adv_data[31];                                            
static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID;                  

static void advertising_start(void);

void twi_init(void) {
    ret_code_t err_code;

    const nrf_drv_twi_config_t twi_config = {
       .scl                = TWI_SCL_PIN,
       .sda                = TWI_SDA_PIN,
       .frequency          = NRF_TWI_FREQ_400K,
       .interrupt_priority = APP_IRQ_PRIORITY_HIGH,
       .clear_bus_init     = false
    };

    err_code = nrf_drv_twi_init(&m_twi, &twi_config, NULL, NULL);
    APP_ERROR_CHECK(err_code);

    nrf_drv_twi_enable(&m_twi);
}

static void on_adv_evt(ble_adv_evt_t ble_adv_evt) {
    switch (ble_adv_evt) {
        case BLE_ADV_EVT_FAST:
            NRF_LOG_INFO("Fast advertising.");
            break;
        case BLE_ADV_EVT_IDLE:
            advertising_start();
            break;
        default:
            break;
    }
}

static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context) {
    switch (p_ble_evt->header.evt_id) {
        case BLE_GAP_EVT_DISCONNECTED:
            NRF_LOG_INFO("Disconnected.");
            break;
        case BLE_GAP_EVT_CONNECTED:
            NRF_LOG_INFO("Connected.");
            m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
            break;
        default:
            break;
    }
}

static void gap_params_init(void) {
    ret_code_t err_code;
    ble_gap_conn_params_t gap_conn_params;
    ble_gap_conn_sec_mode_t sec_mode;

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);

    err_code = sd_ble_gap_device_name_set(&sec_mode,
                                          (const uint8_t *)DEVICE_NAME,
                                          strlen(DEVICE_NAME));
    APP_ERROR_CHECK(err_code);

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

    gap_conn_params.min_conn_interval = MSEC_TO_UNITS(100, UNIT_1_25_MS);
    gap_conn_params.max_conn_interval = MSEC_TO_UNITS(200, UNIT_1_25_MS);
    gap_conn_params.slave_latency     = 0;
    gap_conn_params.conn_sup_timeout  = MSEC_TO_UNITS(4000, UNIT_10_MS);

    err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
    APP_ERROR_CHECK(err_code);
}

static void advertising_init(void) {
    ret_code_t err_code;
    ble_advdata_t advdata;

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

    advdata.name_type               = BLE_ADVDATA_FULL_NAME;
    advdata.include_appearance      = false;
    advdata.flags                   = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;

    ble_advdata_manuf_data_t manuf_data;
    manuf_data.company_identifier = 0x0059; // Nordic Semiconductor company ID
    manuf_data.data.p_data = m_adv_data;
    manuf_data.data.size = sizeof(m_adv_data);

    advdata.p_manuf_specific_data = &manuf_data;

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

    init.advdata = advdata;
    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);
}

static void ble_stack_init(void) {
    ret_code_t err_code = nrf_sdh_enable_request();
    APP_ERROR_CHECK(err_code);

    uint32_t ram_start = 0x20001800;  // Adjusted RAM start
    err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_sdh_ble_enable(&ram_start);
    APP_ERROR_CHECK(err_code);
}

static void power_management_init(void) {
    ret_code_t err_code = nrf_pwr_mgmt_init();
    APP_ERROR_CHECK(err_code);
}

static void idle_state_handle(void) {
    if (NRF_LOG_PROCESS() == false) {
        nrf_pwr_mgmt_run();
    }
}

static void advertising_start(void) {
    ret_code_t err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);
    APP_ERROR_CHECK(err_code);
}

int main(void) {
    int16_t accel_data[3], gyro_data[3];

    APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
    NRF_LOG_DEFAULT_BACKENDS_INIT();

    NRF_LOG_INFO("MPU6050 BLE example started.");
    NRF_LOG_FLUSH();

    twi_init();
    mpu6050_init();

    power_management_init();
    ble_stack_init();
    gap_params_init();
    advertising_init();

    advertising_start();

    while (true) {
        read_mpu6050_data(accel_data, gyro_data);

        // Send only 0.2f values of acceleration and gyro data
        float ax = accel_data[0] / 16384.0;
        float ay = accel_data[1] / 16384.0;
        float az = accel_data[2] / 16384.0;
        float gx = gyro_data[0] / 131.0;
        float gy = gyro_data[1] / 131.0;
        float gz = gyro_data[2] / 131.0;

        // Prepare advertising data (in this example, ensure it fits in 31 bytes)
        memcpy(m_adv_data, &ax, sizeof(float));
        memcpy(m_adv_data + sizeof(float), &ay, sizeof(float));
        memcpy(m_adv_data + 2 * sizeof(float), &az, sizeof(float));
        memcpy(m_adv_data + 3 * sizeof(float), &gx, sizeof(float));
        memcpy(m_adv_data + 4 * sizeof(float), &gy, sizeof(float));
        memcpy(m_adv_data + 5 * sizeof(float), &gz, sizeof(float));

        NRF_LOG_INFO("ACC: X=%0.2f, Y=%0.2f, Z=%0.2f; GYRO: X=%0.2f, Y=%0.2f, Z=%0.2f",
                     ax, ay, az, gx, gy, gz);

        advertising_start();

        nrf_delay_ms(1000);
        idle_state_handle();
    }
}

Why am I not able to send acceleration and gyro values though BLE?

Thank you so much for the help.

Parents
  • Hello,

    It is difficult to say exactly what the issue is caused by based on the file that you sent. Does the log say anything about where this error was coming from?

    I do see, however, that you are setting your:

        ble_advdata_manuf_data_t manuf_data;
        manuf_data.company_identifier = 0x0059; // Nordic Semiconductor company ID
        manuf_data.data.p_data = m_adv_data;
        manuf_data.data.size = sizeof(m_adv_data);
    

    and the m_adv_data is a 31 byte array.

    It is correct that you have 31 bytes at your disposal, but two of these bytes will be the company identifier, one byte will be the manufacturer_specific data length.

    I believe the scan response packet will look like: <type><length><company_identifier><payload>

    So 1 byte for type, 1 byte for length, 2 bytes for company_identifier, this leaves you with 31-1-1-2 = 27 bytes for manufacturer data payload. Try to reduce the m_adv_data array to this size, and keep reducing it if you still get the same error. Or even better, reduce it to the amount of bytes you actually read from your sensor. A float takes 4 bytes. So if you try to push 6 float numbers, that is 24 bytes. 

    Best regards,

    Edvin

Reply
  • Hello,

    It is difficult to say exactly what the issue is caused by based on the file that you sent. Does the log say anything about where this error was coming from?

    I do see, however, that you are setting your:

        ble_advdata_manuf_data_t manuf_data;
        manuf_data.company_identifier = 0x0059; // Nordic Semiconductor company ID
        manuf_data.data.p_data = m_adv_data;
        manuf_data.data.size = sizeof(m_adv_data);
    

    and the m_adv_data is a 31 byte array.

    It is correct that you have 31 bytes at your disposal, but two of these bytes will be the company identifier, one byte will be the manufacturer_specific data length.

    I believe the scan response packet will look like: <type><length><company_identifier><payload>

    So 1 byte for type, 1 byte for length, 2 bytes for company_identifier, this leaves you with 31-1-1-2 = 27 bytes for manufacturer data payload. Try to reduce the m_adv_data array to this size, and keep reducing it if you still get the same error. Or even better, reduce it to the amount of bytes you actually read from your sensor. A float takes 4 bytes. So if you try to push 6 float numbers, that is 24 bytes. 

    Best regards,

    Edvin

Children
  • I made m_adv_data as 20 byte array. It seems like I'm not getting the data issue.

    However, I'm getting another issue. I'm not able to output ACC and gyro values through LOG. I know that my sensor is working properly. I think there's something wrong with the code. This is the error:

    This is my current code:

    #include <stdbool.h>
    #include <stdint.h>
    #include <string.h>
    #include "nordic_common.h"
    #include "nrf.h"
    #include "app_error.h"
    #include "ble.h"
    #include "ble_hci.h"
    #include "ble_srv_common.h"
    #include "ble_advdata.h"
    #include "ble_advertising.h"
    #include "ble_conn_params.h"
    #include "nrf_sdh.h"
    #include "nrf_sdh_soc.h"
    #include "nrf_sdh_ble.h"
    #include "app_timer.h"
    #include "nrf_pwr_mgmt.h"
    #include "app_util_platform.h"
    #include "nrf_drv_twi.h"
    #include "nrf_delay.h"
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    #include "mpu6050.h"
    #include <math.h>  // Include this for M_PI(pi)
    
    #define DEVICE_NAME                     "MPU"                          
    #define APP_ADV_INTERVAL                300                             
    #define APP_ADV_DURATION                0                               
    #define APP_BLE_CONN_CFG_TAG            1                               
    
    #define TWI_SCL_PIN                     25                              
    #define TWI_SDA_PIN                     24                              
    
    #define gyroSENSITIVITY                 131.0f
    #define G_CONSTANT                      9.81f
    #define accSENSITIVITY                  16384.0f
    
    BLE_ADVERTISING_DEF(m_advertising);                                      
    
    static uint8_t m_adv_data[20];                                            
    static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID;                  
    static char log_buffer[256];
    
    static void advertising_start(void);
    
    void twi_init(void) {
        ret_code_t err_code;
    
        const nrf_drv_twi_config_t twi_config = {
           .scl                = TWI_SCL_PIN,
           .sda                = TWI_SDA_PIN,
           .frequency          = NRF_TWI_FREQ_400K,
           .interrupt_priority = APP_IRQ_PRIORITY_HIGH,
           .clear_bus_init     = false
        };
    
        err_code = nrf_drv_twi_init(&m_twi, &twi_config, NULL, NULL);
        APP_ERROR_CHECK(err_code);
    
        nrf_drv_twi_enable(&m_twi);
    }
    
    static void on_adv_evt(ble_adv_evt_t ble_adv_evt) {
        switch (ble_adv_evt) {
            case BLE_ADV_EVT_FAST:
                NRF_LOG_INFO("Fast advertising.");
                break;
            case BLE_ADV_EVT_IDLE:
                advertising_start();
                break;
            default:
                break;
        }
    }
    
    static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context) {
        switch (p_ble_evt->header.evt_id) {
            case BLE_GAP_EVT_DISCONNECTED:
                NRF_LOG_INFO("Disconnected.");
                break;
            case BLE_GAP_EVT_CONNECTED:
                NRF_LOG_INFO("Connected.");
                m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
                break;
            default:
                break;
        }
    }
    
    static void gap_params_init(void) {
        ret_code_t err_code;
        ble_gap_conn_params_t gap_conn_params;
        ble_gap_conn_sec_mode_t sec_mode;
    
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
    
        err_code = sd_ble_gap_device_name_set(&sec_mode,
                                              (const uint8_t *)DEVICE_NAME,
                                              strlen(DEVICE_NAME));
        APP_ERROR_CHECK(err_code);
    
        memset(&gap_conn_params, 0, sizeof(gap_conn_params));
    
        gap_conn_params.min_conn_interval = MSEC_TO_UNITS(100, UNIT_1_25_MS);
        gap_conn_params.max_conn_interval = MSEC_TO_UNITS(200, UNIT_1_25_MS);
        gap_conn_params.slave_latency     = 0;
        gap_conn_params.conn_sup_timeout  = MSEC_TO_UNITS(4000, UNIT_10_MS);
    
        err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
        APP_ERROR_CHECK(err_code);
    }
    
    static void advertising_init(void) {
        ret_code_t err_code;
        ble_advdata_t advdata;
    
        memset(&advdata, 0, sizeof(advdata));
    
        advdata.name_type               = BLE_ADVDATA_FULL_NAME;
        advdata.include_appearance      = false;
        advdata.flags                   = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
    
        ble_advdata_manuf_data_t manuf_data;
        manuf_data.company_identifier = 0x0059; // Nordic Semiconductor company ID
        manuf_data.data.p_data = m_adv_data;
        manuf_data.data.size = sizeof(m_adv_data);
    
        advdata.p_manuf_specific_data = &manuf_data;
    
        ble_advertising_init_t init;
        memset(&init, 0, sizeof(init));
    
        init.advdata = advdata;
        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);
    }
    
    static void ble_stack_init(void) {
        ret_code_t err_code = nrf_sdh_enable_request();
        APP_ERROR_CHECK(err_code);
    
        uint32_t ram_start = 0x20001800;  // Adjusted RAM start
        err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_sdh_ble_enable(&ram_start);
        APP_ERROR_CHECK(err_code);
    }
    
    static void power_management_init(void) {
        ret_code_t err_code = nrf_pwr_mgmt_init();
        APP_ERROR_CHECK(err_code);
    }
    
    static void idle_state_handle(void) {
        if (NRF_LOG_PROCESS() == false) {
            nrf_pwr_mgmt_run();
        }
    }
    
    static void advertising_start(void) {
        ret_code_t err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);
        APP_ERROR_CHECK(err_code);
    }
    
    // Function to pack scaled float data into an array as int16_t
    void pack_scaled_data(uint8_t *buffer, float value, uint8_t *offset) {
        int16_t scaled_value = (int16_t)(value * 10);  // Scale to 1 decimal place
        buffer[*offset] = (scaled_value >> 8) & 0xFF;
        buffer[*offset + 1] = scaled_value & 0xFF;
        *offset += 2;
    }
    
    void update_advertising_data(void) {
        ret_code_t err_code;
        ble_advdata_t advdata;
    
        ble_advdata_manuf_data_t manuf_data;
        manuf_data.company_identifier = 0x0059;
        manuf_data.data.p_data = m_adv_data;
        manuf_data.data.size = sizeof(m_adv_data);
    
        memset(&advdata, 0, sizeof(advdata));
        advdata.name_type               = BLE_ADVDATA_FULL_NAME;
        advdata.include_appearance      = false;
        advdata.flags                   = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
        advdata.p_manuf_specific_data   = &manuf_data;
    
        err_code = ble_advertising_advdata_update(&m_advertising, &advdata, NULL);
        APP_ERROR_CHECK(err_code);
    }
    
    int main(void) {
        int16_t accel_data[3], gyro_data[3];
    
        APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    
        NRF_LOG_INFO("MPU6050 BLE example started.");
        NRF_LOG_FLUSH();
    
        twi_init();
        mpu6050_init();
    
        power_management_init();
        ble_stack_init();
        gap_params_init();
        advertising_init();
    
        advertising_start();
    
        while (true) {
            read_mpu6050_data(accel_data, gyro_data);
    
            float ax = ((float)accel_data[0] / accSENSITIVITY) * G_CONSTANT;
            float ay = ((float)accel_data[1] / accSENSITIVITY) * G_CONSTANT;
            float az = ((float)accel_data[2] / accSENSITIVITY) * G_CONSTANT;
            float gx = ((float)gyro_data[0] / gyroSENSITIVITY) * (M_PI / 180);
            float gy = ((float)gyro_data[1] / gyroSENSITIVITY) * (M_PI / 180);
            float gz = ((float)gyro_data[2] / gyroSENSITIVITY) * (M_PI / 180);
    
            snprintf(log_buffer, sizeof(log_buffer), "ACC: X=%0.1f, Y=%0.1f, Z=%0.1f; GYRO: X=%0.1f, Y=%0.1f, Z=%0.1f",
                     ax, ay, az, gx, gy, gz);
            NRF_LOG_INFO("%s", NRF_LOG_PUSH(log_buffer));
    
            uint8_t offset = 0;
            // Pack acceleration data
            pack_scaled_data(m_adv_data, ax, &offset);
            pack_scaled_data(m_adv_data, ay, &offset);
            pack_scaled_data(m_adv_data, az, &offset);
            // Pack gyroscope data
            pack_scaled_data(m_adv_data, gx, &offset);
            pack_scaled_data(m_adv_data, gy, &offset);
            pack_scaled_data(m_adv_data, gz, &offset);
    
            update_advertising_data();
    
            nrf_delay_ms(1000);
            idle_state_handle();
        }
    }

  • The way float numbers are handled on embedded devices is often a little different. And also in the NRF_LOG module.

    Try printing them using this:

    NRF_LOG_INFO("My float number: " NRF_LOG_FLOAT_MARKER "\r\n", NRF_LOG_FLOAT(ax));

    Does that work?

    BR,
    Edvin

  • I made a change and I get an error.

    This is the error:

    This is my current code:

    #include <stdbool.h>
    #include <stdint.h>
    #include <string.h>
    #include "nordic_common.h"
    #include "nrf.h"
    #include "app_error.h"
    #include "ble.h"
    #include "ble_hci.h"
    #include "ble_srv_common.h"
    #include "ble_advdata.h"
    #include "ble_advertising.h"
    #include "ble_conn_params.h"
    #include "nrf_sdh.h"
    #include "nrf_sdh_soc.h"
    #include "nrf_sdh_ble.h"
    #include "app_timer.h"
    #include "nrf_pwr_mgmt.h"
    #include "app_util_platform.h"
    #include "nrf_drv_twi.h"
    #include "nrf_delay.h"
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    #include "mpu6050.h"
    #include <math.h>  // Include this for M_PI(pi)
    
    #define DEVICE_NAME                     "MPU"                          
    #define APP_ADV_INTERVAL                300                             
    #define APP_ADV_DURATION                0                               
    #define APP_BLE_CONN_CFG_TAG            1                               
    
    #define TWI_SCL_PIN                     25                              
    #define TWI_SDA_PIN                     24                              
    
    #define gyroSENSITIVITY                 131.0f
    #define G_CONSTANT                      9.81f
    #define accSENSITIVITY                  16384.0f
    
    BLE_ADVERTISING_DEF(m_advertising);                                      
    
    static uint8_t m_adv_data[20];                                            
    static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID;                  
    static char log_buffer[256];
    
    static void advertising_start(void);
    
    void twi_init(void) {
        ret_code_t err_code;
    
        const nrf_drv_twi_config_t twi_config = {
           .scl                = TWI_SCL_PIN,
           .sda                = TWI_SDA_PIN,
           .frequency          = NRF_TWI_FREQ_400K,
           .interrupt_priority = APP_IRQ_PRIORITY_HIGH,
           .clear_bus_init     = false
        };
    
        err_code = nrf_drv_twi_init(&m_twi, &twi_config, NULL, NULL);
        APP_ERROR_CHECK(err_code);
    
        nrf_drv_twi_enable(&m_twi);
    }
    
    static void on_adv_evt(ble_adv_evt_t ble_adv_evt) {
        switch (ble_adv_evt) {
            case BLE_ADV_EVT_FAST:
                NRF_LOG_INFO("Fast advertising.");
                break;
            case BLE_ADV_EVT_IDLE:
                advertising_start();
                break;
            default:
                break;
        }
    }
    
    static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context) {
        switch (p_ble_evt->header.evt_id) {
            case BLE_GAP_EVT_DISCONNECTED:
                NRF_LOG_INFO("Disconnected.");
                break;
            case BLE_GAP_EVT_CONNECTED:
                NRF_LOG_INFO("Connected.");
                m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
                break;
            default:
                break;
        }
    }
    
    static void gap_params_init(void) {
        ret_code_t err_code;
        ble_gap_conn_params_t gap_conn_params;
        ble_gap_conn_sec_mode_t sec_mode;
    
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
    
        err_code = sd_ble_gap_device_name_set(&sec_mode,
                                              (const uint8_t *)DEVICE_NAME,
                                              strlen(DEVICE_NAME));
        APP_ERROR_CHECK(err_code);
    
        memset(&gap_conn_params, 0, sizeof(gap_conn_params));
    
        gap_conn_params.min_conn_interval = MSEC_TO_UNITS(100, UNIT_1_25_MS);
        gap_conn_params.max_conn_interval = MSEC_TO_UNITS(200, UNIT_1_25_MS);
        gap_conn_params.slave_latency     = 0;
        gap_conn_params.conn_sup_timeout  = MSEC_TO_UNITS(4000, UNIT_10_MS);
    
        err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
        APP_ERROR_CHECK(err_code);
    }
    
    static void advertising_init(void) {
        ret_code_t err_code;
        ble_advdata_t advdata;
    
        memset(&advdata, 0, sizeof(advdata));
    
        advdata.name_type               = BLE_ADVDATA_FULL_NAME;
        advdata.include_appearance      = false;
        advdata.flags                   = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
    
        ble_advdata_manuf_data_t manuf_data;
        manuf_data.company_identifier = 0x0059; // Nordic Semiconductor company ID
        manuf_data.data.p_data = m_adv_data;
        manuf_data.data.size = sizeof(m_adv_data);
    
        advdata.p_manuf_specific_data = &manuf_data;
    
        ble_advertising_init_t init;
        memset(&init, 0, sizeof(init));
    
        init.advdata = advdata;
        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);
    }
    
    static void ble_stack_init(void) {
        ret_code_t err_code = nrf_sdh_enable_request();
        APP_ERROR_CHECK(err_code);
    
        uint32_t ram_start = 0x20001800;  // Adjusted RAM start
        err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_sdh_ble_enable(&ram_start);
        APP_ERROR_CHECK(err_code);
    }
    
    static void power_management_init(void) {
        ret_code_t err_code = nrf_pwr_mgmt_init();
        APP_ERROR_CHECK(err_code);
    }
    
    static void idle_state_handle(void) {
        if (NRF_LOG_PROCESS() == false) {
            nrf_pwr_mgmt_run();
        }
    }
    
    static void advertising_start(void) {
        ret_code_t err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);
        APP_ERROR_CHECK(err_code);
    }
    
    // Function to pack scaled float data into an array as int16_t
    void pack_scaled_data(uint8_t *buffer, float value, uint8_t *offset) {
        int16_t scaled_value = (int16_t)(value * 10);  // Scale to 1 decimal place
        buffer[*offset] = (scaled_value >> 8) & 0xFF;
        buffer[*offset + 1] = scaled_value & 0xFF;
        *offset += 2;
    }
    
    void update_advertising_data(void) {
        ret_code_t err_code;
        ble_advdata_t advdata;
    
        ble_advdata_manuf_data_t manuf_data;
        manuf_data.company_identifier = 0x0059;
        manuf_data.data.p_data = m_adv_data;
        manuf_data.data.size = sizeof(m_adv_data);
    
        memset(&advdata, 0, sizeof(advdata));
        advdata.name_type               = BLE_ADVDATA_FULL_NAME;
        advdata.include_appearance      = false;
        advdata.flags                   = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
        advdata.p_manuf_specific_data   = &manuf_data;
    
        err_code = ble_advertising_advdata_update(&m_advertising, &advdata, NULL);
        APP_ERROR_CHECK(err_code);
    }
    
    int main(void) {
        int16_t accel_data[3], gyro_data[3];
        float ax, ay, az, gx, gy, gz;
    
        APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    
        NRF_LOG_INFO("MPU6050 BLE example started.");
        NRF_LOG_FLUSH();
    
        twi_init();
        mpu6050_init();
    
        power_management_init();
        ble_stack_init();
        gap_params_init();
        advertising_init();
    
        advertising_start();
    
        while (true) {
            read_mpu6050_data(accel_data, gyro_data);
    
            // Log raw data for debugging
            NRF_LOG_INFO("Raw ACC: X=%d, Y=%d, Z=%d; Raw GYRO: X=%d, Y=%d, Z=%d",
                         accel_data[0], accel_data[1], accel_data[2],
                         gyro_data[0], gyro_data[1], gyro_data[2]);
    
            ax = ((float)accel_data[0] / accSENSITIVITY) * G_CONSTANT;
            ay = ((float)accel_data[1] / accSENSITIVITY) * G_CONSTANT;
            az = ((float)accel_data[2] / accSENSITIVITY) * G_CONSTANT;
            gx = ((float)gyro_data[0] / gyroSENSITIVITY) * (M_PI / 180);
            gy = ((float)gyro_data[1] / gyroSENSITIVITY) * (M_PI / 180);
            gz = ((float)gyro_data[2] / gyroSENSITIVITY) * (M_PI / 180);
    
            // Log calculated values using NRF_LOG_FLOAT_MARKER and NRF_LOG_FLOAT
            NRF_LOG_INFO("Calculated ACC: X=" NRF_LOG_FLOAT_MARKER ", Y=" NRF_LOG_FLOAT_MARKER ", Z=" NRF_LOG_FLOAT_MARKER, NRF_LOG_FLOAT(ax), NRF_LOG_FLOAT(ay), NRF_LOG_FLOAT(az));
            NRF_LOG_INFO("Calculated GYRO: X=" NRF_LOG_FLOAT_MARKER ", Y=" NRF_LOG_FLOAT_MARKER ", Z=" NRF_LOG_FLOAT_MARKER, NRF_LOG_FLOAT(gx), NRF_LOG_FLOAT(gy), NRF_LOG_FLOAT(gz));
    
    
            uint8_t offset = 0;
            // Pack acceleration data
            pack_scaled_data(m_adv_data, ax, &offset);
            pack_scaled_data(m_adv_data, ay, &offset);
            pack_scaled_data(m_adv_data, az, &offset);
            // Pack gyroscope data
            pack_scaled_data(m_adv_data, gx, &offset);
            pack_scaled_data(m_adv_data, gy, &offset);
            pack_scaled_data(m_adv_data, gz, &offset);
    
            update_advertising_data();
    
            nrf_delay_ms(1000);
            idle_state_handle();
        }
    }
    

  • Unless you actually intend to do any calculations on the floating numbers, you probably don't need to print them in the log. If the goal is to just send them over bluetooth either way. However, if you want to log them, please try to split up your problem. Try to strip out the accellerometer, and just try to print a floating number in the log. I got it working using:

    #define ACCSENSITIVITY 16384.0f
    #define GCONSTANT 9.81f
    
    int main(void)
    {
        ...
        
        float my_float = 32768.14;
        float ax = ((float)my_float / ACCSENSITIVITY * GCONSTANT);
        NRF_LOG_INFO("floating number:" NRF_LOG_FLOAT_MARKER "\r\n", NRF_LOG_FLOAT(ax));
        // Enter main loop.
        for (;;)
        {
            idle_state_handle();
        }

    Perhaps your log message is too long. Try printing only one at the time.

    Best regards,

    Edvin

  • Thank you so much for your help! 

    I currently having a problem with sending ax,ay,az,gx,gy,gz values through BLE.

    This is what acceleration and gyro values that should be sent out by BLE:

    However, this is a snapshot of data that's sent through BLE. I used Wireshark to get this data:

    Frame 723682: 63 bytes on wire (504 bits), 63 bytes captured (504 bits) on interface COM8-4.2, id 0
        Section number: 1
        Interface id: 0 (COM8-4.2)
        Encapsulation type: nRF Sniffer for Bluetooth LE (186)
        Arrival Time: Jun 21, 2024 18:27:41.048745000 중부 일광 절약 시간
        UTC Arrival Time: Jun 21, 2024 23:27:41.048745000 UTC
        Epoch Arrival Time: 1719012461.048745000
        [Time shift for this packet: 0.000000000 seconds]
        [Time delta from previous captured frame: 0.000755000 seconds]
        [Time delta from previous displayed frame: 0.000755000 seconds]
        [Time since reference or first frame: 3786.864048000 seconds]
        Frame Number: 723682
        Frame Length: 63 bytes (504 bits)
        Capture Length: 63 bytes (504 bits)
        [Frame is marked: False]
        [Frame is ignored: False]
        [Protocols in frame: nordic_ble:btle:btcommon]
    nRF Sniffer for Bluetooth LE
        Board: 8
        Header Version: 3, Packet counter: 6013
            Length of payload: 56
            Protocol version: 3
            Packet counter: 6013
            Packet ID: 2
        Length of packet: 10
        Flags: 0x01
            .... ...1 = CRC: Ok
            .... ..0. = Reserved: 0
            .... .0.. = Reserved: 0
            .... 0... = Address Resolved: No
            .000 .... = PHY: LE 1M (0)
            0... .... = Reserved: 0
        Channel Index: 39
        RSSI: -51 dBm
        Event counter: 0
        Timestamp: 76326918µs
        [Packet time (start to end): 376µs]
        [Delta time (end to start): 579µs]
        [Delta time (start to start): 755µs]
    Bluetooth Low Energy Link Layer
        Access Address: 0x8e89bed6
        Packet Header: 0x2560 (PDU Type: ADV_IND, ChSel: #2, TxAdd: Random)
        Advertising Address: cc:69:fe:c9:06:21 (cc:69:fe:c9:06:21)
        Advertising Data
            Flags
                Length: 2
                Type: Flags (0x01)
                000. .... = Reserved: 0x0
                ...0 .... = Simultaneous LE and BR/EDR to Same Device Capable (Host): false (0x0)
                .... 0... = Simultaneous LE and BR/EDR to Same Device Capable (Controller): false (0x0)
                .... .1.. = BR/EDR Not Supported: true (0x1)
                .... ..1. = LE General Discoverable Mode: true (0x1)
                .... ...0 = LE Limited Discoverable Mode: false (0x0)
            Manufacturer Specific
                Length: 23
                Type: Manufacturer Specific (0xff)
                Company ID: Nordic Semiconductor ASA (0x0059)
                Data: 0024ffbd03760000000000000000000000000000
                    [Expert Info (Note/Undecoded): Undecoded]
            Device Name (shortened): MP
                Length: 3
                Type: Device Name (shortened) (0x08)
                Device Name: MP
        CRC: 0xca4899
    
    I don't think I'm sending correct acceleration and gyro values through BLE.

    This is my current code:

    #include <stdbool.h>
    #include <stdint.h>
    #include <string.h>
    #include "nordic_common.h"
    #include "nrf.h"
    #include "app_error.h"
    #include "ble.h"
    #include "ble_hci.h"
    #include "ble_srv_common.h"
    #include "ble_advdata.h"
    #include "ble_advertising.h"
    #include "ble_conn_params.h"
    #include "nrf_sdh.h"
    #include "nrf_sdh_soc.h"
    #include "nrf_sdh_ble.h"
    #include "app_timer.h"
    #include "nrf_pwr_mgmt.h"
    #include "app_util_platform.h"
    #include "nrf_drv_twi.h"
    #include "nrf_delay.h"
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    #include "mpu6050.h"
    #include <math.h>  // Include this for M_PI(pi)
    
    #define DEVICE_NAME                     "MPU"                          
    #define APP_ADV_INTERVAL                300                             
    #define APP_ADV_DURATION                0                               
    #define APP_BLE_CONN_CFG_TAG            1                               
    
    #define TWI_SCL_PIN                     25                              
    #define TWI_SDA_PIN                     24                              
    
    #define gyroSENSITIVITY                 131.0f
    #define G_CONSTANT                      9.8f
    #define accSENSITIVITY                  16384.0f
    
    BLE_ADVERTISING_DEF(m_advertising);                                      
    
    static uint8_t m_adv_data[20];                                            
    static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID;                  
    static char log_buffer[256];
    
    static void advertising_start(void);
    
    void twi_init(void) {
        ret_code_t err_code;
    
        const nrf_drv_twi_config_t twi_config = {
           .scl                = TWI_SCL_PIN,
           .sda                = TWI_SDA_PIN,
           .frequency          = NRF_TWI_FREQ_400K,
           .interrupt_priority = APP_IRQ_PRIORITY_HIGH,
           .clear_bus_init     = false
        };
    
        err_code = nrf_drv_twi_init(&m_twi, &twi_config, NULL, NULL);
        APP_ERROR_CHECK(err_code);
    
        nrf_drv_twi_enable(&m_twi);
    }
    
    static void on_adv_evt(ble_adv_evt_t ble_adv_evt) {
        switch (ble_adv_evt) {
            case BLE_ADV_EVT_FAST:
                NRF_LOG_INFO("Fast advertising.");
                break;
            case BLE_ADV_EVT_IDLE:
                advertising_start();
                break;
            default:
                break;
        }
    }
    
    static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context) {
        switch (p_ble_evt->header.evt_id) {
            case BLE_GAP_EVT_DISCONNECTED:
                NRF_LOG_INFO("Disconnected.");
                break;
            case BLE_GAP_EVT_CONNECTED:
                NRF_LOG_INFO("Connected.");
                m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
                break;
            default:
                break;
        }
    }
    
    static void gap_params_init(void) {
        ret_code_t err_code;
        ble_gap_conn_params_t gap_conn_params;
        ble_gap_conn_sec_mode_t sec_mode;
    
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
    
        err_code = sd_ble_gap_device_name_set(&sec_mode,
                                              (const uint8_t *)DEVICE_NAME,
                                              strlen(DEVICE_NAME));
        APP_ERROR_CHECK(err_code);
    
        memset(&gap_conn_params, 0, sizeof(gap_conn_params));
    
        gap_conn_params.min_conn_interval = MSEC_TO_UNITS(100, UNIT_1_25_MS);
        gap_conn_params.max_conn_interval = MSEC_TO_UNITS(200, UNIT_1_25_MS);
        gap_conn_params.slave_latency     = 0;
        gap_conn_params.conn_sup_timeout  = MSEC_TO_UNITS(4000, UNIT_10_MS);
    
        err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
        APP_ERROR_CHECK(err_code);
    }
    
    static void advertising_init(void) {
        ret_code_t err_code;
        ble_advdata_t advdata;
    
        memset(&advdata, 0, sizeof(advdata));
    
        advdata.name_type               = BLE_ADVDATA_FULL_NAME;
        advdata.include_appearance      = false;
        advdata.flags                   = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
    
        ble_advdata_manuf_data_t manuf_data;
        manuf_data.company_identifier = 0x0059; // Nordic Semiconductor company ID
        manuf_data.data.p_data = m_adv_data;
        manuf_data.data.size = sizeof(m_adv_data);
    
        advdata.p_manuf_specific_data = &manuf_data;
    
        ble_advertising_init_t init;
        memset(&init, 0, sizeof(init));
    
        init.advdata = advdata;
        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);
    }
    
    static void ble_stack_init(void) {
        ret_code_t err_code = nrf_sdh_enable_request();
        APP_ERROR_CHECK(err_code);
    
        uint32_t ram_start = 0x20001800;  // Adjusted RAM start
        err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_sdh_ble_enable(&ram_start);
        APP_ERROR_CHECK(err_code);
    }
    
    static void power_management_init(void) {
        ret_code_t err_code = nrf_pwr_mgmt_init();
        APP_ERROR_CHECK(err_code);
    }
    
    static void idle_state_handle(void) {
        if (NRF_LOG_PROCESS() == false) {
            nrf_pwr_mgmt_run();
        }
    }
    
    static void advertising_start(void) {
        ret_code_t err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);
        APP_ERROR_CHECK(err_code);
    }
    
    void update_advertising_data(void) {
        ret_code_t err_code;
        ble_advdata_t advdata;
    
        ble_advdata_manuf_data_t manuf_data;
        manuf_data.company_identifier = 0x0059;
        manuf_data.data.p_data = m_adv_data;
        manuf_data.data.size = sizeof(m_adv_data);
    
        memset(&advdata, 0, sizeof(advdata));
        advdata.name_type               = BLE_ADVDATA_FULL_NAME;
        advdata.include_appearance      = false;
        advdata.flags                   = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
        advdata.p_manuf_specific_data   = &manuf_data;
    
        err_code = ble_advertising_advdata_update(&m_advertising, &advdata, NULL);
        APP_ERROR_CHECK(err_code);
    }
    
    int main(void) {
        int16_t accel_data[3], gyro_data[3];
        float ax, ay, az, gx, gy, gz;
    
        APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    
        NRF_LOG_INFO("MPU6050 BLE example started.");
        NRF_LOG_FLUSH();
    
        twi_init();
        mpu6050_init();
    
        power_management_init();
        ble_stack_init();
        gap_params_init();
        advertising_init();
    
        advertising_start();
    
        while (true) {
            read_mpu6050_data(accel_data, gyro_data);
    
            // Log raw data for debugging
            NRF_LOG_INFO("Raw ACC: X=%d, Y=%d, Z=%d; Raw GYRO: X=%d, Y=%d, Z=%d",
                         accel_data[0], accel_data[1], accel_data[2],
                         gyro_data[0], gyro_data[1], gyro_data[2]);
    
            ax = ((float)accel_data[0] / accSENSITIVITY) * G_CONSTANT;
            ay = ((float)accel_data[1] / accSENSITIVITY) * G_CONSTANT;
            az = ((float)accel_data[2] / accSENSITIVITY) * G_CONSTANT;
            gx = ((float)gyro_data[0] / gyroSENSITIVITY) * (M_PI / 180);
            gy = ((float)gyro_data[1] / gyroSENSITIVITY) * (M_PI / 180);
            gz = ((float)gyro_data[2] / gyroSENSITIVITY) * (M_PI / 180);
    
    
            uint8_t offset = 0;
            // Directly update m_adv_data array with scaled values
            int16_t scaled_value;
    
            scaled_value = (int16_t)(ax*100);
            m_adv_data[offset++] = (scaled_value >> 8) & 0xFF;
            m_adv_data[offset++] = scaled_value & 0xFF;
    
            scaled_value = (int16_t)(ay*100);
            m_adv_data[offset++] = (scaled_value >> 8) & 0xFF;
            m_adv_data[offset++] = scaled_value & 0xFF;
    
            scaled_value = (int16_t)(az*100);
            m_adv_data[offset++] = (scaled_value >> 8) & 0xFF;
            m_adv_data[offset++] = scaled_value & 0xFF;
    
            scaled_value = (int16_t)(gx*100);
            m_adv_data[offset++] = (scaled_value >> 8) & 0xFF;
            m_adv_data[offset++] = scaled_value & 0xFF;
    
            scaled_value = (int16_t)(gy*100);
            m_adv_data[offset++] = (scaled_value >> 8) & 0xFF;
            m_adv_data[offset++] = scaled_value & 0xFF;
    
            scaled_value = (int16_t)(gz*100);
            m_adv_data[offset++] = (scaled_value >> 8) & 0xFF;
            m_adv_data[offset++] = scaled_value & 0xFF;
    
            update_advertising_data();
    
            nrf_delay_ms(1000);
            idle_state_handle();
        }
    }
    

    Thank you for helping me!

Related