Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

How to get data from sensor ( bmi160 ) using spi?

Hello !

I am trying to get data from sensor ( chip_id of bmi160 ), but i always get 0 .

Could someone tell me how to do?

I follow these steps :

1. I Declared SPI instance and bmi160 sensor struct like this : 

static nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE( 0 );  // SPI instance. //宣告spi例子
struct bmi160_dev sensor ; // bmi160 sensor struct // 宣告bmi160感應器結構

2. Declare delay & read & write functions like this : 

void user_delay_ms(uint32_t period) { 
	// delay time
	//暫停幾毫秒
	
  nrf_delay_ms( period ) ;
} // user_delay_ms()

int8_t spi1_read_transfer(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t length){
	// read data from sensor
	// 從感應器讀取資料
	
	ret_code_t ret;
	
  nrf_drv_gpiote_out_clear(SPI_SS_PIN); /* To activate the sensor on the bus, i.e., set the chip/slave select low */
	
	ret = nrf_drv_spi_transfer(&spi, &reg_addr, 1, NULL, 0);
	if(ret == NRF_SUCCESS)
		ret = nrf_drv_spi_transfer(&spi, NULL, 0, reg_data, length);
	
	nrf_gpio_pin_set(SPI_SS_PIN); /* To deactivate the sensor on the bus, i.e., set the chip/slave select high*/
	
	return (int8_t)ret;	
} // spi1_read_transfer()

int8_t spi1_write_transfer(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t length){
	// write data to sensor 
	// 寫資料到感應器
	
	ret_code_t ret;
	
	nrf_drv_gpiote_out_clear(SPI_SS_PIN); /* To activate the sensor on the bus, i.e., set the chip/slave select low */
	
	ret = nrf_drv_spi_transfer(&spi, &reg_addr, 1, NULL, 0);

	if(ret == NRF_SUCCESS)
		ret = nrf_drv_spi_transfer(&spi, reg_data, length, NULL, 0);

	nrf_gpio_pin_set(SPI_SS_PIN); /* To deactivate the sensor on the bus, i.e., set the chip/slave select high*/
	
	return (int8_t)ret;	
} // spi1_write_transfer()

3. init spi_config and bmi160 sensor and print result in main like this :

int main(void){   
	
    bsp_board_init(BSP_INIT_LEDS);
    APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
    NRF_LOG_DEFAULT_BACKENDS_INIT();

  	// init spi // 初始化接角
  	nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG; 
    spi_config.ss_pin   = SPI_SS_PIN; 
    spi_config.miso_pin = SPI_MISO_PIN;
    spi_config.mosi_pin = SPI_MOSI_PIN;
    spi_config.sck_pin  = SPI_SCK_PIN;
    APP_ERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, NULL, NULL));
		
  	// init bmi160 sensor // 初始化感應器
	sensor.id = 1 ; 
    sensor.interface = BMI160_SPI_INTF;
    sensor.read = spi1_read_transfer;
    sensor.write = spi1_write_transfer;
    sensor.delay_ms = user_delay_ms;

	int8_t rslt = BMI160_OK;
    uint8_t reg_addr = BMI160_CHIP_ID_ADDR; // chip_id address // chip_id暫存器位置
    uint8_t data;
    uint16_t len = 1;
    rslt = bmi160_get_regs(reg_addr, &data, len, &sensor); // read sensor chip_id // 讀取chip_id資料

    // print result // 輸出結果
		SEGGER_RTT_printf( 0, "rslt = %d \n", rslt ) ; 
		SEGGER_RTT_printf( 0, "data = %d \n", data ) ; 
		
} // main()

4.result : 

both of rslt and data are 0 .

I have referenced two websites : 

1. BMI160 sensor API Introduction 

2.How to initializate SPI user interface?

Thanks for help!

Parents Reply Children
  • I modify functions spi1_read_transfer &  spi1_write_transfer and it can get chip_id. 

    You can try it.

    static uint8_t       no_use = 0xFF ;
    
    int8_t spi1_read_transfer(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t length)
    {
    	ret_code_t ret ;
    	uint8_t read_temp[ length + 1 ] ;
    	
        ret = nrf_drv_spi_transfer(&spi, &reg_addr, 1, read_temp, length + 1 ) ;	
    	nrf_delay_ms(5); 
    	
    	for( int i = 1 ; i < length + 1 ; i ++ )
    	  reg_data[i-1] = read_temp[i] ;
    	
    	return (int8_t)ret;	
    }
    
    int8_t spi1_write_transfer(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t length)
    {
    	ret_code_t ret;
    	uint8_t write_temp[ length + 1 ] ;
    	write_temp[0] = reg_addr ;
    	for( int i = 1 ; i < length + 1 ; i ++ )
    	  write_temp[i] = reg_data[i-1] ;
    
        ret = nrf_drv_spi_transfer(&spi, write_temp, length + 1, &no_use, 1 ) ;
    	nrf_delay_ms(5) ;
    	
    	return (int8_t)ret;	
    }

  • It is working now, but we have to  OR the read register with  0x80 to be able to read, we did an AND before.

  • Hello,

    I was wondering if I could get some help. I am using MikeLin's code, in conjunction with the link below to access the BMI160. This is my output - I am able to get the chip ID,  sensor counter value, but not the raw acc data - just zeros. I switched the GPIO pins around, checked connections, and am using the NRF VDD. None of them seem to make a difference. Will appreciate any advice.

    github.com/.../bmi160_defs.h

    Setting SPI mode complete.
    Initialisation of ACC sensor complete.
    Counter: 13478970, x: 0, y: 0, z: 0
    Counter: 13479477, x: 0, y: 0, z: 0
    Counter: 13479983, x: 0, y: 0, z: 0
    Counter: 13480489, x: 0, y: 0, z: 0
    Counter: 13480995, x: 0, y: 0, z: 0
    Counter: 13481500, x: 0, y: 0, z: 0
    Counter: 13482006, x: 0, y: 0, z: 0
    Counter: 13482512, x: 0, y: 0, z: 0
    Counter: 13483018, x: 0, y: 0, z: 0
    Counter: 13483523, x: 0, y: 0, z: 0

    Thanks,

    Ed

  • I'm facing the same issue. I checked that the spi is working and the BMI160 is awake but the acceleration and gyroscope values are zero. Do I need to start the acquisition and how to do it?

    Augustin

  • You may want to have a look at this driver. github.com/.../ag_bmi160.cpp

    It works well in both i2c and spi and also support bmm150 mag sensor connected to the bmi160 secondary interface.  We used many drivers in this library our own product and very satisfied with it.

Related