Bosch Sensortec Community

    cancel
    Showing results for 
    Search instead for 
    Did you mean: 

    BMI270 unnable to write to a register (0x53)

    BMI270 unnable to write to a register (0x53)

    Genadi
    New Poster

    Hello, everyone

    I am trying to implement your driver on my evaluation board EFM32. Everything went smoothly until I got to the part where I had to implement HW interrupt for any-motion feature. I didn't find in your example (GitHub) where you configure the INT1_IO_CTRL, INT2_IO_CTRL and INT_LATCH registers (and didn't see any behavior on the pin either), so I went further and tried to write the needed configuration manually, but for some reason, register INT1_IO_CTRL didn't change (when INT_LATCH did). I2C and the rest of the driver work fine, I can read the status register and validate if the interrupt had been fired. 

    Here is what I get when I am printing the register values (the first line I get before bmi270_set_gpio_config function and the second line comes right after):

    Genadi_0-1682348900489.png

     

     

    Could you please kindly explain to me what am  I missing?

    The code is attached below.

    BR, Genadi

     

    /*******************************************************************************
     *
     *     BBBBBBB      IIII   NNN     N   AA       TTTTTTTT   AA
     *     B      B      II    N N     N   AAA        TTTT     AAA
     *     B      BB     II    N  N    N   AAAA        TT      AAAA
     *     BBBBBBBBB     II    N   N   N   AAAAA       TT      AAAAA
     *     B        BB   II    N   N   N   AA   A      TT      AA   A
     *     B        BB   II    N    N  N   AA    A     TT      AA    A
     *     BBBBBBBBBB   IIII   N    NNNN   AA     A   TTTT     AA     A
     *
     ********************************************************************************
     * All software (C)
     ******************************************************************************/
    
    /*******************************************************************************
     * Module name: 		BMI270_Handler.c
     *
     * Module contents: BMI270 API
     *
     * Description:			Accelerometer and gyroscope HAL driver.
     *
     * Author: 					Genadi Manoilenko
     *
     * Date: 						04/2023
     *
     ******************************************************************************/
    
    /*******************************************************************************
     *  Includes
     ******************************************************************************/
    #include "BMI270_Handler.h"
    
    /*******************************************************************************
     * Variables structures
     *******************************************************************************/
    
    /*******************************************************************************
     * BMI270 object
     *******************************************************************************/
    /* Sensor initialization configuration. */
    struct bmi2_dev bmi2_dev;
    /* Create an instance of sensor data structure. */
    /* Assign accel sensor to variable. */
    uint8_t sensor_list[2] = { BMI2_ACCEL, BMI2_ANY_MOTION };
    /* Initialize the interrupt status of accel. */
    uint16_t int_status = 0;
    struct bmi2_sens_data sensor_data = 
    { 
        .acc = { 0 }, 
        .gyr = { 0 }, 
        .aux_data = { 0 }, 
        .sens_time = 0, 
    };
    struct bmi2_acc_mps2_data acc_mps2 =
    {
        .x_mps2 = 0,
        .y_mps2 = 0,
        .z_mps2 = 0,
    };
    /*******************************************************************************
     *  Constants and Macros
     ******************************************************************************/
    
    /*******************************************************************************
     *  Static Data Declarations
     ******************************************************************************/
    
    /*******************************************************************************
     *  Data types
     ******************************************************************************/
    
    /*******************************************************************************
     *  Private Functions Prototypes
     ******************************************************************************/
    /*!
     *  @brief This internal API is used to set configurations for any-motion.
     *
     *  @param[in] bmi2_dev       : Structure instance of bmi2_dev.
     *
     *  @return Status of execution.
     */
    static int8_t set_any_motion_config(struct bmi2_dev *bmi2_dev);
    
    /*!
     *  @brief This function prints the accelerometer data to the log.
     *
     */
    static void bmi270_print_acc_data(void);
    
    
    /*!
     *  @brief This internal API is used to set configurations for accel.
     *
     *  @param[in] dev       : Structure instance of bmi2_dev.
     *
     *  @return Status of execution.
     */
    static int8_t set_accel_config(struct bmi2_dev *bmi2_dev);
    
    /*!
     *  @brief This function converts lsb to meter per second squared for 16 bit accelerometer at
     *  range 2G, 4G, 8G or 16G.
     *
     *  @param[in] val       : LSB from each axis.
     *  @param[in] g_range   : Gravity range.
     *  @param[in] bit_width : Resolution for accel.
     *
     *  @return Gravity.
     */
    static float lsb_to_mps2(int16_t val, float g_range, uint8_t bit_width);
    
    static int8_t bmi270_set_gpio_config(void);
    
    /*******************************************************************************
     *  Public Function Bodies
     ******************************************************************************/
    
    /*****************************************************************************
     * Function name: bmi270_I2C_Transmit
     *
     * Description: This is a warper function which call I2C transmit function to perform:
     * S + SALVE_ADDR(W) + DATA0(REG_ADD), DATA1-n(write data) + P.
     *
     * Parameters:  TxWriteBuf -  a pointer to Tx array which include:
     *                            register address,
     *                            write data
     *              txsize - number of bytes to transmit.
     * Returns:     The status of the I2C operation.
     ******************************************************************************/
    uint16_t bmi270_I2C_Transmit(uint8_t *TxWriteBuf, uint16_t txsize)
    {
    	I2C_TransferReturn_TypeDef status;
    
    	status = I2C0_D_Write(ADPD4101_ADDRESS, TxWriteBuf, txsize);
    
    	return (status);
    }
    
    /*****************************************************************************
     * Function name: bmi270_I2C_TxRx
     *
     * Description: This is a warper function which call I2C transmit & receive
     * function to perform:
     * S + SLAVE_ADDR(W) + DATA(REG_ADD) + Sr + SLAVE_ADDR(R) + DATA + P.
     *
     * Parameters:  register_address -  a pointer to array which hold register address.
     *              buffer - array to hold read data.
     *              txsize - number of bytes in register_address.
     *              rxsize - number of bytes to read.
     * Returns:     The status of the I2C operation.
     ******************************************************************************/
    uint16_t bmi270_I2C_TxRx(uint8_t *register_address, uint8_t *buffer, uint16_t txsize, uint16_t rxsize)
    {
    	I2C_TransferReturn_TypeDef status;
    
    	status = I2C0_D_WriteRead(ADPD4101_ADDRESS, register_address, txsize, buffer, rxsize);
    
    	return (status);
    }
    
    void bmi270_test()
    {
    	uint8_t rslt;
    	uint8_t data[3] = {0};
    
    	rslt = bmi2_get_regs(BMI2_INT1_IO_CTRL_ADDR, data, 3, &bmi2_dev);
    	if(rslt != FuncSuccess)
    	{
        	bmi2_error_codes_print_result(rslt);
    		Error_Handler(Err_BMI270_Init);
    	}
    	printf("0x53 = %d, 0x54 = %d, 0x55 = %d\n", data[0], data[1], data[2]);
    
        rslt = bmi270_set_gpio_config();
    	if(rslt != FuncSuccess)
    	{
        	bmi2_error_codes_print_result(rslt);
    		Error_Handler(Err_BMI270_Init);
    	}
    
    	rslt = bmi2_get_regs(BMI2_INT1_IO_CTRL_ADDR, data, 3, &bmi2_dev);
    	if(rslt != FuncSuccess)
    	{
        	bmi2_error_codes_print_result(rslt);
    		Error_Handler(Err_BMI270_Init);
    	}
    	printf("0x53 = %d, 0x54 = %d, 0x55 = %d\n", data[0], data[1], data[2]);
    }
    
    /******************************************************************************/
    /*!            Functions                                        */
    
    /* This function starts the execution of program. */
    void bmi270_Init(void)
    {
    	/* Status of api are returned to this variable. */
    	int8_t rslt;
    
        /* Select features and their pins to be mapped to. */
        struct bmi2_sens_int_config sens_int = { .type = BMI2_ANY_MOTION, .hw_int_pin = BMI2_INT1 };
    
    	/* Trigger a soft reset */
    	bmi2_soft_reset(&bmi2_dev);
    
    	/* Interface reference is given as a parameter
    	 * For I2C : BMI2_I2C_INTF
    	 * For SPI : BMI2_SPI_INTF
    	 */
    	rslt = bmi2_interface_init(&bmi2_dev, BMI2_I2C_INTF);
        if(rslt != FuncSuccess)
    	{
        	bmi2_error_codes_print_result(rslt);
    		Error_Handler(Err_BMI270_Init);
    	}
    
    	/* Initialize bmi270. */
    	rslt = bmi270_init(&bmi2_dev);
        if(rslt != FuncSuccess)
    	{
        	bmi2_error_codes_print_result(rslt);
    		Error_Handler(Err_BMI270_Init);
    	}
    
    	/* Accel configuration settings. */
    	rslt = set_accel_config(&bmi2_dev);
    	if(rslt != FuncSuccess)
    	{
        	bmi2_error_codes_print_result(rslt);
    		Error_Handler(Err_BMI270_Init);
    	}
    	
    	/* Set feature configurations for any-motion. */
    	rslt = set_any_motion_config(&bmi2_dev);
    	if(rslt != FuncSuccess)
    	{
        	bmi2_error_codes_print_result(rslt);
    		Error_Handler(Err_BMI270_Init);
    	}
    
    	/* Map the feature interrupt for any-motion. */
    	rslt = bmi270_map_feat_int(&sens_int, 1, &bmi2_dev);
    	if(rslt != FuncSuccess)
    	{
        	bmi2_error_codes_print_result(rslt);
    		Error_Handler(Err_BMI270_Init);
    	}
    
    	// TODO: delete me
    	bmi270_test();
    
    	/* NOTE:
    	 * Accel enable must be done after setting configurations
    	 */
    	rslt = bmi270_sensor_enable(sensor_list, sizeof(sensor_list), &bmi2_dev);
    	if(rslt != FuncSuccess)
    	{
        	bmi2_error_codes_print_result(rslt);
    		Error_Handler(Err_BMI270_Init);
    	}
    
    	printf("BMI270 init complited\n");
    }
    
    /*!
     * @brief This internal API is used to set configurations for accel.
     */
    static int8_t set_accel_config(struct bmi2_dev *bmi2_dev)
    {
    	/* Status of api are returned to this variable. */
    	int8_t rslt;
    
    	/* Structure to define accelerometer configuration. */
    	struct bmi2_sens_config config;
    
    	/* Configure the type of feature. */
    	config.type = BMI2_ACCEL;
    
    	/* Get default configurations for the type of feature selected. */
    	rslt = bmi270_get_sensor_config(&config, 1, bmi2_dev);
    	bmi2_error_codes_print_result(rslt);
    
    	if (rslt == BMI2_OK)
    	{
    		/* Set Output Data Rate */
    		config.cfg.acc.odr = BMI270_OUTPUT_RATE;
    
    		/* Gravity range of the sensor (+/- 2G, 4G, 8G, 16G). */
    		config.cfg.acc.range = BMI270_ACC_RANGE;
    
    		/* The bandwidth parameter is used to configure the number of sensor samples that are averaged
    		 * if it is set to 2, then 2^(bandwidth parameter) samples
    		 * are averaged, resulting in 4 averaged samples.
    		 * Note1 : For more information, refer the datasheet.
    		 * Note2 : A higher number of averaged samples will result in a lower noise level of the signal, but
    		 * this has an adverse effect on the power consumed.
    		 */
    		config.cfg.acc.bwp = BMI270_AVRG_SAMPLES;
    
    		/* Enable the filter performance mode where averaging of samples
    		 * will be done based on above set bandwidth and ODR.
    		 * There are two modes
    		 *  0 -> Ultra low power mode
    		 *  1 -> High performance mode(Default)
    		 * For more info refer datasheet.
    		 */
    		config.cfg.acc.filter_perf = BMI270_POWER_MODE;
    
    		/* Set the accel configurations. */
    		rslt = bmi270_set_sensor_config(&config, 1, bmi2_dev);
    		bmi2_error_codes_print_result(rslt);
    
    		/* Map data ready interrupt to interrupt pin. */
    		rslt = bmi2_map_data_int(BMI2_DRDY_INT, BMI2_INT1, bmi2_dev);
    		bmi2_error_codes_print_result(rslt);
    	}
    
    	return rslt;
    }
    
    /*!
     * @brief This function converts lsb to meter per second squared for 16 bit accelerometer at
     * range 2G, 4G, 8G or 16G.
     */
    static float lsb_to_mps2(int16_t val, float g_range, uint8_t bit_width)
    {
    	float half_scale = ((float)(1 << bit_width) / 2.0f);
    
    	return (GRAVITY_EARTH * val * g_range) / half_scale;
    }
    
    /*!
     * @brief This internal API is used to set configurations for any-motion.
     */
    static int8_t set_any_motion_config(struct bmi2_dev *bmi2_dev)
    {
    
        /* Status of api are returned to this variable. */
        int8_t rslt;
    
        /* Structure to define the type of sensor and its configurations. */
        struct bmi2_sens_config config;
    
        /* Configure the type of feature. */
        config.type = BMI2_ANY_MOTION;
    
        /* Get default configurations for the type of feature selected. */
        rslt = bmi270_get_sensor_config(&config, 1, bmi2_dev);
        bmi2_error_codes_print_result(rslt);
        if (rslt == BMI2_OK)
        {
            /* 1LSB equals 20ms. Default is 100ms. */
            config.cfg.any_motion.duration = BMI270_ANY_MOTION_DURATION_mSEC / 20; 
    
            /* 1LSB equals to 0.48mg. Default is 83mg. */
            config.cfg.any_motion.threshold = (uint16_t)(BMI270_ANY_MOTION_THRESHOLD_mG / 0.48);
    
    		printf("select_x = %u\n", config.cfg.any_motion.select_x);
    		printf("select_y = %u\n", config.cfg.any_motion.select_y);
    		printf("select_z = %u\n", config.cfg.any_motion.select_z);
    
            /* Set new configurations. */
            rslt = bmi270_set_sensor_config(&config, 1, bmi2_dev);
            bmi2_error_codes_print_result(rslt);
        }
    
        return rslt;
    }
    
    /*****************************************************************************
     * Function name:	bmi270_Interrupt_Service
     *
     * Description: 	This function manages received interrupt from INT1 and INT2.
     *
     * Parameters:  	None.
     * 
     * Returns:     	RetVal_t.
     ******************************************************************************/
    RetVal_t bmi270_Interrupt_Service()
    {
    	int8_t rslt;
    
    	/* To get the status of accel data ready interrupt. */
    	rslt = bmi2_get_int_status(&int_status, &bmi2_dev);
    	if(rslt != FuncSuccess)
    	{
    		bmi2_error_codes_print_result(rslt);
    		return FuncFailed;
    	}
    
    	/* To check the accel data ready interrupt status. */
    	if (int_status & BMI2_ACC_DRDY_INT_MASK)
    	{
    		rslt = bmi2_get_sensor_data(&sensor_data, &bmi2_dev);
    		if(rslt != FuncSuccess)
    		{
    			bmi2_error_codes_print_result(rslt);
    			return FuncFailed;
    		}
    
    		bmi270_print_acc_data();
    	}
    	/* To check the interrupt status of any-motion. */
    	if (int_status & BMI270_ANY_MOT_STATUS_MASK)
    	{
    		printf("Any-motion interrupt is generated\n");
    	}
    
    	return FuncSuccess;
    }
    
    /*****************************************************************************
     * Function name:	bmi270_print_acc_data
     *
     * Description: 	This function prints the accelerometer data to the log.
     *
     * Parameters:  	None.
     * 
     * Returns:     	None.
     ******************************************************************************/
    static void bmi270_print_acc_data()
    {
    #ifndef BMI270_PRINT_ACC_DATA
    	return;
    #endif
    
    	/* Get accelerometer data for x, y and z axis. */
    	printf("Acc_X = %d, Acc_Y = %d, Acc_Z = %d\n", sensor_data.acc.x, sensor_data.acc.y, sensor_data.acc.z);
    
    	/* Converting lsb to meter per second squared for 16 bit accelerometer at 2G range. */
    	acc_mps2.x_mps2 = lsb_to_mps2(sensor_data.acc.x, 2, bmi2_dev.resolution);
    	acc_mps2.y_mps2 = lsb_to_mps2(sensor_data.acc.y, 2, bmi2_dev.resolution);
    	acc_mps2.z_mps2 = lsb_to_mps2(sensor_data.acc.z, 2, bmi2_dev.resolution);
    
    	/* Print the data in m/s^2. */
    	printf("Acc_ms2_X = %4.2f, Acc_ms2_Y = %4.2f, Acc_ms2_Z = %4.2f\n", acc_mps2.x_mps2, acc_mps2.y_mps2, acc_mps2.z_mps2);
    }
    
    
    /*****************************************************************************
     * Function name:	bmi270_set_gpio_config
     *
     * Description: 	Setup the bmi270 GPIO configuration for the application.
     *
     * Parameters:  	None.
     * 
     * Returns:     	rslt.
     ******************************************************************************/
    static int8_t bmi270_set_gpio_config(void)
    {
    	/* Status of api are returned to this variable. */
    	int8_t rslt;
    
    	const struct bmi2_int_pin_config int_pin_config =
    	{
    		.pin_type = BMI2_INT1,
    
    		/*! Latched or non-latched mode*/
        	.int_latch = BMI2_INT_LATCH,
    
    		/*! Structure to define Interrupt pin configuration */
    		.pin_cfg[0] =
    		{
    			/*! Configure level of interrupt pin */
    			.lvl = BMI2_INT_ACTIVE_HIGH,
    
    			/*! Configure behavior of interrupt pin */
    			.od = BMI2_INT_PUSH_PULL,
    
    			/*! Output enable for interrupt pin */
    			.output_en = BMI2_INT_OUTPUT_ENABLE,
    
    			/*! Input enable for interrupt pin */
    			.input_en = BMI2_INT_INPUT_DISABLE,
    		},
    	};
    
    	rslt = bmi2_set_int_pin_config(&int_pin_config, &bmi2_dev);
    
    	return rslt;
    }
    
    
    /*****************************************************************************
     * Function name:	bmi270_Int_1_Handler
     *
     * Description: 	INT1 interrupt handler.
     *
     * Parameters:  	None.
     * 
     * Returns:     	None.
     ******************************************************************************/
    void bmi270_Int_1_Handler(uint8_t intNo)
    {
    	(void)intNo;
    	printf("BMI270_INT_1_FIRED\n");
    }
    3 REPLIES 3

    BSTRobin
    Community Moderator
    Community Moderator

    Hi Genadi,

    BMI270 sensor API on github provide interface to configure interrupt pins INT1, INT2. You could refer the following example code.
    int8_t Open_BMI270_RDRY_INT(struct bmi2_dev *dev)
    {
    int8_t rslt = BMI2_OK;
    struct bmi2_int_pin_config int_cfg;

    /* Map data ready interrupt to interrupt pin. */
    rslt = bmi2_map_data_int(BMI2_DRDY_INT, BMI2_INT1, dev);
    bmi2_error_codes_print_result(rslt);

    bmi2_get_int_pin_config(&int_cfg, dev);

    int_cfg.pin_type = BMI2_INT1;
    int_cfg.pin_cfg[0].lvl = BMI2_INT_ACTIVE_HIGH;/*Config INT1 rising edge trigging*/
    int_cfg.pin_cfg[0].od = BMI2_INT_PUSH_PULL;
    int_cfg.pin_cfg[0].output_en= BMI2_INT_OUTPUT_ENABLE;

    bmi2_set_int_pin_config(&int_cfg, dev);
    bmi2_error_codes_print_result(rslt);

    return rslt;
    }

    Thank you Robin for your fast reply.

    Your answer helped me a lot, but I had to make some moderation to your code. I had to disable advance power save in order to make the change in the register. Is it a necessary step or did I mess up with the setup?  

     

    BR, Genadi

    BSTRobin
    Community Moderator
    Community Moderator

    Hi Genadi,

    If you would like to enable/disable BMI270 features or modify parameters in config file, you have to disable advance power save.

    Icon--AD-black-48x48Icon--address-consumer-data-black-48x48Icon--appointment-black-48x48Icon--back-left-black-48x48Icon--calendar-black-48x48Icon--center-alignedIcon--Checkbox-checkIcon--clock-black-48x48Icon--close-black-48x48Icon--compare-black-48x48Icon--confirmation-black-48x48Icon--dealer-details-black-48x48Icon--delete-black-48x48Icon--delivery-black-48x48Icon--down-black-48x48Icon--download-black-48x48Ic-OverlayAlertIcon--externallink-black-48x48Icon-Filledforward-right_adjustedIcon--grid-view-black-48x48IC_gd_Check-Circle170821_Icons_Community170823_Bosch_Icons170823_Bosch_Icons170821_Icons_CommunityIC-logout170821_Icons_Community170825_Bosch_Icons170821_Icons_CommunityIC-shopping-cart2170821_Icons_CommunityIC-upIC_UserIcon--imageIcon--info-i-black-48x48Icon--left-alignedIcon--Less-minimize-black-48x48Icon-FilledIcon--List-Check-grennIcon--List-Check-blackIcon--List-Cross-blackIcon--list-view-mobile-black-48x48Icon--list-view-black-48x48Icon--More-Maximize-black-48x48Icon--my-product-black-48x48Icon--newsletter-black-48x48Icon--payment-black-48x48Icon--print-black-48x48Icon--promotion-black-48x48Icon--registration-black-48x48Icon--Reset-black-48x48Icon--right-alignedshare-circle1Icon--share-black-48x48Icon--shopping-bag-black-48x48Icon-shopping-cartIcon--start-play-black-48x48Icon--store-locator-black-48x48Ic-OverlayAlertIcon--summary-black-48x48tumblrIcon-FilledvineIc-OverlayAlertwhishlist