Multiple Acceleration output from 'AccelGyro' code

Hello all,

I am new to Arduino and to this forum so I hope you will forgive me if I am not up to speed with the correct way of doing things.

I have downloaded the AccelGyro code on to my Arduino Mega 2560, it compiled ok but when I ran the Serial Monitor I saw that for every line representing the acceleration and Gyroscope readings from my MPU9150 chip there was a further two duplication (three lines of the same readings).

I am not sure if I have set up the Arduino incorrectly or if there is something missing from the code that I need to include because I am using the Mega 2560. See below a section of the Serial Monitor output.

Initializing I2C devices…
Testing device connections…
MPU6050 connection successful
a/g: 76 396 16812 -27 -63 196
a/g: -312 424 16728 188 263 160
a/g: -312 424 16728 188 263 160
a/g: -312 424 16728 188 263 160
a/g: 8 488 16732 -76 -87 218
a/g: 8 488 16732 -76 -87 218
a/g: 8 488 16732 -76 -87 218
a/g: -20 324 16688 -11 -29 188
a/g: -20 324 16688 -11 -29 188
a/g: -20 324 16688 -11 -29 188
a/g: -116 336 16904 -66 -54 212
a/g: -116 336 16904 -66 -54 212
a/g: -116 336 16904 -66 -54 212
a/g: 48 456 16924 -49 -71 191
a/g: 48 456 16924 -49 -71 191
a/g: 48 456 16924 -49 -71 191
a/g: -76 416 16804 -57 -75 170
a/g: -76 416 16804 -57 -75 170
a/g: -76 416 16804 -57 -75 170
a/g: -64 376 16736 -180 -264 198
a/g: -64 376 16736 -180 -264 198
a/g: -64 376 16736 -180 -264 198
a/g: -28 420 16912 -93 -180 189
a/g: -28 420 16912 -93 -180 189
a/g: -28 420 16912 -93 -180 189

Does anybody know why this duplication is occuring? Your help will be much appreciated.

AccelGyro.ino (5.99 KB)

I'm only guessing here, but maybe your gyro/accel doesn't have any new values since you last called the getmotion6 function. You'r loop doesn't do much, so is probably running quite quickly.

As a quick test, put a delay(100) at the bottom of your loop and see if the repeats go away.

tammytam:
I’m only guessing here, but maybe your gyro/accel doesn’t have any new values since you last called the getmotion6 function. You’r loop doesn’t do much, so is probably running quite quickly.

As a quick test, put a delay(100) at the bottom of your loop and see if the repeats go away.

tammytam:
I’m only guessing here, but maybe your gyro/accel doesn’t have any new values since you last called the getmotion6 function. You’r loop doesn’t do much, so is probably running quite quickly.

As a quick test, put a delay(100) at the bottom of your loop and see if the repeats go away.

tammytam:
I’m only guessing here, but maybe your gyro/accel doesn’t have any new values since you last called the getmotion6 function. You’r loop doesn’t do much, so is probably running quite quickly.

As a quick test, put a delay(100) at the bottom of your loop and see if the repeats go away.

Thanks TammyTam the delay seemed to work fine.

Excellent. Now if there is no function call to return whether a value is ready, I would instead remove that delay and set up a timer that polls the gyro at set intervals. This stops your program blocking when you need to do other stuff.

OK, I have GPS on my Arduino so I could try using the time stamp from this or I could set the sample rate on the MPU9150 so the accelertion values are linked to a time interval?

I have added a ‘For’ loop to count the accelerometer and Gyroscope readings from the MPU9150. I set the MPU9150 sample rate to 50Hz, which is the upper limit in the ‘For’ loop, but I am not sure if the readings are at specific time intervals within the sample rate or just the ‘For’ loop count. I suspect they are the latter.

I am trying to get acceleration values at a specific frequency (known time interval) so I can then calculate the velocity and then displacement. I am not sure I have done this correctly within the code!

Does anybody know how to get the acceleration output from the MPU9150 at a specific sample rate so that the acceleration readings are at specific time intervals?

Here is my code

