This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Fatal Error on I2C Sensor Initialization

Segger Embedded Studi, SDK 15.2, Windows 10

Nordic NRF52DK PCA 10040 1. 2 .4

Hello again everyone, I have gotten farther with my previous issues of not being able to access individual register with the Bosch IMU (BMX055). I have used an example found here that specifically applies to my application for guidance as well. Another example of a read routine using the NRF52 and the same IMU was found here, but this routine also didn't work.

I have used code from this nordic thread for reading and writing functions through i2c but have had no success with them. I will post the code in question

#include <stdio.h>
#include "boards.h"
#include "app_util_platform.h"
#include "app_error.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 "blebugIMU.h"

/* TWI instance ID. */
#define TWI_INSTANCE_ID 0

/* Common addresses definition for temperature sensor. */
#define LM75B_ADDR (0x90U >> 1)

#define LM75B_REG_TEMP 0x00U
#define LM75B_REG_CONF 0x01U
#define LM75B_REG_THYST 0x02U
#define LM75B_REG_TOS 0x03U

/* Mode for LM75B. */
#define NORMAL_MODE 0U

/* 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 setting active mode on MMA7660 accelerometer.
*/


/**
* @brief Function for writing to registers on the MPU-6050.
*/

ret_code_t bmx055_I2C_register_write(uint8_t reg_addr, uint8_t * p_tx_data, uint8_t bytes)
{
ret_code_t ret_code;

uint8_t tx_data[bytes+1];

tx_data[0] = reg_addr;

for(uint8_t i = 0 ; i<bytes ; i++) 
{
tx_data[i+1] = p_tx_data[i];
} 

ret_code = nrf_drv_twi_tx(&m_twi, BMX055_GYRO_ADDRESS, tx_data, sizeof(tx_data), false);

return ret_code;
}

/**
* @brief Function for reading from registers on the MPU-6050.
*/

ret_code_t bmx055_I2C_register_read( uint8_t reg_addr, uint8_t * p_rx_data, uint32_t bytes)
{ 
ret_code_t ret_code;

ret_code = nrf_drv_twi_tx(&m_twi,BMX055_GYRO_ADDRESS, &reg_addr, 1, false);

if(ret_code != NRF_SUCCESS)
{
return ret_code;
}

ret_code = nrf_drv_twi_rx(&m_twi, BMX055_GYRO_ADDRESS, p_rx_data, bytes);

return ret_code;
}

void bmx055_get_device_id (uint8_t * p_dev_id)
{
ret_code_t err_code;

uint8_t rx_data;

// Read the I2C Address of the BMX055 from the WHO_AM_I register
err_code = bmx055_I2C_register_read(BMX055_ACC_WHOAMI,&rx_data,1);

APP_ERROR_CHECK(err_code);

*p_dev_id = rx_data;
}

void bmx055_read_acc(int16_t * p_x_val, int16_t * p_y_val, int16_t * p_z_val)
{
ret_code_t err_code;

// Raw accelerometer measurements buffer
uint8_t acc_data[6];

// Read the six accelerometer data registers starting from ACCEL_XOUT_H
err_code = bmx055_I2C_register_read(BMX055_ACC_D_X_LSB,acc_data,sizeof(acc_data));

APP_ERROR_CHECK(err_code);

/* Combine the two 8-bit data registers to a 16-bit value
for each axis by left shifting ACCEL_xOUT_H eight times 
and OR it with ACCEL_xOUT_L. */

*p_x_val = (acc_data[0]<<8)|acc_data[1];
*p_y_val = (acc_data[2]<<8)|acc_data[3];
*p_z_val = (acc_data[4]<<8)|acc_data[5];
}
/**
* @brief Function for handling data from temperature sensor.
*
* @param[in] temp Temperature in Celsius degrees read from sensor.
*/
__STATIC_INLINE void data_handler(uint8_t temp)
{
NRF_LOG_INFO("Temperature: %d Celsius degrees.", temp);
}

void bmx055_read_gyro(int16_t * p_x_gyro, int16_t * p_y_gyro, int16_t * p_z_gyro)
{
ret_code_t err_code;

uint8_t gyro_data[6];

//Read the 6 gyroscope data registers starting from GYRO_XOUT_H
err_code = bmx055_I2C_register_read(BMX055_GYRO_RATE_X_LSB, gyro_data, sizeof(gyro_data));

APP_ERROR_CHECK(err_code);

/* Combine the two 8-bit data registers to a 16-bit value
for each axis by left shifting GYRO_xOUT_H eight times 
and OR it with GYRO_xOUT_L. */
*p_x_gyro = (gyro_data[0]<<8)|gyro_data[1];
*p_y_gyro = (gyro_data[2]<<8)|gyro_data[3];
*p_z_gyro = (gyro_data[4]<<8)|gyro_data[5];
}




