Jump to content


Photo
- - - - -

FIFO Overflow

yaw pitch roll Arduino FIFO overflow

Best Answer Jeff Rowberg , 17 August 2013 - 06:42 PM

Hi Vigil,

 

Other than overclocking (not typically a good idea) or switching to a faster CPU (e.g. Arduino Due), one thing you can do to help with I2C transactions is to change the I2C clock rate from 100kHz (default) to 400kHz (assuming you are running at 16MHz, otherwise it will be 200kHz). This is done with the following direct register write after you call "Wire.begin()":

TWBR = 12; // set 400kHz mode @ 16MHz CPU or 200kHz mode @ 8MHz CPU

Alternatively, you can change the DMP output rate by modifying the last bye of the last DMP configuration command on line 261 of the MPU6050_6Axis_MotionApps_20.h file:

 

https://github.com/j...onApps20.h#L261

    0x02,   0x16,   0x02,   0x00, 0x01                // D_0_22 inv_set_fifo_rate

    // This very last 0x01 WAS a 0x09, which drops the FIFO rate down to 20 Hz. 0x07 is 25 Hz,
    // 0x01 is 100Hz. Going faster than 100Hz (0x00=200Hz) tends to result in very noisy data.
    // DMP output frequency is calculated easily using this equation: (200Hz / (1 + value))

    // It is important to make sure the host processor can keep up with reading and processing
    // the FIFO output at the desired rate. Handling FIFO overflow cleanly is also a good idea.

You do have to read all of the data that goes into the FIFO in order to prevent an overflow, but you can slow down the data that goes into the FIFO easily enough.

Go to the full post


  • Please log in to reply
4 replies to this topic

#1 Vigil

Vigil

    Newbie

  • Members
  • Pip
  • 2 posts

Posted 22 July 2013 - 05:09 PM

Hello everyone!

 

I am pretty inexperienced when it comes to computer programming, but I am using the program Jeff posted to use the yaw, pitch, and roll values (I really only need the yaw, though) in a feedback system for a UAV. I am using an Arduino Uno to run the gyroscope, and the program works fine by itself. My issue results from me putting the program on a timer so that it only reads the value every, say, 100 ms. Then FIFO overflow then gets triggered (which makes sense because the values are going in faster than they go out.) Is there any way to bypass this? I noticed one of the past iterations of the program read the values directly instead of from the FIFO buffer, but I didn't understand that version of the program, and I also don't think it had a "ypr" option. Is there an easy way to change the programming, or perhaps a better way to do it?

 

Thanks for any help you can give!



#2 Vigil

Vigil

    Newbie

  • Members
  • Pip
  • 2 posts

Posted 31 July 2013 - 05:02 PM

Hi,

 

So I did a little more messing around with my program, and I got it to work well. I decided not to use the interrupts because they were actually messing up the rest of my program. However, it does work. The only problem I have is that it runs a little slow. Another part of the program controls an oscillating servomotor and, right now, it won't really run faster that about 1 hz. I believe is just a processing issue because the program is so big. The main part of the issue is that, as I have the program right now, the gyroscope is taking data as fast as possible is the background and I only sample it even 10 ms or so. I guess my question is there any way around that? I feel like the FIFO buffer is still kind of an "issue"--the time it takes to read into that or something. But the program does have to have the 42 byte packet, right? Or can that be changed? Any help anyone could give even just regarding ways to make the Arduino faster would be greatly appreciated. Thanks!



#3 Jeff Rowberg

Jeff Rowberg

    Administrator

  • Administrators
  • 57 posts
  • LocationRoanoke, VA

Posted 17 August 2013 - 06:42 PM   Best Answer

Hi Vigil,

 

Other than overclocking (not typically a good idea) or switching to a faster CPU (e.g. Arduino Due), one thing you can do to help with I2C transactions is to change the I2C clock rate from 100kHz (default) to 400kHz (assuming you are running at 16MHz, otherwise it will be 200kHz). This is done with the following direct register write after you call "Wire.begin()":

TWBR = 12; // set 400kHz mode @ 16MHz CPU or 200kHz mode @ 8MHz CPU

Alternatively, you can change the DMP output rate by modifying the last bye of the last DMP configuration command on line 261 of the MPU6050_6Axis_MotionApps_20.h file:

 

https://github.com/j...onApps20.h#L261

    0x02,   0x16,   0x02,   0x00, 0x01                // D_0_22 inv_set_fifo_rate

    // This very last 0x01 WAS a 0x09, which drops the FIFO rate down to 20 Hz. 0x07 is 25 Hz,
    // 0x01 is 100Hz. Going faster than 100Hz (0x00=200Hz) tends to result in very noisy data.
    // DMP output frequency is calculated easily using this equation: (200Hz / (1 + value))

    // It is important to make sure the host processor can keep up with reading and processing
    // the FIFO output at the desired rate. Handling FIFO overflow cleanly is also a good idea.

You do have to read all of the data that goes into the FIFO in order to prevent an overflow, but you can slow down the data that goes into the FIFO easily enough.



