Bosch Sensortec Community

    cancel
    Showing results forย 
    Search instead forย 
    Did you mean:ย 

    BMX055 constant read from FIFO returns -32768

    BMX055 constant read from FIFO returns -32768

    KamWo
    New Poster

    Hello,

    I use BMX 055 with 12MHz MCU (Lpc1343 Cortex-M3) and get data through I2C. I2C is set to 100kHz.

    When I read first frame of data from gyroscope with FIFO queue data for X and Y axises seems reasonable (a sensor lies still on a desk), but data for Z axis sometimes is ok and sometimes has value -32768 (0x8000).

    After first frame data for all axises has value -32768. What is the reason?

     

    #include "LPC13xx.h"
    
    #include <cr_section_macros.h>
    
    #define POWER_ON_IOCON (0x1 << 16)
    #define DEASSERT_I2C_RESET (0x1 << 1)
    #define POWER_ON_I2C (0x1 << 5)
    #define PIO0_4_FUNC_I2C_SCL (0x1 << 0)
    #define PIO0_5_FUNC_I2C_SDA (0x1 << 0)
    
    #define I2C_ENABLE (0x1 << 6)
    #define I2C_SCL_HIGH_TIME (60 << 0)
    #define I2C_SCL_LOW_TIME (60 << 0)
    
    #define I2C_START_BIT (0x1 << 5)
    #define I2C_STOP_BIT (0x1 << 4)
    #define I2C_ACK_BIT (0x1 << 2)
    
    #define I2C_SI_BIT (0x1 << 3)
    #define I2C_SIC_BIT I2C_SI_BIT
    
    #define ACC_BUFFER_SIZE 6
    
    int16_t x,y,z;
    float fx, fy, fz;
    unsigned char i = 0;
    int stop = 1, idx;
    char buffer[ACC_BUFFER_SIZE];
    
    int main(void) {
    	LPC_SYSCON->PRESETCTRL |= DEASSERT_I2C_RESET;
    	LPC_SYSCON->SYSAHBCLKCTRL |= POWER_ON_I2C | POWER_ON_IOCON;
    	LPC_IOCON->PIO0_4 |= PIO0_4_FUNC_I2C_SCL;
    	LPC_IOCON->PIO0_5 |= PIO0_5_FUNC_I2C_SDA;
    
    	NVIC_EnableIRQ(I2C_IRQn);
    
    	LPC_I2C->CONSET |= I2C_ENABLE;
    	LPC_I2C->SCLH = I2C_SCL_HIGH_TIME;
    	LPC_I2C->SCLL = I2C_SCL_LOW_TIME;
    
        // Enter an infinite loop, just incrementing a counter
        while(1) {
            if (stop == 1) {
            	stop = 0;
            	// answer with ACK
            	LPC_I2C->CONSET |= I2C_ACK_BIT;
            	LPC_I2C->CONSET |= I2C_START_BIT;
            }
            // "Dummy" NOP to allow source level single
            // stepping of tight while() loop
            __asm volatile ("nop");
        }
        return 0 ;
    }
    
    void processGyroData() {
    	x = (int16_t) (((int16_t)buffer[1] << ๐Ÿ˜Ž | buffer[0]);
    	y = (int16_t) (((int16_t)buffer[3] << ๐Ÿ˜Ž | buffer[2]);
    	z = (int16_t) (((int16_t)buffer[5] << ๐Ÿ˜Ž | buffer[4]);
    }
    
    void I2C_IRQHandler(void) {
    	volatile unsigned int statusCode = LPC_I2C->STAT;
    	switch(statusCode) {
    
    	case 0x08:
                    //address of gyro
    		LPC_I2C->DAT = 0x68 << 1;
                    // start condition on bus
    		LPC_I2C->CONCLR = I2C_START_BIT;
    		break;
    	case 0x18: //SLA+W has been transmitted; ACK has been received.
                    // read register at address 0x3F (FIFO)
    		LPC_I2C->DAT = 0x3F;
    
    		break;
    	case 0x20: // SLA+W has been transmitted; NOT ACK has been received.
    	case 0x28: // Data byte in I2DAT has been transmitted; ACK has been received.
    		LPC_I2C->CONSET = I2C_START_BIT;
    		break;
    	case 0x10: // A Repeated START condition has been transmitted.
    		LPC_I2C->CONCLR = I2C_START_BIT;
    		LPC_I2C->DAT = (0x68 << 1) | 1;
    		break;
    	case 0x40:
    		break;
    	case 0x50:
    		idx = i % ACC_BUFFER_SIZE;
    		buffer[idx] = LPC_I2C->DAT;
       		if (idx == ACC_BUFFER_SIZE - 1) {
    			processGyroData();
    			__asm volatile ("nop");
    		}
    		i++;
    		break;
    	case 0x58:
    		LPC_I2C->CONSET = I2C_STOP_BIT;
     		stop = 1;
    		break;
    	default:
    		break;
    	}
    	LPC_I2C->CONCLR = I2C_SIC_BIT;
    }

     

    6 REPLIES 6

    Yanchao
    Community Moderator
    Community Moderator

    Hi,

    BMX055 include 3 sensor, accel ->bma2x2, gyro->bmg160, mag->bmm150. Before use gyro of BMX055, please refer to BMG160_driver that already have fifo read function. If use accel, please refer to BMA2x2_driver .

    From your code, I didn't get gyro initial function, so please follow BMX055 work flow read/write sensor and then read fifo.

    Best regards.

    Hi Yanchao,
    thank you for your reply.

    What is "gyro initial function" where in datasheet can I find information about having to initialize gyro?

    I have read BMG160_driver's source and found "bmg160_read_fifo_data" function.

     

    BMG160_RETURN_FUNCTION_TYPE bmg160_read_fifo_data(struct fifo_configuration *fifo_conf)
    {
        /* variable used to return the bus communication status*/
        BMG160_RETURN_FUNCTION_TYPE comres;
        u8 fifo_frame_count = 0;
        u8 fifo_data_select = 0;
        u8 fifo_tag = 0;
        u16 fifo_data_bytes = 0;
    
        if (p_bmg160 == BMG160_NULL || fifo_conf->fifo_data == BMG160_NULL)
        {
            /* check the p_bmg160 is NULL or fifo_data is not assigned*/
            comres = E_BMG160_NULL_PTR;
        }
        else
        {
            /*Frames in FIFO is stored */
            comres = bmg160_get_fifo_frame_count(&fifo_frame_count);
    
            /*FIFO data select value is stored*/
            comres += bmg160_get_fifo_data_select(&fifo_data_select);
    
            /*FIFO data tag is stored*/
            comres += bmg160_get_fifo_tag(&fifo_tag);
    
            /*Number of bytes in FIFO is calculated*/
            if (fifo_data_select == BMG160_FIFO_XYZ_DATA_ENABLED)
            {
                /*Number of bytes in FIFO when XYZ data are enabled*/
                if (fifo_tag == BMG160_FIFO_TAG_ENABLED)
                {
                    /*Number of bytes in FIFO when XYZ data
                     * are enabled with tag (in register 0x3D)
                     */
                    fifo_data_bytes = fifo_frame_count * BMG160_FIFO_XYZ_AXES_TAG_FRAME_SIZE;
                }
                else
                {
                    /*Number of bytes in FIFO when XYZ data
                     * are enabled without tag
                     */
                    fifo_data_bytes = fifo_frame_count * BMG160_FIFO_XYZ_AXES_FRAME_SIZE;
                }
            }
            else
            {
                /*No of bytes in FIFO when single axis data enabled*/
                if (fifo_tag == BMG160_FIFO_TAG_ENABLED)
                {
                    /*Number of bytes in FIFO when single axis data
                     * is enabled in FIFO without tag
                     */
                    fifo_data_bytes = fifo_frame_count * BMG160_FIFO_SINGLE_AXIS_TAG_FRAME_SIZE;
                }
                else
                {
                    /*Number of bytes in FIFO when single axis data
                     * is enabled in FIFO without tag
                     */
                    fifo_data_bytes = fifo_frame_count * BMG160_FIFO_SINGLE_AXIS_FRAME_SIZE;
                }
            }
            if (fifo_conf->fifo_length > fifo_data_bytes)
            {
                /*Number of bytes in FIFO is read entirely when user
                 * reads more FIFO data than available
                 */
                fifo_conf->fifo_length = fifo_data_bytes;
            }
    
            /* Read the fifo data */
            comres += p_bmg160->BMG160_BURST_READ_FUNC(p_bmg160->dev_addr,
                                                       BMG160_FIFO_DATA_ADDR,
                                                       fifo_conf->fifo_data,
                                                       fifo_conf->fifo_length);
        }
    
        return comres;
    }

     

     

    firstly it reads how many bytes there are to read and reads exactly that numbr of bytes.
    My problem is different. I start by addressing FIFO register (0x3F) and after repeated start I read bytes constantly (I did this based on datasheet example how to read Accelerometer data from 0x02 register).

    Screenshot from 2021-02-23 18-44-53.png

     

     

     

     

     

     

     

     

     

     

     

     

     

    Here is the code that I use currently:

     

    #include "LPC13xx.h"
    
    #include <cr_section_macros.h>
    
    #define POWER_ON_IOCON (0x1 << 16)
    #define DEASSERT_I2C_RESET (0x1 << 1)
    #define POWER_ON_I2C (0x1 << 5)
    #define PIO0_4_FUNC_I2C_SCL (0x1 << 0)
    #define PIO0_5_FUNC_I2C_SDA (0x1 << 0)
    
    #define I2C_ENABLE (0x1 << 6)
    #define I2C_SCL_HIGH_TIME (60 << 0)
    #define I2C_SCL_LOW_TIME (60 << 0)
    
    #define I2C_START_BIT (0x1 << 5)
    #define I2C_STOP_BIT (0x1 << 4)
    #define I2C_ACK_BIT (0x1 << 2)
    
    #define I2C_SI_BIT (0x1 << 3)
    #define I2C_SIC_BIT I2C_SI_BIT
    
    #define ACC_BUFFER_SIZE 6
    
    #define ACC_ADDR 0x18
    #define GYR_ADDR 0x68
    #define READ_DATA(addr) ((addr << 1) | 0x1)
    #define WRITE_DATA(addr) ((addr << 1) & (~0x1))
    
    
    int16_t x,y,z;
    float fx, fy, fz;
    unsigned char i = 0, idx;
    int stop = 1;
    char buffer[ACC_BUFFER_SIZE] = {0, 0, 0, 0, 0, 0};
    volatile int statusCode;
    
    int main(void) {
    	LPC_SYSCON->PRESETCTRL |= DEASSERT_I2C_RESET;
    	LPC_SYSCON->SYSAHBCLKCTRL |= POWER_ON_I2C | POWER_ON_IOCON;
    	LPC_IOCON->PIO0_4 |= PIO0_4_FUNC_I2C_SCL;
    	LPC_IOCON->PIO0_5 |= PIO0_5_FUNC_I2C_SDA;
    
    	NVIC_EnableIRQ(I2C_IRQn);
    
    	LPC_I2C->CONSET |= I2C_ENABLE;
    	LPC_I2C->SCLH = I2C_SCL_HIGH_TIME;
    	LPC_I2C->SCLL = I2C_SCL_LOW_TIME;
    
    	// Enter an infinite loop, just incrementing a counter
        while(1) {
            if (stop == 1) {
            	stop = 0;
            	// Sets start condition
            	LPC_I2C->CONSET |= I2C_START_BIT;
            }
            // "Dummy" NOP to allow source level single
            // stepping of tight while() loop
            __asm volatile ("nop");
        }
        return 0 ;
    }
    
    void processGyroData() {
    	x = (int16_t) (((int16_t)buffer[1] << ๐Ÿ˜Ž | buffer[0]);
    	y = (int16_t) (((int16_t)buffer[3] << ๐Ÿ˜Ž | buffer[2]);
    	z = (int16_t) (((int16_t)buffer[5] << ๐Ÿ˜Ž | buffer[4]);
    }
    
    int k;
    void I2C_IRQHandler(void) {
    	statusCode = LPC_I2C->STAT;
    	switch(statusCode) {
    
    	case 0x08: // A START condition has been transmitted.
    		LPC_I2C->DAT = WRITE_DATA(GYR_ADDR);
    		LPC_I2C->CONCLR = I2C_START_BIT;
    		break;
    	case 0x18: //SLA+W has been transmitted; ACK has been received.
                    /* 
                      * reading from 0x3F register constantly gives -32768
                      */
    		LPC_I2C->DAT = 0x3F; //acc or gyr FIFO register 0x3F
    		break;
    	case 0x28: // Data byte in I2DAT has been transmitted; ACK has been received.
    		LPC_I2C->CONSET = I2C_START_BIT;
    		break;
    	case 0x10: // A Repeated START condition has been transmitted.
    		LPC_I2C->DAT = READ_DATA(GYR_ADDR);
    		break;
    	case 0x40:
    		LPC_I2C->CONCLR = I2C_START_BIT;
    		LPC_I2C->CONSET = I2C_ACK_BIT;
    		break;
    	case 0x50:
    		k = idx++ % ACC_BUFFER_SIZE;
    		buffer[k] = LPC_I2C->DAT;
    		if ((idx % ACC_BUFFER_SIZE) == 0) {
    			processGyroData();
    		}
    		break;
    	case 0x58:
    		LPC_I2C->CONSET = I2C_STOP_BIT;
     		stop = 1;
    		break;
    	default:
    		break;
    	}
    	LPC_I2C->CONCLR = I2C_SIC_BIT;
    }

     

    When I read 6 bytes of data starting from 0x02 register and after that I stop the transmision and start it after stopping everything is OK this way I can read data constantly.

    But when I read data from 0x3F register (FIFO) first data frame X and Y axises are OK but Z axis has value -32768. In next frame every axis has value -32768.

    Fifo mode is Bypass. Datasheet states:


    BYPASS Mode: In bypass mode, only the current sensor data can be read out from the
    FIFO address. Essentially, the FIFO behaves like the STREAM mode with a depth of 1.
    Compared to reading the data from the normal data registers, the advantage to the user
    is that the packages X, Y, Z are from the same timestamp, while the data registers are
    updated sequentially and hence mixing of data from different axes can occur.


    If the FIFO is read beyond the FIFO fill level zeroes (0) will be read. If the FIFO is read beyond
    the FIFO fill level the read or burst read access time must not exceed the sampling time t SAMPLE .
    Otherwise frames may be lost.

    I assume that reading data too slow will cause loss of data (i.e. every nth data from gyro will be read). Reading data too fast will cause reading of zeros every time when there is no new data.
    So what could cause reading -32768 from FIFO as I did not find any information about it in datasheet?

    Yanchao
    Community Moderator
    Community Moderator

    Hi,

    If your could read 0x02 register success, the I2C is right.

    1 confirm you have enbale fifo mode check by func bmg160_get_fifo_mode(), read FIFO length by bmg160_get_fifo_frame_count(), clear FIFO buffer by wirte 0x3E bit<7,6>. These operation is only register operation, could confirm the FIFO state.

    2 From BMG160_driver, you could find fifo read by BMG160_BURST_READ_FUNC.

    3 you could lower the odr freq, then fifo fill rate also down.

    Best regards.

     

    Thanks Yanchao,

    I was not replying so long because in spite of trying to read the data as you instructed me I still receive wrong values. I bought BMX055 shuttle board and will see if the problem will be solved. Maybe my current IC is broken.

    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