[/
[color=blue]// 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 "MPU6050.h"

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

// 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
MPU6050 accelgyro;
//MPU6050 accelgyro(0x69); // <-- use for AD0 high

int16_t ax, ay, az;
int16_t gx, gy, gz;



// uncomment "OUTPUT_READABLE_ACCELGYRO" if you want to see a tab-separated
// list of the accel X/Y/Z and then gyro X/Y/Z values in decimal. Easy to read,
// not so easy to parse, and slow(er) over UART.
#define OUTPUT_READABLE_ACCELGYRO

// uncomment "OUTPUT_BINARY_ACCELGYRO" to send all 6 axes of data as 16-bit
// binary, one right after the other. This is very fast (as fast as possible
// without compression or data loss), and easy to parse, but impossible to read
// for a human.
//#define OUTPUT_BINARY_ACCELGYRO


#define LED_PIN 13
bool blinkState = false;

unsigned long PreviousBit = 0;
unsigned long SampleRate;


void setup() {
    // join I2C bus (I2Cdev library doesn't do this automatically)
    #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
        Wire.begin();
    #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
        Fastwire::setup(400, true);
    #endif

    // 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(38400);

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

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

    // use the code below to change accel/gyro offset values
    /*
    Serial.println("Updating internal sensor offsets...");
    // -76	-2359	1688	0	0	0
    Serial.print(accelgyro.getXAccelOffset()); Serial.print("\t"); // -76
    Serial.print(accelgyro.getYAccelOffset()); Serial.print("\t"); // -2359
    Serial.print(accelgyro.getZAccelOffset()); Serial.print("\t"); // 1688
    Serial.print(accelgyro.getXGyroOffset()); Serial.print("\t"); // 0
    Serial.print(accelgyro.getYGyroOffset()); Serial.print("\t"); // 0
    Serial.print(accelgyro.getZGyroOffset()); Serial.print("\t"); // 0
    Serial.print("\n");
    accelgyro.setXGyroOffset(220);
    accelgyro.setYGyroOffset(76);
    accelgyro.setZGyroOffset(-85);
    Serial.print(accelgyro.getXAccelOffset()); Serial.print("\t"); // -76
    Serial.print(accelgyro.getYAccelOffset()); Serial.print("\t"); // -2359
    Serial.print(accelgyro.getZAccelOffset()); Serial.print("\t"); // 1688
    Serial.print(accelgyro.getXGyroOffset()); Serial.print("\t"); // 0
    Serial.print(accelgyro.getYGyroOffset()); Serial.print("\t"); // 0
    Serial.print(accelgyro.getZGyroOffset()); Serial.print("\t"); // 0
    Serial.print("\n");
    */

    // configure Arduino LED for
    pinMode(LED_PIN, OUTPUT);
    
    //Set the MPU9150 acceleration range to +/-2g
    accelgyro.setFullScaleAccelRange(MPU6050_ACCEL_FS_2);
    
    //Set the sample rate divider value
    accelgyro.setRate(19);
    
    SampleRate = (1000.00/( 1.00 + accelgyro.getRate()));   // get a status message every NN ms equal to the sample rate
    
    //Print sample rate
    Serial.print("Sample Rate = ");
    Serial.print(SampleRate);
    Serial.println(" bits/s");
               
}

void loop() {
    
    unsigned long currentBit;
    
    for (unsigned long currentBit=0; currentBit <= SampleRate-1; currentBit++){

    // read raw accel/gyro measurements from device
    accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);

    // these methods (and a few others) are also available
    //accelgyro.getAcceleration(&ax, &ay, &az);
    //accelgyro.getRotation(&gx, &gy, &gz);

    #ifdef OUTPUT_READABLE_ACCELGYRO
        // display tab-separated accel/gyro x/y/z values
        Serial.print("a/g:\t"); 
        Serial.print(currentBit); Serial.print("\t");
        Serial.print(ax); Serial.print("\t");
        Serial.print(ay); Serial.print("\t");
        Serial.print(az); Serial.print("\t");
        Serial.print(gx); Serial.print("\t");
        Serial.print(gy); Serial.print("\t");
        Serial.println(gz);
        //delay(100);
    #endif
    
    #ifdef OUTPUT_BINARY_ACCELGYRO
        Serial.write((uint8_t)(ax >> 8)); Serial.write((uint8_t)(ax & 0xFF));
        Serial.write((uint8_t)(ay >> 8)); Serial.write((uint8_t)(ay & 0xFF));
        Serial.write((uint8_t)(az >> 8)); Serial.write((uint8_t)(az & 0xFF));
        Serial.write((uint8_t)(gx >> 8)); Serial.write((uint8_t)(gx & 0xFF));
        Serial.write((uint8_t)(gy >> 8)); Serial.write((uint8_t)(gy & 0xFF));
        Serial.write((uint8_t)(gz >> 8)); Serial.write((uint8_t)(gz & 0xFF));
    #endif

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

    }
}[/color]

code]

Yea all that loop is doing, is grabbing the accel values whether they are new or not, most likely not ;)

Is this your unit?:

module datasheet

If so, looks like your max rate on the accelerometer gyros is 8 KHz.

Also, calculating displacement from acceleration on these things is hard/unreliable/inaccurate, the inaccuracy increases the longer you attempt to calculate displacement over.

Yes this is the unit I am using (InvenSense MPU9150)

I am not looking for a high sample rate, somewhere between 50 and 200 bits/s, but this will depend upon the measurements I get and if I will need to increase this value once I have seen the results.

I have heard this is difficult but would like to give it a go and see what issues I get. My thought is that I sample at a suficiently high rate and periodically zero the displacement so the integration does not applify the error.