i2c_transfer() reads all zeros

Hello,

I am trying to read data from LS2DE12 accelerometer MEMS chip via I2C bus and I am seeing only zeros for all 3 axes.
I can write to the various registers successfully and read back their content to check the write was successful using this function.

static int32_t lis2de12_readb(uint8_t add, uint8_t *b)
{
    struct i2c_msg msgs[2];

    /* Send the address to read from */
    msgs[0].buf = &add;
    msgs[0].len = 1U;
    msgs[0].flags = I2C_MSG_WRITE | I2C_MSG_STOP;

    /* Read from device. STOP after this. */
    msgs[1].buf = b;
    msgs[1].len = 1U;
    msgs[1].flags = I2C_MSG_READ | I2C_MSG_STOP;

    return i2c_transfer(accelerometer.handle, &msgs[0], 2, LIS2DE12_I2C_ADD);
}

The above is called at initialisation to configure the various registers as shown in the snippets of code below, and all seems to be working ok...

accelerometer_t *lis2de12_initialise(void *dev)
{
    accelerometer.handle = dev;
    uint8_t b,d[8];

    accelerometer.moved = false;
    lis2de12_readb( LIS2DE12_WHO_AM_I,&d[0] );
    if ( d[0] != LIS2DE12_ID )
    {
        LOG_INF( "Fail LIS2" );
        return( NULL );
    }
    else
    {
        LOG_DBG( "OK LIS2" );
        accelerometer.present = true;

        lis2de12_writeb( LIS2DE12_CTRL_REG1, 0x2f ); //0x1f);
        lis2de12_readb( LIS2DE12_CTRL_REG1, &d[0] );
        if ( d[0] != 0x2f )
        {
            LOG_INF( "Fail LIS2" );
            return( NULL );
        }

        lis2de12_writeb( LIS2DE12_CTRL_REG4, 0x80 );
        lis2de12_readb( LIS2DE12_CTRL_REG4, &d[1] );
        if (d[1] != 0x80)
        {
            LOG_INF( "Fail LIS2" );
            return( NULL );
        }

        //High pass filter enabled
//      lis2de12_writeb(LIS2DE12_CTRL_REG2,0x40);

        // Normal mode + HPF cutoff freq 0.02 Hz @1 Hz ODR + Enable the internal filter
        lis2de12_writeb( LIS2DE12_CTRL_REG2,0xB8 );
        lis2de12_readb( LIS2DE12_CTRL_REG2,&d[2] );
        if ( d[2] != 0xB8 )
        {
            LOG_INF( "Fail LIS2" );
            return( NULL );
        }

        // Enable FIFO operation
        lis2de12_writeb( LIS2DE12_CTRL_REG5, 0x40 );
        lis2de12_readb( LIS2DE12_CTRL_REG5, &d[3] );
        if (d[3] != 0x40)
        {
            LOG_INF( "Fail LIS2" );
            return( NULL );
        }

        // Enable FIFO Mode
        lis2de12_writeb( LIS2DE12_FIFO_CTRL_REG, 0x40 );
        lis2de12_readb( LIS2DE12_FIFO_CTRL_REG, &d[4] );
        if (d[4] != 0x40)
        {
            LOG_INF( "Fail LIS2" );
            return( NULL );
        }

        LOG_DBG( "C1 %x:C4 %x:C2 %x:C5 %x:FIFO %x:",d[0],d[1],d[2],d[3],d[4] );
        k_sleep(K_MSEC(20));

        return( &accelerometer );
    }

}//lis2de12_initialise()

However, when I read the x,y,z data I am getting all zeros.
The function that reads the x,y,z data is shown below,

static int32_t lis2de12_read_fifo(uint8_t add, uint8_t *b)
{
    struct i2c_msg msgs[2];

    /* Send the address to read from */
    msgs[0].buf = &add;
    msgs[0].len = 1U;
    msgs[0].flags = I2C_MSG_WRITE | I2C_MSG_STOP;

    /* Read from device. STOP after this. */
    msgs[1].buf = b;
    msgs[1].len = 6U;
    msgs[1].flags = I2C_MSG_READ | I2C_MSG_STOP;

    return i2c_transfer(accelerometer.handle, &msgs[0], 2, LIS2DE12_I2C_ADD);
}

The above function lis2de12_read_fifo() is called from the function shown below which itself gets called from an executive loop running in a forever loop.

