MMA8451Q not reading FIFO correctly... what am I doing wrong here?

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 
已解决

MMA8451Q not reading FIFO correctly... what am I doing wrong here?

跳至解决方案
2,177 次查看
peteDDD
Contributor II

I am working with the FIFO on the MMA8451Q and have spent days with the data sheet and FIFO app note (AN4073) and the Motion app note (AN4070).  My goal is to use the FIFO in trigger mode, triggering on motion in excess of 1g on either x-axis or y-axis, with the FIFO capturing two events pre-trigger and 30 events post trigger.  I have the data_rate at 100hz, Lnoise off, F_Read off (using 14-bit data), range=8g.

I have first implemented the Power Minimization Example: Data Logger Collecting example in section 5.1 of AN4073 to make sure I could sort out the basics of the FIFO first.

While I have both that example, and the motion trigger code working, in both cases the data coming back from the FIFO is bit odd.   I will explain what I mean by that.

In either case, the first 21 events returned give correct values (when the sensor is not moving, the g values are 0 in the x and y axes).  But the values for the remaining 11 values are all over the place.  If there is no motion, the values can be as high as 2g and with a triggering motion (in the latter example), these values returned go all the way up to 8g (the actual movement is no where near that high).

The best I can figure is that I am not going about reading the FIFO correctly.  I am using an ESP32-S3 which clocks I2C at 400Khz by default and have adapted the Adafruit MMA8451 library as a starting point (it does not have anything in the library with regards to using the FIFO).

Here is a minimal code sample of how I am reading the FIFO: 

#define use14bit true
#define MMA8451_FIFO_REG 0x01
#uint8_ FIFObuffer[192];
 
bool PD_MMA8451::getFIFO(bool use14bit)
{
  uint8_t targetRegister[1] = {MMA8451_FIFO_REG};
  return (i2c_dev->write_then_read(targetRegister, 1, FIFObuffer, use14bit ? 192 : 96));
}
 
This code should first write the FIFO buffer register address to the chip and then read the first 192 bytes from that buffer.
 
I can then print out the FIFO, with event number in the first column and see the following (again, this is with no motion and basically using the AN4073 section 5.1 example converted to ESP32 code):

0 255 248 0 0 255 192
1 0 0 0 16 255 212
2 255 252 255 248 255 208
3 255 240 255 244 255 244
4 0 16 255 228 0 4
5 255 240 255 240 255 216
6 255 248 255 240 0 0
7 255 252 0 20 0 40
8 0 4 0 4 255 236
9 255 252 255 252 0 12
10 0 24 0 0 255 248
11 0 12 255 240 0 64
12 255 228 255 252 255 252
13 255 248 0 12 255 240
14 0 0 0 40 255 228
15 255 252 255 236 255 208
16 255 236 255 244 0 40
17 0 28 0 20 0 20
18 0 16 0 4 255 216
19 0 8 255 224 0 36
20 255 244 0 20 255 208
21 0 4 14 255 232 0
22 8 0 72 255 252 255
23 228 255 232 255 252 0
24 32 0 8 255 200 255
25 224 0 32 0 12 255
26 212 255 244 255 252 255
27 248 0 16 0 0 255
28 240 0 44 0 12 0
29 16 255 200 255 220 0
30 8 0 44 255 220 255
31 248 0 16 255 228 0

If I then convert this to g values for X ,Y, and Z,  I see the following for that same data:

0 -0.00, 0.00, -0.01
1 0.00, 0.00, -0.01
2 -0.00, -0.00, -0.01
3 -0.00, -0.00, -0.00
4 0.00, -0.00, 0.00
5 -0.00, -0.00, -0.00
6 -0.00, -0.00, 0.00
7 -0.00, 0.00, 0.00
8 0.00, 0.00, -0.00
9 -0.00, -0.00, 0.00
10 0.00, 0.00, -0.00
11 0.00, -0.00, 0.01
12 -0.00, -0.00, -0.00
13 -0.00, 0.00, -0.00
14 0.00, 0.00, -0.00
15 -0.00, -0.00, -0.01
16 -0.00, -0.00, 0.00
17 0.00, 0.00, 0.00
18 0.00, 0.00, -0.00
19 0.00, -0.00, 0.00
20 -0.00, 0.00, -0.01
21 0.00, 0.47, -0.75
22 0.25, 2.28, -0.09
23 -0.84, -0.72, -0.12
24 1.00, 0.28, -1.72
25 -1.00, 1.00, 0.41
26 -1.34, -0.34, -0.09
27 -0.25, 0.50, 0.03
28 -0.50, 1.38, 0.38
29 0.53, -1.72, -1.12
30 0.25, 1.41, -1.09
31 -0.25, 0.53, -0.88

