Based on BMI160's Wiki (and the chip ID trick for BMX160), I can successfully run the snipped below in my setup (AppBoard2.0+BMX160 ShuttleBoard+COINES), which outputs refreshed magnetometer data. Note that the interrupts configuration is not included, and that I tried to re-use similar sensor configurations.
/*********************************************************************/
/* system header files */
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
/*********************************************************************/
/* own header files */
#include "coines.h"
#include "bmi160.h"
#include "bmm150.h"
/*********************************************************************/
/* local macro definitions */
/*! i2c interface communication, 1 - Enable; 0- Disable */
#define BMX160_INTERFACE_I2C 1
/*! spi interface communication, 1 - Enable; 0- Disable */
#define BMX160_INTERFACE_SPI 0
#if (!((BMX160_INTERFACE_I2C==1) && (BMX160_INTERFACE_SPI==0)) && \
(!((BMX160_INTERFACE_I2C==0) && (BMX160_INTERFACE_SPI==1))))
#error "Invalid value given for the macros BMX160_INTERFACE_I2C / BMX160_INTERFACE_SPI"
#endif
/*! bmx160 shuttle id */
#define BMX160_SHUTTLE_ID 0xD8
/*! bmi160 Device address */
#define BMI160_DEV_ADDR BMI160_I2C_ADDR
/*! bmm150 Device address */
#define BMM150_DEV_ADDR BMM150_DEFAULT_I2C_ADDRESS
/*********************************************************************/
/* global variables */
/*! @brief This structure containing relevant bmi160 info */
struct bmi160_dev bmi160dev;
/*! @brief This structure containing relevant bmm150 info */
struct bmm150_dev bmm150dev;
/*! @brief variable to hold the bmi160 accel data */
struct bmi160_sensor_data bmi160_accel;
/*! @brief variable to hold the bmi160 gyro data */
struct bmi160_sensor_data bmi160_gyro;
/* @brief Buffer to store the Mag data from 0x42 to 0x48 */
uint8_t mag_data[8] = {0};
/*********************************************************************/
/* static function declarations */
/*! internal API is used to initialize the sensor interface */
static void init_sensor_interface(void);
/*! This internal API is used to initialize the bmx160 sensor */
static void init_bmx160(void);
/*! This internal API is used to initialize the sensor driver interface */
static void init_bmx160_sensor_driver_interface(void);
/* Auxiliary interface read function */
static int8_t bmm150_aux_read(uint8_t id, uint8_t reg_addr, uint8_t *aux_data, uint16_t len);
/* Auxiliary interface write function */
static int8_t bmm150_aux_write(uint8_t id, uint8_t reg_addr, uint8_t *aux_data, uint16_t len);
/*********************************************************************/
/* functions */
static int8_t bmm150_aux_read(uint8_t id, uint8_t reg_addr, uint8_t *aux_data, uint16_t len)
{
(void) id; /* id is unused here */
return bmi160_aux_read(reg_addr, aux_data, len, &bmi160dev);
}
static int8_t bmm150_aux_write(uint8_t id, uint8_t reg_addr, uint8_t *aux_data, uint16_t len)
{
(void) id; /* id is unused here */
return bmi160_aux_write(reg_addr, aux_data, len, &bmi160dev);
}
/*!
* @brief This internal API is used to initialize the sensor interface depending
* on selection either SPI or I2C.
*
* @param[in] void
*
* @return void
*
*/
static void init_sensor_interface(void)
{
/* Switch VDD for sensor off */
coines_set_shuttleboard_vdd_vddio_config(0, 0);
/* wait until the sensor goes off */
coines_delay_msec(10);
#if BMX160_INTERFACE_I2C==1
/* set the sensor interface as I2C */
coines_config_i2c_bus(COINES_I2C_BUS_0, COINES_I2C_FAST_MODE);
#endif
#if BMX160_INTERFACE_SPI==1
/* set the sensor interface as SPI */
coines_config_spi_bus(COINES_SPI_BUS_0, COINES_SPI_SPEED_5_MHZ, COINES_SPI_MODE3);
#endif
/* Switch VDD for sensor on */
coines_set_shuttleboard_vdd_vddio_config(3300, 3300);
}
/*!
* @brief This internal API is used to initializes the bmx160 sensor
* settings like power mode and OSRS settings.
*
* @param[in] void
*
* @return void
*
*/
static void init_bmx160(void)
{
int8_t rslt = BMI160_OK;
uint8_t bmm150_data_start = BMM150_DATA_X_LSB;
rslt = bmi160_init(&bmi160dev);
if (rslt == BMI160_OK)
{
printf("BMI160 initialization success !\r\n");
printf("Chip ID 0x%X\n", bmi160dev.chip_id);
}
else
{
printf("BMI160 initialization failure !\r\n");
exit(COINES_E_FAILURE);
}
/* Configure the BMI160's auxiliary interface for the BMM150 */
bmi160dev.aux_cfg.aux_sensor_enable = BMI160_ENABLE;
bmi160dev.aux_cfg.aux_i2c_addr = BMM150_DEV_ADDR;
bmi160dev.aux_cfg.manual_enable = BMI160_ENABLE; /* Manual mode */
bmi160dev.aux_cfg.aux_rd_burst_len = BMI160_AUX_READ_LEN_0; /* 1 byte */
rslt = bmi160_aux_init(&bmi160dev);
if (rslt == BMI160_OK)
{
printf("BMI160 aux. interface init success !\r\n");
}
else
{
printf("BMI160 aux. interface init failure !\r\n");
exit(COINES_E_FAILURE);
}
rslt = bmm150_init(&bmm150dev);
if (rslt == BMI160_OK)
{
printf("BMM150 initialization success !\r\n");
printf("Chip ID 0x%X\n", bmm150dev.chip_id);
}
else
{
printf("BMM150 initialization failure !\r\n");
exit(COINES_E_FAILURE);
}
/* Select the Output data rate, range of accelerometer sensor */
bmi160dev.accel_cfg.odr = BMI160_ACCEL_ODR_50HZ;
bmi160dev.accel_cfg.range = BMI160_ACCEL_RANGE_4G;
bmi160dev.accel_cfg.bw = BMI160_ACCEL_BW_NORMAL_AVG4;
/* Select the power mode of accelerometer sensor */
bmi160dev.accel_cfg.power = BMI160_ACCEL_NORMAL_MODE;
/* Select the Output data rate, range of Gyroscope sensor */
bmi160dev.gyro_cfg.odr = BMI160_GYRO_ODR_50HZ;
bmi160dev.gyro_cfg.range = BMI160_GYRO_RANGE_125_DPS;
bmi160dev.gyro_cfg.bw = BMI160_GYRO_BW_NORMAL_MODE;
/* Select the power mode of Gyroscope sensor */
bmi160dev.gyro_cfg.power = BMI160_GYRO_SUSPEND_MODE;
/* Set the sensor configuration */
rslt = bmi160_set_sens_conf(&bmi160dev);
/* Configure the magnetometer. The regular preset supports up to 60Hz in Forced mode */
bmm150dev.settings.preset_mode = BMM150_PRESETMODE_ENHANCED;
rslt += bmm150_set_presetmode(&bmm150dev);
/* It is important that the last write to the BMM150 sets the forced mode.
* This is because the BMI160 writes the last value to the auxiliary sensor
* after every read */
bmm150dev.settings.pwr_mode = BMM150_FORCED_MODE;
rslt += bmm150_set_op_mode(&bmm150dev);
bmi160dev.aux_cfg.aux_odr = BMI160_AUX_ODR_50HZ;
rslt += bmi160_set_aux_auto_mode(&bmm150_data_start, &bmi160dev);
if (rslt == BMI160_OK)
{
printf("BMX160 configuration success !\r\n");
}
else
{
printf("BMX160 configuration failure !\r\n");
exit(COINES_E_FAILURE);
}
}
/*!
* @brief This internal API is used to set the sensor driver interface to
* read/write the data.
*
* @param[in] void
*
* @return void
*
*/
static void init_bmx160_sensor_driver_interface(void)
{
#if BMX160_INTERFACE_I2C==1
/* I2C setup */
/* link read/write/delay function of host system to appropriate
* bmi160 function call prototypes */
bmi160dev.write = coines_write_i2c;
bmi160dev.read = coines_read_i2c;
bmi160dev.delay_ms = coines_delay_msec;
/* set correct i2c address */
bmi160dev.id = BMI160_DEV_ADDR;
bmi160dev.interface = BMI160_I2C_INTF;
#endif
#if BMX160_INTERFACE_SPI==1
/* SPI setup */
/* link read/write/delay function of host system to appropriate
* bmi160 function call prototypes */
bmi160dev.write = coines_write_spi;
bmi160dev.read = coines_read_spi;
bmi160dev.delay_ms = coines_delay_msec;
bmi160dev.id = 0;
bmi160dev.interface = BMI160_SPI_INTF;
#endif
bmm150dev.dev_id = BMM150_DEV_ADDR;
bmm150dev.intf = BMM150_I2C_INTF;
bmm150dev.read = bmm150_aux_read;
bmm150dev.write = bmm150_aux_write;
bmm150dev.delay_ms = coines_delay_msec;
}
/*!
* @brief Main Function where the execution getting started to test the code.
*
* @param[in] argc
* @param[in] argv
*
* @return status
*
*/
int main(int argc, char *argv[])
{
struct coines_board_info board_info;
int16_t rslt;
int times_to_read = 0;
init_bmx160_sensor_driver_interface();
rslt = coines_open_comm_intf(COINES_COMM_INTF_USB);
if (rslt < 0)
{
printf("\n Unable to connect with Application Board ! \n"
" 1. Check if the board is connected and powered on. \n"
" 2. Check if Application Board USB driver is installed. \n"
" 3. Check if board is in use by another application. (Insufficient permissions to access USB) \n");
exit(rslt);
}
rslt = coines_get_board_info(&board_info);
if (rslt == COINES_SUCCESS)
{
if (board_info.shuttle_id != BMX160_SHUTTLE_ID)
{
printf("! Warning invalid sensor shuttle \n ,"
"This application will not support this sensor \n");
exit(COINES_E_FAILURE);
}
}
init_sensor_interface();
init_bmx160();
/* after sensor init introduce 200 msec sleep */
coines_delay_msec(200);
while (times_to_read < 100)
{
/* To read both Accel and Gyro data */
bmi160_get_sensor_data((BMI160_ACCEL_SEL | BMI160_GYRO_SEL), &bmi160_accel, &bmi160_gyro, &bmi160dev);
bmi160_read_aux_data_auto_mode(mag_data, &bmi160dev);
rslt = bmm150_aux_mag_data(mag_data, &bmm150dev);
printf("ax:%d\tay:%d\taz:%d\n", bmi160_accel.x, bmi160_accel.y, bmi160_accel.z);
printf("gx:%d\tgy:%d\tgz:%d\n", bmi160_gyro.x, bmi160_gyro.y, bmi160_gyro.z);
printf("mx:%d\tmy:%d\tmz:%d\n", bmm150dev.data.x, bmm150dev.data.y, bmm150dev.data.z);
fflush(stdout);
coines_delay_msec(20); // 50Hz ODR
times_to_read ++;
}
coines_close_comm_intf(COINES_COMM_INTF_USB);
return EXIT_SUCCESS;
}
... View more