Bosch Sensortec Community

    cancel
    Showing results for 
    Search instead for 
    Did you mean: 

    Reading data from BMI160

    Reading data from BMI160

    Alex2hsrw
    Member

    Hello,

    Im trying to use BMi160 as an external interrupt with MSP430 in low power mode. So far interrupt feature works perfectly and I can wake up MSP430 from sleep mode by moving BMI160. However I also want to read the accel, after its being moved and show data on console. Which does not work correctly.  I am using a function process() to read z-axis accel and printing the values, but i see wrong values as :

    Output in console when accelerometer is laying on table without any movement:
    Z-axis: -24767.000000
    Z-axis: -28095.000000
    Z-axis: 23617.000000
    Z-axis: -4031.000000
    Z-axis: -31167.000000
    Z-axis: -8895.000000
    Z-axis: 2625.000000
    Z-axis: -19390.000000
    Z-axis: 14401.000000
    Z-axis: 31553.000000
    Z-axis: 9281.000000
    Z-axis: 10305.000000
    Z-axis: -32703.000000
    Output in console when accelerometer is moved:
    Z-axis: 12865.000000
    Z-axis: -185.000000
    Z-axis: -129.000000
    Z-axis: -129.000000
    Z-axis: 127.000000
    Z-axis: -128.000000
    Z-axis: 18559.000000
    Z-axis: 51.000000
    Z-axis: -128.000000
    Z-axis: 127.000000
    Z-axis: -128.000000
    Z-axis: -32385.000000
    Z-axis: -25285.000000
    Z-axis: 10561.000000
    Z-axis: 67.000000

    Here it can be seen that when accelerometer is on rest, i get higher values and when accelerometer is being moved, output comes closer to 127 or 128. Sometimes, I can also see random jump in values in between. 
    My Code: 

    #include "driverlib.h"
    #include <gpio.h>
    #include <msp430fr5xx_6xxgeneric.h>
    #include <stdint.h>
    #include <stdio.h>
    
    // Address of the BMI160
    #define SLAVE_ADDR 0x69
    #define MAX_BUFFER_SIZE 20
    #define SAMPLES 1000
    #define ACCEL_SCALE 16384.0 // Scale factor for ±2g range (default)
    int16_t input[SAMPLES] = {0}; // Store samples
    
    void initI2C() {
        UCB1CTLW0 = UCSWRST;                      // Enable SW reset
        UCB1CTLW0 |= UCMODE_3 | UCMST | UCSSEL__SMCLK | UCSYNC; // I2C master mode, SMCLK
        UCB1BRW = 160;                            // fSCL = SMCLK/160 = ~100kHz
        UCB1I2CSA = SLAVE_ADDR;                   // Slave Address
        UCB1CTLW0 &= ~UCSWRST;                    // Clear SW reset, resume operation
    }
    
    void I2C_Master_WriteReg(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, uint8_t count) {
        // Send start condition
        UCB1CTLW0 |= UCTR | UCTXSTT;
        while (!(UCB1IFG & UCTXIFG)); // Wait for TX buffer to be ready
    
        // Send device address with write flag
        UCB1TXBUF = dev_addr << 1; // Address with write bit
        while (!(UCB1IFG & UCTXIFG)); // Wait for TX buffer to be ready
    
        // Send register address
        UCB1TXBUF = reg_addr;
        while (!(UCB1IFG & UCTXIFG)); // Wait for TX buffer to be ready
    
        // Send data
        for (int i = 0; i < count; i++) {
            UCB1TXBUF = data[i];
            while (!(UCB1IFG & UCTXIFG)); // Wait for TX buffer to be ready
        }
    
        // Send stop condition
        UCB1CTLW0 |= UCTXSTP;
        while (UCB1CTLW0 & UCTXSTP); // Wait for stop condition
    }
    
    void I2C_Master_ReadReg(uint8_t dev_addr, uint8_t *data, uint8_t count) {
        // Send repeated start and switch to receive mode
        UCB1CTLW0 &= ~UCTR;
        UCB1CTLW0 |= UCTXSTT;
        while (UCB1CTLW0 & UCTXSTT);
    
        // Receive data
        for (int i = 0; i < count; i++) {
            while (!(UCB1IFG & UCRXIFG0));
            data[i] = UCB1RXBUF;
        }
    
        // Send stop condition
        UCB1CTLW0 |= UCTXSTP;
        while (UCB1CTLW0 & UCTXSTP);
    }
    
    void initGPIO() {
        // I2C pins (P4.0 is SDA, P4.1 is SCL)
        P4SEL1 |= BIT0 | BIT1;
        P4SEL0 &= ~(BIT0 | BIT1);
        // Configure INT1 pin (P3.2) as input
        P3DIR &= ~BIT2;
        P3IES &= ~BIT2; // Interrupt on rising edge
        P3IFG &= ~BIT2; // Clear interrupt flag
        P3IE |= BIT2;   // Enable interrupt
    
        // Configure INT2 pin (P3.3) as input
        P3DIR &= ~BIT3;
        P3IES &= ~BIT3; // Interrupt on rising edge
        P3IFG &= ~BIT3; // Clear interrupt flag
        P3IE |= BIT3;   // Enable interrupt
    
        PM5CTL0 &= ~LOCKLPM5; // Disable the GPIO power-on default high-impedance mode
    }
    
    void init_BMI160_ACC() {
        uint8_t writeData[2];
    
        // Soft reset BMI160
        writeData[0] = 0xB6;
        I2C_Master_WriteReg(SLAVE_ADDR, 0x7E, writeData, 1);
        __delay_cycles(55000); // Delay 55ms for BMI160 to stabilize
    
        // Set accelerometer to LPM mode
        writeData[0] = 0x12;
        I2C_Master_WriteReg(SLAVE_ADDR, 0x7E, writeData, 1);
        __delay_cycles(5000); // Delay 5ms for accelerometer to stabilize
    
        // Set ODR to 100Hz with no average
        writeData[0] = 0x86;
        I2C_Master_WriteReg(SLAVE_ADDR, 0x40, writeData, 1);
    
        // Set both INT1  pin as output, active-high, push-pull
        writeData[0] = 0x0A;
        I2C_Master_WriteReg(SLAVE_ADDR, 0x53, writeData, 1);
    
        // Temporarily latch the interrupt for 80ms
        writeData[0] = 0x09;
        I2C_Master_WriteReg(SLAVE_ADDR, 0x54, writeData, 1);
    
        // Route single-tap interrupt to INT1 pin
        writeData[0] = 0x04;
        I2C_Master_WriteReg(SLAVE_ADDR, 0x55, writeData, 1);
    
        // Configure tap sensing
        writeData[0] = 0x14; // Default values
        I2C_Master_WriteReg(SLAVE_ADDR, 0x60, writeData, 1);
    
        writeData[0] = 0x00; // Default threshold value
        I2C_Master_WriteReg(SLAVE_ADDR, 0x5F, writeData, 1);
    
        // Enable single-tap and double-tap interrupt
        writeData[0] = 0x07;
        I2C_Master_WriteReg(SLAVE_ADDR, 0x50, writeData, 1);
    
    }
    
    #pragma vector=PORT3_VECTOR
    __interrupt void Port_3(void) {
        if (P3IFG & BIT2) {
            P3IFG &= ~BIT2; // Clear the interrupt flag for INT1
            //printf("Single-tap detected!\n");
            process();
        }
    }
    
    void process() {
        for (int i = 0; i < SAMPLES; i++) {
            uint8_t reg_data[2] = {0};
            uint8_t reg_addr = 0x16; // Register address for the Z-axis data (low byte)
            // Write register address
            I2C_Master_WriteReg(SLAVE_ADDR, reg_addr, NULL, 0);
            // Read data
            I2C_Master_ReadReg(SLAVE_ADDR, reg_data, 2);
    
            // Interpret the received data (Z-axis)
            int16_t raw_data = (int16_t)((reg_data[1] << 😎 | reg_data[0]);
    
            // Convert raw data to G
            float acceleration_g = raw_data ;
            printf("Z-axis: %f\n", acceleration_g);
        }
    }
    
     int main(void) {
        WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
        initGPIO();
        initI2C();
        init_BMI160_ACC();
    
        __enable_interrupt(); // Enable global interrupts
        int i = 0;
        while (1) {
            __low_power_mode_3(); // Enter LPM3
        }
    
        return 0;
    }

     

    1 REPLY 1

    FAE_CA1
    Community Moderator
    Community Moderator

    Hi,

    Thanks for your inquiry.

    Please check your code below.

    // Interpret the received data (Z-axis)
            int16_t raw_data = (int16_t)((reg_data[1] <<  | reg_data[0]);
    
            // Convert raw data to G
            float acceleration_g = raw_data ;
            printf("Z-axis: %f\n", acceleration_g);

     (1) It should be (reg_data[1] << 8 | reg_data[0])

    (2) BMI160 accel data has the sensitivity of 16384 LSB/g for x/y/z axes at +/-2g full scale range. So when you want to print z axis g values, you need to divide raw data by 16384 as accelration_g = raw data / 16384.0

    Thanks.

    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