typedef struct accel{
            void        * handle;
            int16_t     x;
            int16_t     y;
            int16_t     z;
            uint32_t    vector;
            uint32_t    oldvector;
            uint8_t     present:1;
            uint8_t     moved:1;
            uint32_t    LastMovementTime;

        } accelerometer_t;

accelerometer_t accelerometer;

boolean_t lis2de12_getxyz(void)
{
    uint8_t     status;
    uint8_t     d[6],i;
    union {
            uint8_t  b[2];
            int16_t  i;
          } iandb;

    accelerometer.vector = accelerometer.oldvector;

    if (accelerometer.present)
    {
        lis2de12_readb( LIS2DE12_STATUS_REG, &status );
        if ( status & ZYX_DATA_READY )
        {
#if 0
            for ( i = 0; i < 6; i++ )
            {
                if ( lis2de12_readb( LIS2DE12_FIFO_READ_START + i, &d[i] ) != 0 )
                {
                    break;
                }
            }
            if ( i == 6 )
#endif //#if 0

            if ( lis2de12_read_fifo( LIS2DE12_FIFO_READ_START, d ) != 0 )
            {
                iandb.b[1] = d[0];
                iandb.b[0] = d[1];
                accelerometer.x = iandb.i;

                iandb.b[1] = d[2];
                iandb.b[0] = d[3];
                accelerometer.y = iandb.i;

                iandb.b[1] = d[4];
                iandb.b[0] = d[5];
                accelerometer.z = iandb.i;

                accelerometer.vector = (uint32_t)accelerometer.x * (uint32_t)accelerometer.x +
                                       (uint32_t)accelerometer.y * (uint32_t)accelerometer.y +
                                       (uint32_t)accelerometer.z * (uint32_t)accelerometer.z;
                
                printf( "[%u s] ", timer_GetOneSecondTime() ); //DBG
                printf( "STATUS_REG = 0x%02x acc_x = 0x%04x acc_y = 0x%04x acc_z = 0x%04x v = %d acc_oldv = %d\n",
                        status,
                        accelerometer.x, accelerometer.y, accelerometer.z,
                        accelerometer.vector,
                        accelerometer.oldvector                             );
            }
        }
        return true;
    }
    else
    {
        return false;
    }

}//lis2de12_getxyz()
 

Here is a sample of the debug output

[14 s] STATUS_REG = 0xff acc_x = 0x0000 acc_y = 0x0000 acc_z = 0x0000 v = 0 acc_oldv = 0
[15 s] STATUS_REG = 0xff acc_x = 0x0000 acc_y = 0x0000 acc_z = 0x0000 v = 0 acc_oldv = 0
[15 s] STATUS_REG = 0xff acc_x = 0x0000 acc_y = 0x0000 acc_z = 0x0000 v = 0 acc_oldv = 0
[15 s] STATUS_REG = 0xff acc_x = 0x0000 acc_y = 0x0000 acc_z = 0x0000 v = 0 acc_oldv = 0
[15 s] STATUS_REG = 0xff acc_x = 0x0000 acc_y = 0x0000 acc_z = 0x0000 v = 0 acc_oldv = 0
[15 s] STATUS_REG = 0xff acc_x = 0x0000 acc_y = 0x0000 acc_z = 0x0000 v = 0 acc_oldv = 0
[15 s] STATUS_REG = 0xff acc_x = 0x0000 acc_y = 0x0000 acc_z = 0x0000 v = 0 acc_oldv = 0