/**
* @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);
}

void bmx055_init (void)
{
ret_code_t err_code;

uint8_t tx_data = 0xB6;

// Write one to the BMX055_ACC_BGW_SOFTRESET and register to wake up the gyro and acc
err_code = bmx055_I2C_register_write(BMX055_ACC_BGW_SOFTRESET, &tx_data, 1);
APP_ERROR_CHECK(err_code);
err_code = bmx055_I2C_register_write(BMX055_GYRO_BGW_SOFTRESET, &tx_data, 1);
APP_ERROR_CHECK(err_code);


}

/**
* @brief Function for reading data from temperature sensor.
*/
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, LM75B_ADDR, &m_sample, sizeof(m_sample));
APP_ERROR_CHECK(err_code);
}

/**
* @brief Function for main application entry.
*/
int main(void)
{
APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
NRF_LOG_DEFAULT_BACKENDS_INIT();

NRF_LOG_INFO("\r\nTWI sensor example started.");
NRF_LOG_FLUSH();
twi_init();
bmx055_init();

uint8_t device_id;

// bmx055_get_device_id(&device_id);
/* 
int16_t x_val;
int16_t y_val;
int16_t z_val;

bmx055_read_acc(&x_val, &y_val, &z_val);

int16_t x_gyro;
int16_t y_gyro;
int16_t z_gyro;

// Read Gyroscope Data
bmx055_read_gyro(&x_gyro, &y_gyro, &z_gyro);

*/

while (true)
{
nrf_delay_ms(500);

do
{
__WFE();
}while (m_xfer_done == false);

read_sensor_data();
NRF_LOG_FLUSH();
}
}

/** @} */

As you will notice, I have commented out the other functions that I am not using and have narrowed down the fatal error occurrence to the instantiation of BMX055. It seems that my writing and reading routines themselves are to blame yet I don't know why. All of the pin addresses of the BMX055 are stored in a header file I put together which I will add below for reference. I would appreciate any help in getting these values sorted. 

/* This header file was put tofether to include register and address definitions of the BMX055 IMU
   Pin defintions and useful enumerations are included */





#define BMX055_ACC_WHOAMI        0x00   // should return 0xFA

//#define BMX055_ACC_Reserved    0x01

#define BMX055_ACC_D_X_LSB       0x02

#define BMX055_ACC_D_X_MSB       0x03

#define BMX055_ACC_D_Y_LSB       0x04

#define BMX055_ACC_D_Y_MSB       0x05

#define BMX055_ACC_D_Z_LSB       0x06

#define BMX055_ACC_D_Z_MSB       0x07

#define BMX055_ACC_D_TEMP        0x08

#define BMX055_ACC_INT_STATUS_0  0x09

#define BMX055_ACC_INT_STATUS_1  0x0A

#define BMX055_ACC_INT_STATUS_2  0x0B

#define BMX055_ACC_INT_STATUS_3  0x0C

//#define BMX055_ACC_Reserved    0x0D

#define BMX055_ACC_FIFO_STATUS   0x0E

#define BMX055_ACC_PMU_RANGE     0x0F

#define BMX055_ACC_PMU_BW        0x10

#define BMX055_ACC_PMU_LPW       0x11

#define BMX055_ACC_PMU_LOW_POWER 0x12

#define BMX055_ACC_D_HBW         0x13

#define BMX055_ACC_BGW_SOFTRESET 0x14

//#define BMX055_ACC_Reserved    0x15

#define BMX055_ACC_INT_EN_0      0x16

#define BMX055_ACC_INT_EN_1      0x17

#define BMX055_ACC_INT_EN_2      0x18

#define BMX055_ACC_INT_MAP_0     0x19

#define BMX055_ACC_INT_MAP_1     0x1A

#define BMX055_ACC_INT_MAP_2     0x1B

//#define BMX055_ACC_Reserved    0x1C

//#define BMX055_ACC_Reserved    0x1D

#define BMX055_ACC_INT_SRC       0x1E

//#define BMX055_ACC_Reserved    0x1F

#define BMX055_ACC_INT_OUT_CTRL  0x20

#define BMX055_ACC_INT_RST_LATCH 0x21

#define BMX055_ACC_INT_0         0x22

#define BMX055_ACC_INT_1         0x23

#define BMX055_ACC_INT_2         0x24

#define BMX055_ACC_INT_3         0x25

#define BMX055_ACC_INT_4         0x26

#define BMX055_ACC_INT_5         0x27

#define BMX055_ACC_INT_6         0x28

#define BMX055_ACC_INT_7         0x29

#define BMX055_ACC_INT_8         0x2A

#define BMX055_ACC_INT_9         0x2B

