Bosch Sensortec Community

    cancel
    Showing results for 
    Search instead for 
    Did you mean: 

    BMG250 API Support - bmg_init() error

    mrlcollado
    New Poster

    BMG250 API Support - bmg_init() error

    Hi I am currently working on a project which requires interfacing BMG250 with ESP32. I am currently using ESP-IDF. I am stuck at the initialization of the bmg250. I browsed the API for BMI160 and I notice major differences. It seems like there are missing parts on the API provided at https://github.com/BoschSensortec/BMG250-API.

    I have tried accessing the BMG250 using the i2c_tools example for ESP-IDF API Reference. I was able to detect the I2C address (0x68), read the default of values  of some registers as well as write on some registers. Hence, I already ruled out the hardware side (connections from esp32 to bmg250 module) from the probable causes of may failed bmg250 initialization. See figure below.

     

    Here's my code for your review.

    #include <stdio.h>
    #include "freertos/FreeRTOS.h"
    #include "freertos/task.h"
    #include "esp_log.h"
    #include "driver/i2c.h"
    #include "sdkconfig.h"
    #include "bmg250.h"
    #include "bmg250_defs.h"

    //static const char *TAG = "gyro";

    #define _I2C_NUMBER(num) I2C_NUM_##num
    #define I2C_NUMBER(num) _I2C_NUMBER(num)

    #define I2C_MASTER_SCL_IO 19 /*!< gpio number for I2C master clock */
    #define I2C_MASTER_SDA_IO 18 /*!< gpio number for I2C master data */
    #define I2C_MASTER_NUM 0 /*!< I2C port number for master dev */
    #define I2C_MASTER_FREQ_HZ 100000 /*!< I2C master clock frequency */
    #define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
    #define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */

    #define ESP_SLAVE_ADDR 0x68 /*!< ESP32 slave address, you can set any 7bit value */
    #define WRITE_BIT I2C_MASTER_WRITE /*!< I2C master write */
    #define READ_BIT I2C_MASTER_READ /*!< I2C master read */
    #define ACK_CHECK_EN 0x1 /*!< I2C master will check ack from slave*/
    #define ACK_CHECK_DIS 0x0 /*!< I2C master will not check ack from slave */
    #define ACK_VAL 0x0 /*!< I2C ack value */
    #define NACK_VAL 0x1 /*!< I2C nack value */

    esp_err_t i2c_master_read_slave_reg(uint8_t i2c_addr, uint8_t i2c_reg, uint8_t* data_rd, size_t size)
    {
    if (size == 0) {
    return ESP_OK;
    }
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, ( i2c_addr << 1 ), ACK_CHECK_EN);
    i2c_master_write_byte(cmd, i2c_reg, ACK_CHECK_EN);
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, ( i2c_addr << 1 ) | READ_BIT, ACK_CHECK_EN);
    if (size > 1) {
    i2c_master_read(cmd, data_rd, size - 1, ACK_VAL);
    }
    i2c_master_read_byte(cmd, data_rd + size - 1, NACK_VAL);
    i2c_master_stop(cmd);
    esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_RATE_MS);
    i2c_cmd_link_delete(cmd);
    return ret;
    }

    int8_t i2c_reg_read(uint8_t i2c_addr, uint8_t reg_addr, uint8_t *reg_data, uint16_t length)
    {

    i2c_master_read_slave_reg(i2c_addr, reg_addr, reg_data, length);
    /* Implement the I2C read routine according to the target machine. */
    return -1;
    }

    esp_err_t i2c_master_write_slave_reg(uint8_t i2c_addr, uint8_t i2c_reg, uint8_t* data_wr, uint16_t size)
    {
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, ( i2c_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, i2c_reg, ACK_CHECK_EN);
    i2c_master_write(cmd, data_wr, size, ACK_CHECK_EN);
    i2c_master_stop(cmd);
    esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_RATE_MS);
    i2c_cmd_link_delete(cmd);
    return ret;
    }

    int8_t i2c_reg_write(uint8_t i2c_addr, uint8_t reg_addr, uint8_t *reg_data, uint16_t length)
    {

    i2c_master_write_slave_reg(i2c_addr, reg_addr, reg_data, length);
    /* Implement the I2C write routine according to the target machine. */
    return -1;
    }

    void i2c_master_init(void)
    {

    i2c_config_t conf = {
    .mode = I2C_MODE_MASTER,
    .sda_io_num = I2C_MASTER_SDA_IO,
    .sda_pullup_en = GPIO_PULLUP_ENABLE,
    .scl_io_num = I2C_MASTER_SCL_IO,
    .scl_pullup_en = GPIO_PULLUP_ENABLE,
    .master.clk_speed = I2C_MASTER_FREQ_HZ
    };

    if(i2c_param_config(I2C_MASTER_NUM, &conf) != ESP_OK)
    {
    printf("\nError configuring I2C\n");
    }
    else
    {
    printf("\nSuccessful configuring I2C\n");
    }

    if(i2c_driver_install(I2C_MASTER_NUM, // i2c port 1
    I2C_MODE_MASTER, // master mode
    0, // does not need rx buffer
    0, // does not need tx buffer
    0) != ESP_OK)
    {
    printf("\nError installing I2C driver!\n");
    }
    else
    {
    printf("\nSuccessful installing I2C driver\n");
    }

    }


    void print_rslt(const char api_name[], int8_t rslt)
    {
    if (rslt != BMG250_OK)
    {
    printf("%s\t", api_name);
    if (rslt == BMG250_E_NULL_PTR)
    {
    printf("Error [%d] : Null pointer error\r\n", rslt);
    }
    else if (rslt == BMG250_E_COM_FAIL)
    {
    printf("Error [%d] : Bus communication failed\r\n", rslt);
    }
    else if (rslt == BMG250_E_INVALID_TEMPERATURE)
    {
    printf("Error [%d] : Invalid Temperature\r\n", rslt);
    }
    else if (rslt == BMG250_E_DEV_NOT_FOUND)
    {
    printf("Error [%d] : Device not found\r\n", rslt);
    }
    else
    {
    /* For more error codes refer "*_defs.h" */
    printf("Error [%d] : Unknown error code\r\n", rslt);
    }
    }
    }

    void delay_ms(uint32_t period_ms)
    {
    //vTaskDelay(period_ms / portTICK_RATE_MS);
    }

    void i2c_gyro_task(void* arg)
    {


    struct bmg250_dev gyro;

    struct bmg250_cfg gyro_cfg;

    struct bmg250_sensor_data gyro_data;

    //gyro.chip_id = BMG250_CHIP_ID;
    gyro.delay_ms = delay_ms;
    gyro.dev_id = BMG250_I2C_ADDR;
    gyro.intf = BMG250_I2C_INTF;
    gyro.read = i2c_reg_read;
    gyro.write = i2c_reg_write;
    gyro.power_mode = BMG250_GYRO_NORMAL_MODE;

    int8_t rslt = BMG250_OK;
    rslt = bmg250_init(&gyro);

    print_rslt(" bmg250_init status", rslt);

    rslt = bmg250_get_sensor_settings(&gyro_cfg, &gyro);
    print_rslt(" bmg250_get_sensor_settings status ", rslt);

    gyro_cfg.odr = BMG250_ODR_100HZ;
    gyro_cfg.range = BMG250_RANGE_1000_DPS;
    gyro_cfg.bw = BMG250_BW_NORMAL_MODE;

    rslt = bmg250_set_sensor_settings(&gyro_cfg, &gyro);
    print_rslt(" bmg250_set_sensor_settings status ", rslt);

    while (1)
    {
    rslt = bmg250_get_sensor_data(BMG250_DATA_TIME_SEL, &gyro_data, &gyro);
    printf("Gyro data X: %d \t Y: %d Z: %d \t Sensor-time : %zu\n",
    gyro_data.x,
    gyro_data.y,
    gyro_data.z,
    gyro_data.sensortime);

    gyro.delay_ms(10);

    }


    }

    void app_main(void)
    {
    i2c_master_init();

    xTaskCreate(i2c_gyro_task, "i2c_gyro_task_0", 1024 * 2, (void* ) 0, 10, NULL);

    ========================================================================================================

    Here's the sample output from the serial monitor of the esp32

    I (0) cpu_start: App cpu up.
    I (245) heap_init: Initializing. RAM available for dynamic allocation:
    I (252) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
    I (258) heap_init: At 3FFB28F8 len 0002D708 (181 KiB): DRAM
    I (264) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
    I (271) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
    I (277) heap_init: At 4008B234 len 00014DCC (83 KiB): IRAM
    I (283) cpu_start: Pro cpu start user code
    I (302) spi_flash: detected chip: generic
    I (302) spi_flash: flash io: dio
    W (302) spi_flash: Detected size(4096k) larger than the size in the binary image header(2048k). Using the size in the binary image header.
    I (313) cpu_start: Starting scheduler on PRO CPU.
    I (0) cpu_start: Starting scheduler on APP CPU.

    Successful configuring I2C

    Successful installing I2C driver
    bmg250_init status Error [-3] : Device not found
    bmg250_get_sensor_settings status Error [-2] : Bus communication failed
    bmg250_set_sensor_settings status Error [-2] : Bus communication failed
    Gyro data X: 80 Y: 16379 Z: 0 Sensor-time : 0
    Gyro data X: 80 Y: 16379 Z: 0 Sensor-time : 0
    Gyro data X: 80 Y: 16379 Z: 0 Sensor-time : 0

     

    Can you please provide insights or point out problems with my code. Thank you very much

    1 REPLY 1
    Yanchao
    Community Moderator

    Re: BMG250 API Support - bmg_init() error

    Hi,

    From the log, I can only find the bmg250_init error.

    So please go to this function and print more info. If chip_id is not 0xD5, please using logic analyzer to get the SCK and SDI wave to find the reason.

    int8_t bmg250_init(struct bmg250_dev *dev)
    {
        int8_t rslt;
        uint8_t data;
        uint8_t chip_id;
    
        /* Null-pointer check */
        rslt = null_ptr_check(dev);
        if ((rslt == BMG250_OK) && (dev->intf == BMG250_SPI_INTF))
        {
            /* Dummy read of 0x7F register to enable SPI Interface
             * if SPI is used
             */
            rslt = bmg250_get_regs(BMG250_SPI_COMM_TEST_ADDR, &data, 1, dev);
        }
        if (rslt == BMG250_OK)
        {
            /* Read chip_id */
            rslt = bmg250_get_regs(BMG250_CHIP_ID_ADDR, &chip_id, 1, dev);
    
    // print rslt, and chip_id value, here
     
            if ((rslt == BMG250_OK) && (chip_id == BMG250_CHIP_ID))
            {
                /* Updating chip_id in device structure */
                dev->chip_id = chip_id;
            }
            else
            {
                rslt = BMG250_E_DEV_NOT_FOUND;
            }
        }
    
        return rslt;
    }

     

    Best regards.

    Icon--AD-black-48x48Icon--address-consumer-data-black-48x48Icon--appointment-black-48x48Icon--back-left-black-48x48Icon--calendar-black-48x48Icon--center-alignedIcon--Checkbox-checkIcon--clock-black-48x48Icon--close-black-48x48Icon--compare-black-48x48Icon--confirmation-black-48x48Icon--dealer-details-black-48x48Icon--delete-black-48x48Icon--delivery-black-48x48Icon--down-black-48x48Icon--download-black-48x48Ic-OverlayAlertIcon--externallink-black-48x48Icon-Filledforward-right_adjustedIcon--grid-view-black-48x48IC_gd_Check-Circle170821_Icons_Community170823_Bosch_Icons170823_Bosch_Icons170821_Icons_CommunityIC-logout170821_Icons_Community170825_Bosch_Icons170821_Icons_CommunityIC-shopping-cart2170821_Icons_CommunityIC-upIC_UserIcon--imageIcon--info-i-black-48x48Icon--left-alignedIcon--Less-minimize-black-48x48Icon-FilledIcon--List-Check-grennIcon--List-Check-blackIcon--List-Cross-blackIcon--list-view-mobile-black-48x48Icon--list-view-black-48x48Icon--More-Maximize-black-48x48Icon--my-product-black-48x48Icon--newsletter-black-48x48Icon--payment-black-48x48Icon--print-black-48x48Icon--promotion-black-48x48Icon--registration-black-48x48Icon--Reset-black-48x48Icon--right-alignedshare-circle1Icon--share-black-48x48Icon--shopping-bag-black-48x48Icon-shopping-cartIcon--start-play-black-48x48Icon--store-locator-black-48x48Ic-OverlayAlertIcon--summary-black-48x48tumblrIcon-FilledvineIc-OverlayAlertwhishlist