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
  • Hi,

    Do you have a logic analyzer that you can use to see what goes on on the TWI bus?

    Have you tried a simple example like the TWI Scanner, to see if you get any response from BMI160 at all?

  • We have tried to connect to the BMI160 using i2c and we could receive some data from it.

  • 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

Related