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

BMX160 not working correctly over SPI.

I am trying to get a BMX160 working over SPI. I was following this post  to make this code using the SPI example from the SDK as a basis. I am using SDK 15.3 with a nRF52840 in SES.

Below is my code

#include "nrf_drv_spi.h"
#include "app_util_platform.h"
#include "nrf_gpio.h"
#include "nrf_delay.h"
#include "boards.h"
#include "app_error.h"
#include <string.h>
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"

#include "bmi160.h"
#include "bmi160_defs.h"


#define SPI_INSTANCE  0 /**< SPI instance index. */
static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE);  /**< SPI instance. */
static volatile bool spi_xfer_done;  /**< Flag used to indicate that SPI instance completed the transfer. */

struct bmi160_dev sensor;
static uint8_t filler= 0xFF;

/**
 * @brief SPI user event handler.
 * @param event
 */
void spi_event_handler(nrf_drv_spi_evt_t const * p_event,
                       void *                    p_context)
{
    spi_xfer_done = true;
    NRF_LOG_INFO("Transfer completed.");
}

void spi_init(void)
{
	ret_code_t err_code;
	
	// GPIO PIN SETTINGS
	nrf_gpio_cfg_output(IMU_SPI_CS);
	nrf_gpio_cfg_output(IMU_SPI_SDO);
	nrf_gpio_cfg_output(IMU_SPI_SCK);
	nrf_gpio_cfg_input(IMU_SPI_SDI, NRF_GPIO_PIN_PULLDOWN);

	nrf_gpio_pin_clear(IMU_SPI_SDO);
	nrf_gpio_pin_clear(IMU_SPI_SCK);
	nrf_gpio_pin_set(IMU_SPI_CS);
	
	// init spi
	nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
	spi_config.ss_pin = IMU_SPI_CS;
	spi_config.miso_pin = IMU_SPI_SDI;
	spi_config.mosi_pin = IMU_SPI_SDO;
	spi_config.sck_pin = IMU_SPI_SCK;
	
	err_code = nrf_drv_spi_init(&spi, &spi_config, spi_event_handler/*NULL*/, NULL);
	APP_ERROR_CHECK(err_code);
}



int8_t spi_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 spi_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, &filler, 1);
     nrf_delay_ms(5);

     return (int8_t)ret;
}

void init_bmi_sensor(void)
{
    nrf_gpio_pin_set(LEDB_3);
    sensor.id = 1 ; 
    sensor.interface = BMI160_SPI_INTF;
    sensor.read = spi_read_transfer;
    sensor.write = spi_write_transfer;
    sensor.delay_ms = nrf_delay_ms;        

    int8_t rslt = BMI160_OK;
    rslt = bmi160_init(&sensor);
    nrf_gpio_pin_clear(LEDB_3);
}



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

    nrf_gpio_cfg_output(LEDB_3);
    nrf_gpio_cfg_output(LEDG_2);
    nrf_gpio_pin_clear(LEDB_3);
    nrf_gpio_pin_clear(LEDG_2);
    
    spi_init();
    init_bmi_sensor();

    NRF_LOG_INFO("SPI started.");

        /* Call the "bmi160_init" API as a prerequisite before performing self test
        * since invoking self-test will reset the sensor */
        int8_t rslt;
	rslt = bmi160_perform_self_test(BMI160_ACCEL_ONLY, &sensor);
	/* Utilize the enum BMI160_GYRO_ONLY instead of BMI160_ACCEL_ONLY
	   to perform self test for gyro */
	if (rslt == BMI160_OK) {
		NRF_LOG_INFO("ACCEL SELF TEST RESULT SUCCESS");
	} else {
		NRF_LOG_INFO("ACCEL SELF TEST RESULT FAIL");
	}



    while(1)
    {
        int8_t rslt = BMI160_OK;
        uint8_t reg_addr = BMI160_CHIP_ID_ADDR;
        uint8_t data;
        uint16_t len = 1;
        rslt = bmi160_get_regs(reg_addr, &data, len, &sensor);
        
        NRF_LOG_INFO("rslt = %d", rslt);
        NRF_LOG_INFO("data = %d", data);
        NRF_LOG_FLUSH();
        nrf_delay_ms(500);
    }
    
}

And below is my output in the console.

I am not sure if I have made and error in my code to cause a test fail and not give me any outputs for the chip id.

I have also used this post on Bosch's forum as a reference for difference between BMI160 and BMX160. 

Is there anything in my code that could be causing an error that I can fix?

Parents
  • Hi,

    Please try to place your transfer and receive buffers in static memory. I.e., define them globally like in the example application or use the 'static' keyword when you define  write_temp and read_temp. Also, if you could try to replace nrf_delay_ms(5) with "while(spi_xfer_done); spi_xfer_done=false) to ensure the transaction is complete before accessing the data (though a 5ms delay should have been sufficient). 

Reply
  • Hi,

    Please try to place your transfer and receive buffers in static memory. I.e., define them globally like in the example application or use the 'static' keyword when you define  write_temp and read_temp. Also, if you could try to replace nrf_delay_ms(5) with "while(spi_xfer_done); spi_xfer_done=false) to ensure the transaction is complete before accessing the data (though a 5ms delay should have been sufficient). 

Children
No Data
Related