It must be something to do with the way I am reading the FIFO content because when I read individual registers content all seems to be OK.
Please advise.
Kind regards
Mohamed
Parents
  • Hello,

    I'll take a look at this tomorrow.

    Best regards,

    Simon

  • Thank you Simon.

    I am looking forward to read your findings.

    Kind regards

    Mohamed

  • Thank you Simon.

    I tried your suggestion to make the struct declaration static but it did not make any difference.
    Hooking up a logic analyser to SDA and SCL lines was going to be my next move but I was hoping you may be able to find what could be wrong in my code without resorting to a logic analyser. I am not suspecting the hardware, are you?
    The reason I am saying this is because I can read the control and status registers content without any problem. If there was something wrong with the hardware setup it would have affected them too.
    Anyway, I am working from home today and the logic analyser is in the office. So, I will do it on Monday and will give you some feedback.
    Kind regards
    Mohamed
  • Hey, did you capture a trace?

    I'll take a closer look at this tomorrow.

    What happens if you try to read the data in the same way it's done in the lis2ds12 driver, by using i2c_burst_read()?

    https://github.com/nrfconnect/sdk-zephyr/blob/v2.6.99-ncs1/drivers/sensor/lis2ds12/lis2ds12_i2c.c#L28-L29

  • Good Morning Simon,
    Thank you for sharing the link about i2c_burst_read().
    I did not have to use the logic analyser because when I disabled the sensor internal filter (cleared FDS bit) I could read the sensor data.
    lis2de12_writeb( LIS2DE12_CTRL_REG2,0xB8 );
    changed to
    lis2de12_writeb( LIS2DE12_CTRL_REG2,0x80 );
    However, I still cannot read the content of the FIFO. I tried both FIFO and stream modes and neither worked. When in stream mode the FIFO seemed to always be empty (EMPTY bit always set).
    I have not had a chance to try the i2c_burst_read() but I will do tomorrow.
    ------------------
    Updated post
    ------------------
    I have now tried to read the fifo using i2c_burst_read() but I am still finding that when I read register  LIS2DE12_FIFO_SRC_REG (address 0x2F) I get 0x20 meaning the fifo is always empty. I am enabling fifo (FIFO_EN) and selecting stream mode by writing 0x80 to register LIS2DE12_FIFO_CTRL_REG.
    Below is the code used to read the content of the fifo.
    static int32_t lis2de12_read_fifo(uint8_t add, uint8_t *data)
    {
        return i2c_burst_read( accelerometer.handle,    // i - Pointer to the device structure for an I2C controller
                               LIS2DE12_I2C_ADD,        // i - Address of the I2C device to read from
                               add,                     // i - Internal address from which the data is read
                               data,                    // o - Buffer to read the data into
                               6                    );  // i - Number of bytes to read
    }
    
    
    boolean_t lis2de12_getxyz_fifo(void)
    {
        boolean_t   result = false;
        uint8_t     fifo_status;
        uint8_t     d[6],i;
        union {
                uint8_t  b[2];
                int16_t  i;
        } iandb;
    
        accelerometer.vector = accelerometer.oldvector;
    
        if (accelerometer.present)
        {
            lis2de12_readb( LIS2DE12_FIFO_SRC_REG, &fifo_status );
            if ( fifo_status & 0x1f )
            {
                if ( lis2de12_read_fifo( LIS2DE12_FIFO_READ_START | 0x80, d ) == 0 )
                {
                    iandb.b[1] = d[0];
                    iandb.b[0] = d[1];
                    accelerometer.x = iandb.i;
    
                    iandb.b[1] = d[2];
                    iandb.b[0] = d[3];
                    accelerometer.y = iandb.i;
    
                    iandb.b[1] = d[4];
                    iandb.b[0] = d[5];
                    accelerometer.z = iandb.i;
    
                    accelerometer.vector = (uint32_t)accelerometer.x * (uint32_t)accelerometer.x +
                                           (uint32_t)accelerometer.y * (uint32_t)accelerometer.y +
                                           (uint32_t)accelerometer.z * (uint32_t)accelerometer.z;
                    printf( "[%u s] ", timer_GetOneSecondTime() ); //DBG
                    printf( "STATUS_REG = 0x%02x acc_x = 0x%04x acc_y = 0x%04x acc_z = 0x%04x v = %d acc_oldv = %d\n",
                            fifo_status,
                            accelerometer.x, accelerometer.y, accelerometer.z,
                            accelerometer.vector,
                            accelerometer.oldvector                             );
                    
                    result = true;
                }
            }
        }
    
        return result;
    
    }//lis2de12_getxyz_fifo()
    
    -----------------------
    If I don't bother to read and check the content of the FIFO source register (LIS2DE12_FIFO_SRC_REG) for the existence of data before reading then I can read the sensor data successfully. The two commented out lines are shown below.
    //      lis2de12_readb( LIS2DE12_FIFO_SRC_REG, &fifo_status );
    //      if ( fifo_status & 0x1f )
    
    The data read is shown below, ignore the STATUS_REG values because it is not being read.
    [16 s] STATUS_REG = 0x05 acc_x = 0x00fd acc_y = 0x00ff acc_z = 0x0042 v = 133390 acc_oldv = 133390
    [17 s] STATUS_REG = 0x00 acc_x = 0x00fd acc_y = 0x00ff acc_z = 0x0042 v = 133390 acc_oldv = 133390
    [18 s] STATUS_REG = 0x00 acc_x = 0x00f5 acc_y = 0x0006 acc_z = 0x00c5 v = 98870 acc_oldv = 133390
    [19 s] STATUS_REG = 0x00 acc_x = 0x00f9 acc_y = 0x00f8 acc_z = 0x0042 v = 127861 acc_oldv = 98870
    [20 s] STATUS_REG = 0x00 acc_x = 0x00bf acc_y = 0x00f2 acc_z = 0x00fa v = 157545 acc_oldv = 127861
    [21 s] STATUS_REG = 0x00 acc_x = 0x00c1 acc_y = 0x00f3 acc_z = 0x00f9 v = 158299 acc_oldv = 157545
    [22 s] STATUS_REG = 0x05 acc_x = 0x0006 acc_y = 0x00bc acc_z = 0x0006 v = 35416 acc_oldv = 158299
    [23 s] STATUS_REG = 0x00 acc_x = 0x000a acc_y = 0x00bc acc_z = 0x0000 v = 35444 acc_oldv = 35416
    [24 s] STATUS_REG = 0x00 acc_x = 0x000e acc_y = 0x00bd acc_z = 0x0002 v = 35921 acc_oldv = 35444
    [25 s] STATUS_REG = 0x00 acc_x = 0x0010 acc_y = 0x00be acc_z = 0x0001 v = 36357 acc_oldv = 35921
    [26 s] STATUS_REG = 0x05 acc_x = 0x00ff   acc_y = 0x0040 acc_z = 0x00fd v = 133130 acc_oldv = 36357
    [27 s] STATUS_REG = 0x00 acc_x = 0x0003 acc_y = 0x0040 acc_z = 0x0003 v = 4114 acc_oldv = 133130
    [28 s] STATUS_REG = 0x00 acc_x = 0x0002 acc_y = 0x00bc acc_z = 0x0008 v = 35412 acc_oldv = 4114
    [29 s] STATUS_REG = 0x00 acc_x = 0x0000 acc_y = 0x00bc acc_z = 0x000b v = 35465 acc_oldv = 35412
    [30 s] STATUS_REG = 0x05 acc_x = 0x0000 acc_y = 0x00bc acc_z = 0x000b v = 35465 acc_oldv = 35465
    [30 s] STATUS_REG = 0x00 acc_x = 0x0001 acc_y = 0x00bd acc_z = 0x000b v = 35843 acc_oldv = 35465
    [31 s] STATUS_REG = 0x05 acc_x = 0x00fa  acc_y = 0x0001 acc_z = 0x003f v = 66470 acc_oldv = 35843
    [32 s] STATUS_REG = 0x00 acc_x = 0x00fa  acc_y = 0x0000 acc_z = 0x0041 v = 66725 acc_oldv = 66470
    Kind regards
    Mohamed

  • Hi Simon,

    Any update on my question about why I am always getting FIFO EMPTY bit set when I read the FIFO status register LIS2DE12_FIFO_SRC_REG?

    See the notes I added to this ticket yesterday.

    Thank you

    Kind regards

    Mohamed

