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

  • 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();
        }
    }

  • Oh, I forgot to add the main.c file that I ended up with, where I split up the advertisement packet into advdata and srdata. Both in advertising_init() and in update_advertising_data().

    #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[24];                                            
    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;
        ble_advdata_t srdata;
    
        memset(&advdata, 0, sizeof(advdata));
        memset(&srdata, 0, sizeof(srdata));
    
        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);
    
        srdata.p_manuf_specific_data = &manuf_data;
    
        ble_advertising_init_t init;
        memset(&init, 0, sizeof(init));
    
        init.advdata = advdata;
        init.srdata = srdata;
        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_t srdata;
    
        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));
        memset(&srdata, 0, sizeof(srdata));
        advdata.name_type               = BLE_ADVDATA_FULL_NAME;
        advdata.include_appearance      = false;
        advdata.flags                   = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
        srdata.p_manuf_specific_data   = &manuf_data;
    
        err_code = ble_advertising_advdata_update(&m_advertising, &advdata, &srdata);
        APP_ERROR_CHECK(err_code);
    }
    
    void process_logs(void)
    {
        while (NRF_LOG_PROCESS())
        {
            // do nothing.
        }
    }
    
    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);
    
            memcpy(&m_adv_data[0],  &ax, 4); // since the size of a float is 4 bytes.
            memcpy(&m_adv_data[4],  &ay, 4);
            memcpy(&m_adv_data[8],  &az, 4);
            memcpy(&m_adv_data[12], &gx, 4);
            memcpy(&m_adv_data[16], &gy, 4);
            memcpy(&m_adv_data[20], &gz, 4);
    
            NRF_LOG_INFO("test");
            float testfloat;
            memcpy(&testfloat, &m_adv_data[8], 4);
            NRF_LOG_INFO("testfloat: " NRF_LOG_FLOAT_MARKER, NRF_LOG_FLOAT(testfloat));
            NRF_LOG_INFO("az:" NRF_LOG_FLOAT_MARKER, NRF_LOG_FLOAT(az));
    
            NRF_LOG_RAW_INFO("m_adv_data[] = ");
            for (int i=0; i<sizeof(m_adv_data); i++)
            {
              NRF_LOG_RAW_INFO("%02x:", m_adv_data[i]);
            }
            NRF_LOG_RAW_INFO("\r\n");
    
            update_advertising_data();
    
            process_logs();
    
            nrf_delay_ms(1000);
            idle_state_handle();
        }
    }
    

  • Hi Edvin, 

    Thank you so much for your help:) 

    What I'm trying to do with the acceleration and gyro is to use that data to predict some linear motion.

    Therefore, I can't receive acceleration and gyro values at different time. I also want to able to receive those data as soon as possible so that I have more accurate linear motion prediction.

    I'm able to use the code you modified and get the updated ACC and gyro values through BLE but the interval of those data is pretty long. 

    I'm using other dongle(NRF52840) to fetch the BLE transmitted from NRF52. I'm using Wireshark to get the data. 

    I think I might be better of modifying the code so that I can connect to the dongle by Bluetooth and transmit data with no restrictions. However, I'm not sure how to code this..

    Would you be able to guide me please? Thank you so much for your help!!!

  • Hello,

    I see. Yes. Using a connection instead of advertising allows you to get more data through. I suggest that you check out the ble_app_uart and ble_app_uart_c examples from the SDK. Instead of sending the data through your advertisements, you can just create an array uint8_t my_data[24], and update this array, and send it using ble_nus_data_send().

    You should be able to get a decent throughput using this method, so you can send the data many times per second. You will however have a defined latency. Something called "the connection interval". The connection interval is the amount of times that pass between every time the devices communicate. So if you queue up a packet, it will be sent the next connection interval. So if you are lucky, the queued packet will be sent less than 1ms after it is queued up, and if you are unlucky, you queue it up directly after the devices has communicated, meaning it is almost an entire connection interval until the next time it will be able to send the packet. 

    I think the default values should be quite sufficient, but let me know if you need it to be shorter, and you struggle to do so. By default you should see a connection interval of around 30ms. I don't know how frequent you intend to send the data?

    Best regards,

    Edvin

  • Hi Edvin,

    I made changes to my code. I followed your idea and I'm using GATT to update the data that I want to send out when the Bluetooth connection is made. I'm still not sure what you mean by the defined latency. 

    This is my current code but it seems like I'm not able to read the data that's being updated through Wireshark. Also, I'm not able to connect to the advertising ble device with nRF Connect on my phone. It's keep saying that it's connecting. After few seconds, I get an error in the terminal saying this: 

    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 "nrf_ble_gatt.h"
    #include "nrf_ble_qwr.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>
    
    #define DEVICE_NAME                     "MPU"
    #define APP_ADV_INTERVAL                300
    #define APP_ADV_DURATION                0
    #define APP_BLE_CONN_CFG_TAG            1
    #define APP_BLE_OBSERVER_PRIO           3
    
    #define TWI_SCL_PIN                     25
    #define TWI_SDA_PIN                     24
    
    #define gyroSENSITIVITY                 131.0f
    #define G_CONSTANT                      9.8f
    #define accSENSITIVITY                  16384.0f
    
    #define BLE_UUID_OUR_BASE_UUID          {0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x4A, 0xC3, 0x93, \
                                             0xE0, 0xA9, 0xE5, 0x0E, 0x24, 0xE7, 0xB5, 0x00} // 128-bit base UUID
    #define BLE_UUID_OUR_SERVICE            0x1400
    #define BLE_UUID_OUR_CHARACTERISTIC     0x1401
    
    BLE_ADVERTISING_DEF(m_advertising);
    NRF_BLE_GATT_DEF(m_gatt);
    NRF_BLE_QWR_DEF(m_qwr);
    
    static uint8_t m_adv_data[24];
    static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID;
    static ble_gatts_char_handles_t m_char_handles;
    static uint16_t m_service_handle;
    
    static void advertising_start(void);
    void update_characteristic_value(void);
    void mpu6050_data_update(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) {
        ret_code_t err_code;
    
        switch (p_ble_evt->header.evt_id) {
            case BLE_GAP_EVT_DISCONNECTED:
                NRF_LOG_INFO("Disconnected.");
                m_conn_handle = BLE_CONN_HANDLE_INVALID;
                advertising_start();
                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_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 services_init(void) {
        ret_code_t err_code;
        ble_uuid_t service_uuid;
        ble_uuid128_t base_uuid = BLE_UUID_OUR_BASE_UUID;
        service_uuid.uuid = BLE_UUID_OUR_SERVICE;
    
        err_code = sd_ble_uuid_vs_add(&base_uuid, &service_uuid.type);
        APP_ERROR_CHECK(err_code);
    
        err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &service_uuid, &m_service_handle);
        APP_ERROR_CHECK(err_code);
    
        // Add a characteristic to the service
        ble_gatts_char_md_t char_md;
        memset(&char_md, 0, sizeof(char_md));
        char_md.char_props.read = 1;
        char_md.char_props.write = 1;
        char_md.char_props.notify = 1;
    
        ble_uuid_t char_uuid;
        char_uuid.uuid = BLE_UUID_OUR_CHARACTERISTIC;
        char_uuid.type = service_uuid.type;
    
        ble_gatts_attr_md_t attr_md;
        memset(&attr_md, 0, sizeof(attr_md));
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm);
        attr_md.vloc = BLE_GATTS_VLOC_STACK;
    
        ble_gatts_attr_t attr_char_value;
        memset(&attr_char_value, 0, sizeof(attr_char_value));
        attr_char_value.p_uuid = &char_uuid;
        attr_char_value.p_attr_md = &attr_md;
        attr_char_value.init_len = sizeof(uint8_t) * 20;
        attr_char_value.init_offs = 0;
        attr_char_value.max_len = sizeof(uint8_t) * 20;
    
        err_code = sd_ble_gatts_characteristic_add(m_service_handle, &char_md, &attr_char_value, &m_char_handles);
        APP_ERROR_CHECK(err_code);
    }
    
    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;
        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);
    
        NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
    }
    
    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;
        err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);
        APP_ERROR_CHECK(err_code);
    }
    
    void mpu6050_data_update(void) {
        int16_t accel_data[3], gyro_data[3];
        float ax, ay, az, gx, gy, gz;
    
        read_mpu6050_data(accel_data, gyro_data);
    
        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);
    
        memcpy(&m_adv_data[0],  &ax, 4);
        memcpy(&m_adv_data[4],  &ay, 4);
        memcpy(&m_adv_data[8],  &az, 4);
        memcpy(&m_adv_data[12], &gx, 4);
        memcpy(&m_adv_data[16], &gy, 4);
        memcpy(&m_adv_data[20], &gz, 4);
    
        NRF_LOG_RAW_INFO("m_adv_data[] = ");
        for (int i = 0; i < sizeof(m_adv_data); i++) {
            NRF_LOG_RAW_INFO("%02x:", m_adv_data[i]);
        }
        NRF_LOG_RAW_INFO("\r\n");
    
        update_characteristic_value();
    }
    
    void update_characteristic_value(void) {
        if (m_conn_handle != BLE_CONN_HANDLE_INVALID) {
            uint16_t len = sizeof(m_adv_data);
            ble_gatts_hvx_params_t hvx_params;
            memset(&hvx_params, 0, sizeof(hvx_params));
    
            hvx_params.handle = m_char_handles.value_handle;
            hvx_params.type = BLE_GATT_HVX_NOTIFICATION;
            hvx_params.offset = 0;
            hvx_params.p_len = &len;
            hvx_params.p_data = m_adv_data;
    
            ret_code_t err_code = sd_ble_gatts_hvx(m_conn_handle, &hvx_params);
            if (err_code != NRF_SUCCESS) {
                NRF_LOG_ERROR("sd_ble_gatts_hvx failed: 0x%x", err_code);
            }
        }
    }
    
    int main(void) {
        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();
        services_init();
    
        advertising_start();
    
        while (true) {
            mpu6050_data_update();
    
            nrf_delay_ms(1000);
            idle_state_handle();
        }
    }
    

  • Hi,

    Edvin is out on vacation for a few more weeks, so this is just a heads up to let you know that it might take some time before we can follow up on this. We'll let you know more about a status/ETA next week. 

    Thank you for your patience.

    Kind regards,
    Andreas

Reply Children
No Data
Related