Now here, we see zero g on all three axes (whereas we should see ~1g on the z-axis) until we get to the 21st event and then the data goes all over the place.

I can only conclude that the method I am using to read the FIFO is incorrect.  Can anyone see the error in my method and share some pointers with me?

Thank you!

 

0 项奖励
回复
1 解答
1,928 次查看
peteDDD
Contributor II

The underlying problem here is that the ESP32 I2C buffer size is 128 bytes.  It needs to be at lease 192 bytes to accommodate the full buffer when using 14-bit data.

Placing

build_flags =
  -DI2C_BUFFER_LENGTH=255

in my platformio.ini does the trick of setting the buffer to a larger (logical) size.

在原帖中查看解决方案

0 项奖励
回复
7 回复数
1,929 次查看
peteDDD
Contributor II

The underlying problem here is that the ESP32 I2C buffer size is 128 bytes.  It needs to be at lease 192 bytes to accommodate the full buffer when using 14-bit data.

Placing

build_flags =
  -DI2C_BUFFER_LENGTH=255

in my platformio.ini does the trick of setting the buffer to a larger (logical) size.

0 项奖励
回复
2,076 次查看
peteDDD
Contributor II

@ JozefKozon Thank you again.   I have recreated that code and at this point am convinced that the problem is with my burst read.    Here is the data I am collecting using the register setting that your colleague suggested in his message.  The data below is the raw data coming from the FIFO read.  The sensor is motionless during this.

Notice below the value "11" in row 21 of the raw data (which I have highlighted red, bold, underlined).  This is an extra byte which then creates an offset in the whole data set after that point.  What could be causing that?
 
Elasped Time 4604 microseconds
0 255 184 255 192 16 64
1 255 184 255 196 16 52
2 255 188 255 200 16 44
3 255 188 255 196 16 36
4 255 180 255 196 16 52
5 255 188 255 192 16 52
6 255 188 255 188 16 52
7 255 184 255 180 16 56
8 255 184 255 180 16 52
9 255 184 255 188 16 64
10 255 180 255 180 16 44
11 255 184 255 184 16 48
12 255 184 255 180 16 52
13 255 180 255 188 16 48
14 255 180 255 192 16 52
15 255 184 255 196 16 44
16 255 184 255 200 16 64
17 255 184 255 196 16 60
18 255 172 255 204 16 44
19 255 184 255 196 16 36
20 255 188 255 200 16 40
21 255 184 11 255 184 255
22 188 16 48 255 184 255
23 184 16 52 255 184 255
24 184 16 48 255 184 255
25 184 16 64 255 176 255
26 196 16 68 255 176 255
27 184 16 72 255 180 255
28 196 16 48 255 176 255
29 188 16 56 255 180 255
30 192 16 56 255 180 255
31 200 16 60 128 128 128
 
I have tried various I2C frequencies all the way down to 50KHz and that changes nothing.
I have also tried this with and without pull-up resistors and that changes nothing.
 
I am only left to believe that the problem is in the I2C burst read on my ESP32-S3 or some timeout within the MMA8451Q creating an interrupt on the I2C line.  Your thoughts?
2,152 次查看
JozefKozon
NXP TechSupport
NXP TechSupport

Dear Pete, 

please try to calibrate your device according to the AN4069

With Best Regards,

Jozef

0 项奖励
回复
2,134 次查看
peteDDD
Contributor II

@JozefKozon, thank you for your kind and prompt response.

I do not believe that calibration is the issue and I will tell you why...  If I just capture x, y, and z values and convert them to g values in a tight loop, not using the FIFO, etc., all the values make perfect sense.  When still, the z values are very close to 1.00g and the x, y close to 0.00g.  When I move the sensor, the acceleration values all make sense.