Reply Children
  • I don't have any knowledge about the LIS2DE12, so I'm not sure why this happens:

    Learner said:
    Any update on my question about why I am always getting FIFO EMPTY bit set when I read the FIFO status register LIS2DE12_FIFO_SRC_REG?

    Maybe a logic trace would be useful, to figure out if the issue is on the Nordic side or the LIS2DE12

    I will take a deep dive into the LIS2DE12 datasheet on Monday and see if I can get to the bottom of it.

  • Good Afternoon Simon,

    I just had this thought, correct me if I am wrong.

    I thought the reason the EMPTY bit in the FIFO register FIFO_SRC_REG is always set is because STREAM mode does not use the FIFO. Instead I must use the status register STATUS_REG (27h) and poll one of the data ready bits e.g. ZYXDA. This works but I really must use the FIFO in the following way:

    1- Only Read sensor data if FIFO is not EMPTY

    2- Read FSS bits [0:4] to determine the number of samples stored in the FIFO

    3- Read the data from the FIFO

    Unfortunately, I cannot get past step 1 because EMPTY bit is always zero. Note, I cannot use INT1/2 interrupts, so I am polling the EMPTY bit instead.

    Please check this with your design team.

    Kind regards

    Mohamed

  • Hi Simon,
    Have you had a chance to look at the FIFO EMPTY bit always set problem I reported last week?
    Kind regards
    Mohamed
Related