#4 Electrumpet

Electrumpet

    Newbie

  • Members
  • Pip
  • 3 posts

Posted 03 November 2013 - 09:18 PM

Dear Jeff,

 

Thanks for all the good work you did on this sensor. Without your work it would probably be worthless to me.

 

I am posting in this forum although I have a MPU-9150 but this topic seems most fitting to my question.

 

By using the faster I2C clock I am now sampling at 11ms per measurement (the 10 ms is in between measurements tells my osciloscoop). I made adjustments in the code as suggested changing the line:

 

02, 0x16, 0x02, 0x00, 0x01 // D_0_22 inv_set_fifo_rate

 

into

 

02, 0x16, 0x02, 0x00, 0x00 // D_0_22 inv_set_fifo_rate

 

 

I changed it in both the MPU6050_6Axis_MotionApps20.h and the MPU6050_9Axis_MotionApps41.h but I don't see the sample rate go down to 6 ms or change at all. Maybe it is set to 100 Hz somewhere else when I initialize the sensor? This is my arduino code:

 

// I2C device class (I2Cdev) demonstration Arduino sketch for MPU9150
// 1/4/2013 original by Jeff Rowberg <jeff@rowberg.net> at https://github.com/jrowberg/i2cdevlib
//          modified by Aaron Weiss <aaron@sparkfun.com>
//
// Changelog:
//     2011-10-07 - initial release
//     2013-1-4 - added raw magnetometer output


/* ============================================
 I2Cdev device library code is placed under the MIT license


 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:


 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.


 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 ===============================================
 */


// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
// is used in I2Cdev.h
#include "Wire.h"


// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files
// for both classes must be in the include path of your project
#include "I2Cdev.h"
#include "AK8975.h"
#include "MPU6050.h"


// class default I2C address is 0x68
// specific I2C addresses may be passed as a parameter here
// AD0 low = 0x68 (default for InvenSense evaluation board)
// AD0 high = 0x69
AK8975 mag(0x0C);
MPU6050 accelgyro; // address = 0x68, the default, on MPU6050 EVB
MPU6050 mpu;


int16_t ax, ay, az;
int16_t gx, gy, gz;
int16_t mx, my, mz;


int16_t mpuData [9] = { 
  0, 0, 0, 0, 0, 0, 0, 0, 0 };
byte mpuDataSend [21] = { 
  127, 128, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
byte metingLSB = 0;
byte metingMSB = 0;
uint8_t mpuIntStatus;


#define LED_PIN 11 // teensy ledpin
bool blinkState = false;


void setup() {
  // join I2C bus (I2Cdev library doesn't do this automatically)
  Wire.begin();
  TWBR = 12; // set 400kHz mode @ 16MHz CPU or 200kHz mode @ 8MHz CPU


  // initialize serial communication
  // (38400 chosen because it works as well at 8MHz as it does at 16MHz, but
  // it's really up to you depending on your project)
  Serial.begin(115200);


  // initialize device
  Serial.println("Initializing I2C devices...");
  accelgyro.initialize();
  accelgyro.setI2CBypassEnabled(true);
  mag.initialize();


  // verify connection
  Serial.println("Testing device connections...");
  Serial.println(mag.testConnection() ? "AK8975 connection successful" : "AK8975 connection failed");


  // configure Arduino LED for
  pinMode(LED_PIN, OUTPUT);
}


void loop() {
  // read raw accel/gyro measurements from device
    accelgyro.getMotion6(&mpuData[0], &mpuData[1], &mpuData[2], &mpuData[3], &mpuData[4], &mpuData[5]);


    // read raw heading measurements from device
    mag.getHeading(&mpuData[6], &mpuData[7], &mpuData[8]);




    for (byte i = 0; i <= 8; i++){
      metingMSB = mpuData[i] >> 8;
      metingLSB = mpuData[i] & 255;
      mpuDataSend[3 + (i << 1)] = metingMSB;
      mpuDataSend[4 + (i << 1)] = metingLSB;
    }
      Serial.write (mpuDataSend, 21);


      // blink LED to indicate activity
      blinkState = !blinkState;
      digitalWrite(LED_PIN, blinkState);
}

 

I am looking for this high sample rate because of using it in a musical instrument. A latency under 10 ms is preferable.

 

I hope someone (Jeff) can help me.

 

Best, Hans.



#5 Jeff Rowberg

Jeff Rowberg

    Administrator

  • Administrators
  • 57 posts
  • LocationRoanoke, VA

Posted 25 November 2013 - 02:42 AM

Hi Hans,

 

I suspect the Serial.write() command is slowing you down. Can you double or quadruple the baud rate, or temporarily remove it and check the actual data capture rate by toggling a GPIO or something like that? The motion sensor should be able to read at 200Hz, but the Arduino itself or serial transfer might be the bottleneck.

 

One other note is that I have heard that the 200Hz output rate is rather noisy compared to the 100Hz or lower rates.







Also tagged with one or more of these keywords: yaw, pitch, roll, Arduino, FIFO, overflow

0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users