12-13-2019 08:41 PM - edited 12-13-2019 08:52 PM
I am using the BMI160 Shuttle Board for some prototyping and research and I am not using the any of the Bosch API Libraries (BMI160/BMM150). I am running into a few issues while trying communicate with the BMM150. Before I mention the issues, I am connecting the nrf52840 Dev Kit to BMI160 using the I2C(TWI) Communication Interface and have the following setup and configurations.
HARDWARE SETUP:
SOFTWARE TOOLS:
CODE SUMMARY:
ISSUE:
Can anyone help me with solving these issues without using the BMI160/BMM150 API Library?
#include <stdio.h>
#include "boards.h"
#include "bsp.h"
#include "app_util_platform.h"
#include "app_error.h"
#include "nrf_drv_twi.h"
#include "nrf_delay.h"
#include "math.h"
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
/* TWI instance ID. */
#define TWI_INSTANCE_ID 0
#define TWI_ADDRESSES 127
/* Common addresses definition for temperature sensor. */
#define BMI160_ADDR 0x68U
// Registers
#define MAG_X_LSB 0x04U // DATA
#define MAG_X_MSB 0x05U // DATA
#define MAG_Y_LSB 0x06U // DATA
#define MAG_Y_MSB 0x07U // DATA
#define MAG_Z_LSB 0x08U // DATA
#define MAG_Z_MSB 0x09U // DATA
#define MAG_RHALL_LSB 0x0AU // DATA
#define MAG_RHALL_MSB 0x0BU // DATA
#define GYR_X_LSB 0x0CU // DATA
#define GYR_X_MSB 0x0DU // DATA
#define GYR_Y_LSB 0x0EU // DATA
#define GYR_Y_MSB 0x0FU // DATA
#define GYR_Z_LSB 0x10U // DATA
#define GYR_Z_MSB 0x11U // DATA
#define ACC_X_LSB 0x12U // DATA
#define ACC_X_MSB 0x13U // DATA
#define ACC_Y_LSB 0x14U // DATA
#define ACC_Y_MSB 0x15U // DATA
#define ACC_Z_LSB 0x16U // DATA
#define ACC_Z_MSB 0x17U // DATA
#define SENSORTIME_REG_0 0x18U // DATA
#define SENSORTIME_REG_1 0x19U // DATA
#define SENSORTIME_REG_2 0x1AU // DATA
#define CMD_REG 0x7EU // CMD
#define STEP_CONF_0_REG 0x7AU // STEP CONFIG 0
#define STEP_CONF_1_REG 0x7BU // STEP CONFIG 1
#define STEP_CNT_0_REG 0x78U // STEP COUNT 0
#define STEP_CNT_1_REG 0x79U // STEP COUNT 1\
#define TEMP_0_REG 0x21U // STEP COUNT 0
#define TEMP_1_REG 0x22U // STEP COUNT 1
#define INT_MAP_REG_0 0x55U // Interupt Map 0
#define INT_MAP_REG_1 0x56U // Interupt Map 1
#define INT_MAP_REG_2 0x57U // Interupt Map 2
#define INT_STATUS_REG_0 0x1CU // Interupt Status 0
#define INT_STATUS_REG_1 0x1DU // Interupt Status 1
#define INT_STATUS_REG_2 0x1EU // Interupt Status 2
#define INT_STATUS_REG_3 0x1FU // Interupt Status 3
#define IF_CONF_REG 0x6BU // IF_CONF
#define MAG_CONF_REG 0x44U // MAG_CONF
#define MAG_IF_REG_0 0x4BU // MAG_IF_REG
#define MAG_IF_REG_1 0x4CU // MAG_IF_REG
#define MAG_IF_REG_2 0x4DU // MAG_IF_REG
#define MAG_IF_REG_3 0x4EU // MAG_IF_REG
#define MAG_IF_REG_4 0x4FU // MAG_IF_REG
#define IF_CONF_AUTO_MAG 0x20U // CMD
#define MAG_ODR_100 0x08U // on MAG ODR to 100Hz
#define INT_EN_REG_0 0x50U // Interupt Map 0
#define INT_EN_REG_1 0x51U // Interupt Map 1
#define INT_EN_REG_2 0x52U // Interupt Map 2
#define ACC_RANGE_REG 0x41U // Accelerometer range
/* Power Mode for BMI160. */
#define ACC_NORMAL_MODE 0x11U // on ACC
#define GYR_NORMAL_MODE 0x15U // on GYR
#define MAG_NORMAL_MODE 0x19U // on MAG
#define ACC_RANGE_4G 0x05U // 4G range
#define STEP_CONF_0_NORMAL 0x15U // Normal Mode
#define STEP_CONF_1_NORMAL 0x0BU // Normal Mode step cnt enabled
#define STEP_CONF_0_SENS 0x2DU // Sensitive Mode
#define STEP_CONF_1_SENS 0x08U // Sensitive Mode step cnt enabled
#define RESET_STEP_CNT 0xB2U // on REST STEP CNT
#define MAG_IF_I2C 0x20U
#define ZERO_VALUE 0x00U // Value = 0
#define STATUS_REG 0x1BU // Value = 0
#define ERR_REG 0x02U // Value = 0
struct Accelerometer{
float x;
float y;
float z;
}acc;
struct Gyroscope{
float x;
float y;
float z;
}gyro;
struct Magnetometer{
float x;
float y;
float z;
float rhall;
}mag_raw;
/* Indicates if operation on TWI has ended. */
static volatile bool m_xfer_done = false;
/* TWI instance. */
static const nrf_drv_twi_t m_twi = NRF_DRV_TWI_INSTANCE(TWI_INSTANCE_ID);
/* Buffer for samples read from temperature sensor. */
static uint8_t m_sample;
/**
* @brief Function for Configuration, Reading and Writing to BMI160 sensor.
*/
void BMI160_CONFIG(uint8_t Register, uint8_t Value)
{
ret_code_t err_code;
uint8_t reg[2] = {Register, Value};
err_code = nrf_drv_twi_tx(&m_twi, BMI160_ADDR, reg, sizeof(reg), false);
APP_ERROR_CHECK(err_code);
while (m_xfer_done == false);
}
static void read_sensor_data()
{
m_xfer_done = false;
/* Read 1 byte from the specified address - skip 3 bits dedicated for fractional part of temperature. */
ret_code_t err_code = nrf_drv_twi_rx(&m_twi, BMI160_ADDR, &m_sample, 1);
APP_ERROR_CHECK(err_code);
while (m_xfer_done == false);
}
void write_data_to_read_reg(uint8_t Register){
ret_code_t err_code;
/* Writing to pointer byte. */
uint8_t reg[2];
reg[0] = Register;
m_xfer_done = false;
err_code = nrf_drv_twi_tx(&m_twi, BMI160_ADDR, reg, 1, false);
APP_ERROR_CHECK(err_code);
while (m_xfer_done == false);
}
void mag_manual_read(){
BMI160_CONFIG(MAG_IF_REG_1, 128);
nrf_delay_ms(100);
BMI160_CONFIG(MAG_IF_REG_4, 1);
nrf_delay_ms(100);
BMI160_CONFIG(MAG_IF_REG_3, 75); //4B set to 1 Power Control Bit
nrf_delay_ms(100);
BMI160_CONFIG(MAG_IF_REG_4, 1);
nrf_delay_ms(100);
BMI160_CONFIG(MAG_IF_REG_3, 81); // 0x51 set to 1 RepXY
nrf_delay_ms(100);
BMI160_CONFIG(MAG_IF_REG_4, 14);
nrf_delay_ms(100);
BMI160_CONFIG(MAG_IF_REG_3, 82); //0x51 set to 14 RepZ
nrf_delay_ms(100);
BMI160_CONFIG(MAG_IF_REG_4, 2);
nrf_delay_ms(100);
BMI160_CONFIG(MAG_IF_REG_3, 76); //0x4C set to 2 OPMODE 0x01
nrf_delay_ms(100);
BMI160_CONFIG(MAG_IF_REG_2, 66);
nrf_delay_ms(100);
BMI160_CONFIG(MAG_CONF_REG, 5);
nrf_delay_ms(100);
BMI160_CONFIG(MAG_IF_REG_1, ZERO_VALUE);
}
int conv_to_16(int8_t lsb, int8_t msb){
return (msb << + lsb;
}
void read_mag(){
int8_t lsb = 0;
int16_t msb = 0;
// Read MAG_X_LSB
nrf_delay_ms(5);
write_data_to_read_reg(MAG_X_LSB);
do
{
__WFE();
}while (m_xfer_done == false);
read_sensor_data();
lsb = m_sample;
// Read MAG_X_MSB
nrf_delay_ms(5);
write_data_to_read_reg(MAG_X_MSB);
do
{
__WFE();
}while (m_xfer_done == false);
read_sensor_data();
msb = m_sample;
mag_raw.x = conv_to_16(lsb, msb);
// Read MAG_Y_LSB
nrf_delay_ms(5);
write_data_to_read_reg(MAG_Y_LSB);
do
{
__WFE();
}while (m_xfer_done == false);
read_sensor_data();
lsb = m_sample;
// Read MAG_Y_MSB
nrf_delay_ms(5);
write_data_to_read_reg(MAG_Y_MSB);
do
{
__WFE();
}while (m_xfer_done == false);
read_sensor_data();
msb = m_sample;
mag_raw.y = conv_to_16(lsb, msb);
// Read MAG_Z_LSB
nrf_delay_ms(5);
write_data_to_read_reg(MAG_Z_LSB);
do
{
__WFE();
}while (m_xfer_done == false);
read_sensor_data();
lsb = m_sample;
// Read MAG_Z_MSB
nrf_delay_ms(5);
write_data_to_read_reg(MAG_Z_MSB);
do
{
__WFE();
}while (m_xfer_done == false);
read_sensor_data();
msb = m_sample;
mag_raw.z = conv_to_16(lsb, msb);
// Read MAG_RHALL_LSB
nrf_delay_ms(5);
write_data_to_read_reg(MAG_RHALL_LSB);
do
{
__WFE();
}while (m_xfer_done == false);
read_sensor_data();
lsb = m_sample;
// Read MAG_RHALL_MSB
nrf_delay_ms(5);
write_data_to_read_reg(MAG_RHALL_MSB);
do
{
__WFE();
}while (m_xfer_done == false);
read_sensor_data();
msb = m_sample;
mag_raw.rhall = conv_to_16(lsb, msb);
NRF_LOG_INFO("RHALL: " NRF_LOG_FLOAT_MARKER "\r", NRF_LOG_FLOAT(mag_raw.rhall));
NRF_LOG_INFO("MAG_X:" NRF_LOG_FLOAT_MARKER "\r", NRF_LOG_FLOAT(mag_raw.x));
NRF_LOG_INFO("MAG_Y:" NRF_LOG_FLOAT_MARKER "\r", NRF_LOG_FLOAT(mag_raw.y));
NRF_LOG_INFO("MAG_Z:" NRF_LOG_FLOAT_MARKER "\r", NRF_LOG_FLOAT(mag_raw.z));
}
/**
* @brief Data Handler -> Display the data given to read_sensor_data() function every time the
* NRF_LOG_FLUSH() function is called
*/
__STATIC_INLINE void data_handler(uint8_t val)
{
// NRF_LOG_INFO("%d ", val);
}
/**
* @brief TWI events handler.
*/
void twi_handler(nrf_drv_twi_evt_t const * p_event, void * p_context)
{
switch (p_event->type)
{
case NRF_DRV_TWI_EVT_DONE:
if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_RX)
{
data_handler(m_sample);
}
m_xfer_done = true;
break;
default:
break;
}
}
/**
* @brief UART initialization.
*/
void twi_init (void)
{
ret_code_t err_code;
const nrf_drv_twi_config_t twi_lm75b_config = {
.scl = ARDUINO_SCL_PIN,
.sda = ARDUINO_SDA_PIN,
.frequency = NRF_DRV_TWI_FREQ_100K,
.interrupt_priority = APP_IRQ_PRIORITY_HIGH,
.clear_bus_init = false
};
err_code = nrf_drv_twi_init(&m_twi, &twi_lm75b_config, twi_handler, NULL);
APP_ERROR_CHECK(err_code);
nrf_drv_twi_enable(&m_twi);
}
/**
* @brief Function for main application entry.
*/
int main(void)
{
APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
NRF_LOG_DEFAULT_BACKENDS_INIT();
uint32_t reading = 0;
NRF_LOG_INFO("\r\nTWI sensor example started.");
NRF_LOG_FLUSH();
twi_init();
BMI160_CONFIG(IF_CONF_REG, IF_CONF_AUTO_MAG); //Config for I2C as primary and Magnetometer as Secondary
nrf_delay_ms(100);
BMI160_CONFIG(CMD_REG, ACC_NORMAL_MODE);
nrf_delay_ms(100);
BMI160_CONFIG(CMD_REG, GYR_NORMAL_MODE);
nrf_delay_ms(100);
BMI160_CONFIG(CMD_REG, MAG_NORMAL_MODE);
while (true)
{
nrf_delay_ms(500);
NRF_LOG_INFO("\r\nReading: %d", reading);
reading++;
mag_manual_read();
read_mag();
//Flush all Log Data to the UART
NRF_LOG_FLUSH();
}
}
01-13-2020 01:57 PM
12-01-2022 02:37 AM
Hello
https://github.com/BoschSensortec/BMI160_driver/wiki/How-to-use-an-auxiliary-sensor-or-magnetometer-....
If I change it to BMI270 in the link above, will BMI270 be applied?