#define BMX055_ACC_INT_A         0x2C

#define BMX055_ACC_INT_B         0x2D

#define BMX055_ACC_INT_C         0x2E

#define BMX055_ACC_INT_D         0x2F

#define BMX055_ACC_FIFO_CONFIG_0 0x30

//#define BMX055_ACC_Reserved    0x31

#define BMX055_ACC_PMU_SELF_TEST 0x32

#define BMX055_ACC_TRIM_NVM_CTRL 0x33

#define BMX055_ACC_BGW_SPI3_WDT  0x34

//#define BMX055_ACC_Reserved    0x35

#define BMX055_ACC_OFC_CTRL      0x36

#define BMX055_ACC_OFC_SETTING   0x37

#define BMX055_ACC_OFC_OFFSET_X  0x38

#define BMX055_ACC_OFC_OFFSET_Y  0x39

#define BMX055_ACC_OFC_OFFSET_Z  0x3A

#define BMX055_ACC_TRIM_GPO      0x3B

#define BMX055_ACC_TRIM_GP1      0x3C

//#define BMX055_ACC_Reserved    0x3D

#define BMX055_ACC_FIFO_CONFIG_1 0x3E

#define BMX055_ACC_FIFO_DATA     0x3F



// BMX055 Gyroscope Registers

#define BMX055_GYRO_WHOAMI           0x00  // should return 0x0F

//#define BMX055_GYRO_Reserved       0x01

#define BMX055_GYRO_RATE_X_LSB       0x02

#define BMX055_GYRO_RATE_X_MSB       0x03

#define BMX055_GYRO_RATE_Y_LSB       0x04

#define BMX055_GYRO_RATE_Y_MSB       0x05

#define BMX055_GYRO_RATE_Z_LSB       0x06

#define BMX055_GYRO_RATE_Z_MSB       0x07

//#define BMX055_GYRO_Reserved       0x08

#define BMX055_GYRO_INT_STATUS_0  0x09

#define BMX055_GYRO_INT_STATUS_1  0x0A

#define BMX055_GYRO_INT_STATUS_2  0x0B

#define BMX055_GYRO_INT_STATUS_3  0x0C

//#define BMX055_GYRO_Reserved    0x0D

#define BMX055_GYRO_FIFO_STATUS   0x0E

#define BMX055_GYRO_RANGE         0x0F

#define BMX055_GYRO_BW            0x10

#define BMX055_GYRO_LPM1          0x11

#define BMX055_GYRO_LPM2          0x12

#define BMX055_GYRO_RATE_HBW      0x13

#define BMX055_GYRO_BGW_SOFTRESET 0x14

#define BMX055_GYRO_INT_EN_0      0x15

#define BMX055_GYRO_INT_EN_1      0x16

#define BMX055_GYRO_INT_MAP_0     0x17

#define BMX055_GYRO_INT_MAP_1     0x18

#define BMX055_GYRO_INT_MAP_2     0x19

#define BMX055_GYRO_INT_SRC_1     0x1A

#define BMX055_GYRO_INT_SRC_2     0x1B

#define BMX055_GYRO_INT_SRC_3     0x1C

//#define BMX055_GYRO_Reserved    0x1D

#define BMX055_GYRO_FIFO_EN       0x1E

//#define BMX055_GYRO_Reserved    0x1F

//#define BMX055_GYRO_Reserved    0x20

#define BMX055_GYRO_INT_RST_LATCH 0x21

#define BMX055_GYRO_HIGH_TH_X     0x22

#define BMX055_GYRO_HIGH_DUR_X    0x23

#define BMX055_GYRO_HIGH_TH_Y     0x24

#define BMX055_GYRO_HIGH_DUR_Y    0x25

#define BMX055_GYRO_HIGH_TH_Z     0x26

#define BMX055_GYRO_HIGH_DUR_Z    0x27

//#define BMX055_GYRO_Reserved    0x28

//#define BMX055_GYRO_Reserved    0x29

//#define BMX055_GYRO_Reserved    0x2A

#define BMX055_GYRO_SOC           0x31

#define BMX055_GYRO_A_FOC         0x32

#define BMX055_GYRO_TRIM_NVM_CTRL 0x33

#define BMX055_GYRO_BGW_SPI3_WDT  0x34

//#define BMX055_GYRO_Reserved    0x35

#define BMX055_GYRO_OFC1          0x36

#define BMX055_GYRO_OFC2          0x37

#define BMX055_GYRO_OFC3          0x38

#define BMX055_GYRO_OFC4          0x39

#define BMX055_GYRO_TRIM_GP0      0x3A

#define BMX055_GYRO_TRIM_GP1      0x3B

#define BMX055_GYRO_BIST          0x3C