This is why I believe the problem is in the way I am transferring the FIFO buffer to the processor.

Thinking in terms of esp32 processors, do you see an issue with my method of transferring the FIFO data from its register (0x01) to the array FIFObuffer[192]?

#define use14bit true
#define MMA8451_FIFO_REG 0x01
#uint8_t FIFObuffer[192];
 
bool PD_MMA8451::getFIFO(bool use14bit)
{
  uint8_t targetRegister[1= {MMA8451_FIFO_REG};
  return (i2c_dev->write_then_read(targetRegister1FIFObufferuse14bit ? 192 : 96));
}
2,095 次查看
JozefKozon
NXP TechSupport
NXP TechSupport

Dear Pete,

my colleague Tomas has created an FIFO example code for FXLS8471Q. Please check this link. You can use the code with slight adjustments in the MMA8451Q. 

For the SW, the MMA8451Q and FXLS8471Q are compatible, except for A_VECM and A_FFMT registers. So if the customer does not use the vector-magnitude function and independent threshold values for freefall/motion detection, there is no need to change a firmware. 

There is an AN4073 describing FIFO in the MMA8451Q. Please check it here

With Best Regards,

Jozef

0 项奖励
回复
2,050 次查看
peteDDD
Contributor II

@ JozefKozon Thank you again.   I have recreated that code and at this point am convinced that the problem is with my burst read.    Here is the data I am collecting using the register setting that your colleague suggested in his message.  The first column is the sample number, the next three columns are the g values for x, y, and z respectively.   The sensor is motionless during this.

 
As you can see here, the first 21 values (index 0 through 20) read correctly and then the values after that make no sense.
 
I have tried various I2C frequencies all the way down to 50KHz and that changes nothing.
I have also tried this with and without pull-up resistors and that changes nothing.
 
Here is the raw data...  You can see there is an offset in the data at the 21st event.
 
 
0       0.03,   -0.02,  1.01
1       0.03,   -0.02,  1.01
2       0.03,   -0.02,  1.01
3       0.03,   -0.02,  1.01
4       0.03,   -0.02,  1.01
5       0.03,   -0.02,  1.01
6       0.03,   -0.02,  1.01
7       0.03,   -0.02,  1.01
8       0.03,   -0.02,  1.01
9       0.03,   -0.03,  1.01
10      0.03,   -0.03,  1.01
11      0.03,   -0.03,  1.01
12      0.03,   -0.03,  1.01
13      0.03,   -0.03,  1.01
14      0.03,   -0.03,  1.01
15      0.03,   -0.03,  1.01
16      0.03,   -0.03,  1.01
17      0.03,   -0.02,  1.01
18      0.03,   -0.02,  1.01
19      0.03,   -0.02,  1.01
20      0.03,   -0.03,  1.01
21      0.03,   0.81,   7.56
22      -6.50,  3.50,   -7.44
23      -6.25,  2.00,   -7.94
24      -6.50,  3.25,   -7.44
25      -6.50,  3.00,   -7.94
26      -6.00,  2.75,   -7.94
27      -6.00,  2.25,   7.56
28      -6.75,  2.50,   7.81
29      -6.50,  3.00,   -7.69
30      -6.50,  2.50,   7.06
31      -6.25,  2.75,   7.81

I am only left to believe that the problem is in the I2C burst read on my ESP32-S3
 
So out comes the o-scope with I2C protocol decoding...
1- The 192 byte read is interrupted right before the "11" (decimal) value which we saw in line 21 of the raw data mentioned earlier.
SDS00001.jpg
 
2- Switching the output to hexidecimal, we can see line 5 of the decoding writes the register address 0x01 which is the lead byte of the FIFO buffer. The 192 byte read then begins. (Incidentally, lines 3 and 4 are the resetting of the interrupt flag of the MMA8451Q and the results do not change if I move this reset to after the FIFO read).
This image shows the line 6 full decoding of the FIFO data up to the point of the break in the clock signal.
 
SDS00001a.jpg
 
3- This next screen capture shows the line 7 decoding of the FIFO data after the break in the clock signal:
SDS00003.jpg
 
4- In the final screen capture, below, I am zooming in on the clock (SCL) (yellow) and data (SDA) (purple) signals around the "glitch". The top pair of traces indicates the zoom window and the bottom pair of traces is the zoomed in data. What we see here is:
- a 8u-sec low clock (green oval) followed by 0x10 then
- a 91u-sec high clock and then
- the 0x0B (11 decimal) (blue oval) followed by
- a skipped click cycle and then
- two bytes of data that make no sense where they are (there appears to be four bytes from the the FIFO missing here or an offset in the pattern of that many bytes) and then
- a resumption of the data pattern which appears to be correct data
SDS00005.jpg
 
Does all this give us an indication of why we are seeing this break in the 192 byte data stream?
 
(and again, for the record, this is using the set-up suggested by your colleague.  )
[CODE]
writeRegister8(MMA8451_REG_CTRL_REG1, 0x00); //Standby
writeRegister8(MMA8451_F_SETUP, (MMA8451_FIFI_MODE_FILL_BUFFER | 32)); //FIFO Set to Fill Mode, 32 samples
writeRegister8(MMA8451_REG_CTRL_REG4, MMA8451_INT_EN_FIFO); //Enable FIFO interrupt, push-pull, active low
writeRegister8(MMA8451_REG_CTRL_REG5, MMA8451_INT_CFG_FIFO_INT1); //Set the interrupt to route to INT1
writeRegister8(MMA8451_REG_CTRL_REG1, ( MMA8451_DATARATE_100_HZ | MMA8451_ACTIVE ));  // period = 10 ms
[/CODE]
 
Thank you again for your kind assistance with this.
 
2,045 次查看
peteDDD
Contributor II

Sorry... there is a part missing from above and the ability to edit the post timed out...

 

Here is the raw data (in decimal)...  You can see there is an offset in the data at the 21st event. (highlighted in bold and underlined)  The first value of each row is a row number for reference.
 

0 0 148 1 100 16 28
1 0 148 1 96 16 44
2 0 152 1 100 16 24
3 0 144 1 96 16 40
4 0 144 1 108 16 44
5 0 144 1 96 16 40
6 0 148 1 100 16 28
7 0 152 1 100 16 40
8 0 148 1 108 16 52
9 0 148 1 104 16 48
10 0 140 1 108 16 32
11 0 144 1 100 16 28
12 0 144 1 108 16 44
13 0 148 1 100 16 32
14 0 152 1 104 16 44
15 0 140 1 92 16 32
16 0 148 1 96 16 36
17 0 140 1 104 16 32
18 0 144 1 96 16 32
19 0 144 1 100 16 32
20 0 140 1 100 16 36
21 0 144 11 0 152 1
22 100 16 28 0 156 1
23 104 16 40 0 152 1
24 104 16 28 0 148 1
25 104 16 44 0 152 1
26 100 16 32 0 152 1
27 96 16 24 0 144 1
28 104 16 44 0 152 1
29 104 16 32 0 144 1
30 104 16 40 0 152 1
31 104 16 28 128 128 128

This translates to the following g values.

0 0.04, 0.09, 1.01
1 0.04, 0.09, 1.01
2 0.04, 0.09, 1.01
3 0.04, 0.09, 1.01
4 0.04, 0.09, 1.01
5 0.04, 0.09, 1.01
6 0.04, 0.09, 1.01
7 0.04, 0.09, 1.01
8 0.04, 0.09, 1.01
9 0.04, 0.09, 1.01
10 0.03, 0.09, 1.01
11 0.04, 0.09, 1.01
12 0.04, 0.09, 1.01
13 0.04, 0.09, 1.01
14 0.04, 0.09, 1.01
15 0.03, 0.08, 1.01
16 0.04, 0.09, 1.01
17 0.03, 0.09, 1.01
18 0.04, 0.09, 1.01
19 0.04, 0.09, 1.01
20 0.03, 0.09, 1.01
21 0.04, 0.69, -6.50
22 6.25, 1.75, -6.25
23 6.50, 2.50, -6.50
24 6.50, 1.75, -6.75
25 6.50, 2.75, -6.50
26 6.25, 2.00, -6.50
27 6.00, 1.50, -7.00
28 6.50, 2.75, -6.50
29 6.50, 2.00, -7.00
30 6.50, 2.50, -6.50
31 6.50, 1.78, -7.97