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.

  • 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

Related