#define BMX055_GYRO_FIFO_CONFIG_0 0x3D

#define BMX055_GYRO_FIFO_CONFIG_1 0x3E



// BMX055 magnetometer registers

#define BMX055_MAG_WHOAMI         0x40  // should return 0x32

#define BMX055_MAG_Reserved       0x41

#define BMX055_MAG_XOUT_LSB       0x42

#define BMX055_MAG_XOUT_MSB       0x43

#define BMX055_MAG_YOUT_LSB       0x44

#define BMX055_MAG_YOUT_MSB       0x45

#define BMX055_MAG_ZOUT_LSB       0x46

#define BMX055_MAG_ZOUT_MSB       0x47

#define BMX055_MAG_ROUT_LSB       0x48

#define BMX055_MAG_ROUT_MSB       0x49

#define BMX055_MAG_INT_STATUS     0x4A

#define BMX055_MAG_PWR_CNTL1      0x4B

#define BMX055_MAG_PWR_CNTL2      0x4C

#define BMX055_MAG_INT_EN_1       0x4D

#define BMX055_MAG_INT_EN_2       0x4E

#define BMX055_MAG_LOW_THS        0x4F

#define BMX055_MAG_HIGH_THS       0x50

#define BMX055_MAG_REP_XY         0x51

#define BMX055_MAG_REP_Z          0x52

// BMX055 magnetometer registers
#define BMX055_MAG_WHOAMI         0x40  // should return 0x32
#define BMX055_MAG_Reserved       0x41
#define BMX055_MAG_XOUT_LSB       0x42
#define BMX055_MAG_XOUT_MSB       0x43
#define BMX055_MAG_YOUT_LSB       0x44
#define BMX055_MAG_YOUT_MSB       0x45
#define BMX055_MAG_ZOUT_LSB       0x46
#define BMX055_MAG_ZOUT_MSB       0x47
#define BMX055_MAG_ROUT_LSB       0x48
#define BMX055_MAG_ROUT_MSB       0x49
#define BMX055_MAG_INT_STATUS     0x4A
#define BMX055_MAG_PWR_CNTL1      0x4B
#define BMX055_MAG_PWR_CNTL2      0x4C
#define BMX055_MAG_INT_EN_1       0x4D
#define BMX055_MAG_INT_EN_2       0x4E
#define BMX055_MAG_LOW_THS        0x4F
#define BMX055_MAG_HIGH_THS       0x50
#define BMX055_MAG_REP_XY         0x51
#define BMX055_MAG_REP_Z          0x52
/* Trim Extended Registers */
#define BMM050_DIG_X1             0x5D // needed for magnetic field calculation
#define BMM050_DIG_Y1             0x5E  
#define BMM050_DIG_Z4_LSB         0x62
#define BMM050_DIG_Z4_MSB         0x63
#define BMM050_DIG_X2             0x64  
#define BMM050_DIG_Y2             0x65  
#define BMM050_DIG_Z2_LSB         0x68  
#define BMM050_DIG_Z2_MSB         0x69  
#define BMM050_DIG_Z1_LSB         0x6A  
#define BMM050_DIG_Z1_MSB         0x6B  
#define BMM050_DIG_XYZ1_LSB       0x6C 
#define BMM050_DIG_XYZ1_MSB       0x6D 
#define BMM050_DIG_Z3_LSB         0x6E
#define BMM050_DIG_Z3_MSB         0x6F
#define BMM050_DIG_XY2            0x70 
#define BMM050_DIG_XY1            0x71  


// Seven-bit device addresses are ACC = 0x18, GYRO = 0x68, MAG = 0x10

#define BMX055_ACC_ADDRESS  0x18   // Address of BMX055 accelerometer

#define BMX055_GYRO_ADDRESS 0x68 // Address of BMX055 gyroscope

#define BMX055_MAG_ADDRESS  0x10   // Address of BMX055 magnetometer

#define MS5637_ADDRESS      0x76   // Address of altimeter


#define AFS_2G  0x03

#define AFS_4G  0x05

#define AFS_8G  0x08

#define AFS_16G 0x0C

Parents
  • Hi,

    I do not have this module here, sorry that I wont be of much help. But there seems to be a lot of users who has successfully used this sensor with our TWI. An example can be found here

    One easiest thing you can do is to start debugging by sniffing the TWI lines with a logic analyzer and see if it matches the timing diagram of the spec. I know it sounds pretty much useless, but I can see nothing wrong with your sensor address or using of serial API. 

  • With regards to that linked example, are there any examples of NRF_DRV_TWI_XFER_TXRX in practice? The implementation seems different than the use case of the TX and RX functions. It says I need to define a macro, does that mean I need to define it in the function. Otherwise I don't see how this function will know which twi instance to use

Reply Children
Related