Jump to content
I2Cdevlib Forums

Newbie - MPU-6050 Project


Recommended Posts

Hi Guys 

 

so glad i've found this forum.

 

i am developing a data recorder which uses various sensors connected to an arduino uno.

 

i have managed to get a GPS unit (gp-635t) and the MPU-6050 to work within the same program.  

 

but i also have pressure/altimeter (MPL3115A2), that i need to display data for which is also i2c connected to the external sensor input on the 6050.

 

im using the mpu6050 raw example code.

 

ive added this code 

 

   accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
   accelgyro.getExternalSensorWord(px);
      #ifdef OUTPUT_READABLE_ACCELGYRO
        // display tab-separated accel/gyro x/y/z values
        Serial.print("a/g:\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.print(gz);Serial.println(px);
 
but i dont know if its the correct output???
 
also i want to change the accel to 16G ive read the other thread and read through the h file but i still dont know which bit i need to change.

 

hopefully its a simple thing for you guys but im new to arduino and i2c

 

thanks

Link to comment
Share on other sites

If you want to read a sensor connected to MPU's aux I2C bus, check this topic where it is done with a magnetometer and adapt it to your needs.

http://www.i2cdevlib.com/forums/topic/111-arduino-example-sketch-to-read-magnetometer-while-dmp-is-on/

 

Don't miss the configuration part at the beggining.

 

And from documentation: (http://www.i2cdevlib.com/docs/html/class_m_p_u6050.html)

 

void MPU6050::setFullScaleAccelRange(uint8_t range)

0 = +/- 2g
1 = +/- 4g
2 = +/- 8g
3 = +/- 16g

Link to comment
Share on other sites


#include "I2Cdev.h"

#include "MPU6050_6Axis_MotionApps20.h"

#include <SoftwareSerial.h>

#include <TinyGPS.h>

#include <Wire.h>

#include "MPL3115A2.h"

#include "Wire.h"

MPU6050 mpu;

int16_t ax, ay, az;

int16_t gx, gy, gz;

MPL3115A2 myPressure;

TinyGPS gps;

SoftwareSerial nss(3, 4);

static void gpsdump(TinyGPS &gps);

static bool feedgps();

static void print_float(float val, float invalid, int len, int prec);

static void print_int(unsigned long val, unsigned long invalid, int len);

static void print_date(TinyGPS &gps);

static void print_str(const char *str, int len);

// uncomment "OUTPUT_READABLE_QUATERNION" if you want to see the actual

// quaternion components in a [w, x, y, z] format (not best for parsing

// on a remote host such as Processing or something though)

//#define OUTPUT_READABLE_QUATERNION

// uncomment "OUTPUT_READABLE_EULER" if you want to see Euler angles

// (in degrees) calculated from the quaternions coming from the FIFO.

// Note that Euler angles suffer from gimbal lock (for more info, see

// http://en.wikipedia.org/wiki/Gimbal_lock)

//#define OUTPUT_READABLE_EULER

// uncomment "OUTPUT_READABLE_YAWPITCHROLL" if you want to see the yaw/

// pitch/roll angles (in degrees) calculated from the quaternions coming

// from the FIFO. Note this also requires gravity vector calculations.

// Also note that yaw/pitch/roll angles suffer from gimbal lock (for

// more info, see: http://en.wikipedia.org/wiki/Gimbal_lock)

#define OUTPUT_READABLE_YAWPITCHROLL

#define OUTPUT_READABLE_ACCELGYRO

// uncomment "OUTPUT_READABLE_REALACCEL" if you want to see acceleration

// components with gravity removed. This acceleration reference frame is

// not compensated for orientation, so +X is always +X according to the

// sensor, just without the effects of gravity. If you want acceleration

// compensated for orientation, us OUTPUT_READABLE_WORLDACCEL instead.

//#define OUTPUT_READABLE_REALACCEL

// uncomment "OUTPUT_READABLE_WORLDACCEL" if you want to see acceleration

// components with gravity removed and adjusted for the world frame of

// reference (yaw is relative to initial orientation, since no magnetometer

// is present in this case). Could be quite handy in some cases.

//#define OUTPUT_READABLE_WORLDACCEL

// uncomment "OUTPUT_TEAPOT" if you want output that matches the

// format used for the InvenSense teapot demo

//#define OUTPUT_TEAPOT

#define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6)

bool blinkState = false;

// MPU control/status vars

bool dmpReady = false; // set true if DMP init was successful

uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU

uint8_t devStatus; // return status after each device operation (0 = success, !0 = error)

uint16_t packetSize; // expected DMP packet size (default is 42 bytes)

uint16_t fifoCount; // count of all bytes currently in FIFO

uint8_t fifoBuffer[64]; // FIFO storage buffer

// orientation/motion vars

Quaternion q; // [w, x, y, z] quaternion container

VectorInt16 aa; // [x, y, z] accel sensor measurements

VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements

VectorInt16 aaWorld; // [x, y, z] world-frame accel sensor measurements

VectorFloat gravity; // [x, y, z] gravity vector

float euler[3]; // [psi, theta, phi] Euler angle container

float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector

// ================================================================

// === INTERRUPT DETECTION ROUTINE ===

// ================================================================

volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high

void dmpDataReady() {

mpuInterrupt = true;

}

// ================================================================

// === INITIAL SETUP ===

// ================================================================

void setup() {

// join I2C bus (I2Cdev library doesn't do this automatically)

#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE

Wire.begin();

TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz)

#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE

Fastwire::setup(400, true);

#endif

Serial.begin(115200);

nss.begin(9600);

myPressure.begin(); // Get sensor online

// Configure the sensor

myPressure.setModeAltimeter(); // Measure altitude above sea level in meters

//myPressure.setModeBarometer(); // Measure pressure in Pascals from 20 to 110 kPa

myPressure.setOversampleRate(128); // Set Oversample to the recommended 128

myPressure.enableEventFlags(); // Enable all three pressure and temp event flags

// initialize device

Serial.println(F("Initializing I2C devices..."));

mpu.initialize();

mpu.setFullScaleAccelRange(MPU6050_ACCEL_FS_8);

Serial.print(mpu.getFullScaleAccelRange());

// verify connection

Serial.println(F("Testing device connections..."));

Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));

/*

// wait for ready

Serial.println(F("\nSend any character to begin DMP programming and demo: "));

while (Serial.available() && Serial.read()); // empty buffer

while (!Serial.available()); // wait for data

while (Serial.available() && Serial.read()); // empty buffer again

*/

// load and configure the DMP

Serial.println(F("Initializing DMP..."));

devStatus = mpu.dmpInitialize();

// supply your own gyro offsets here, scaled for min sensitivity

mpu.setXGyroOffset(220);

mpu.setYGyroOffset(76);

mpu.setZGyroOffset(-85);

mpu.setZAccelOffset(1788); // 1688 factory default for my test chip

// make sure it worked (returns 0 if so)

if (devStatus == 0) {

// turn on the DMP, now that it's ready

Serial.println(F("Enabling DMP..."));

mpu.setDMPEnabled(true);

// enable Arduino interrupt detection

Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));

attachInterrupt(0, dmpDataReady, RISING);

mpuIntStatus = mpu.getIntStatus();

// set our DMP Ready flag so the main loop() function knows it's okay to use it

Serial.println(F("DMP ready! Waiting for first interrupt..."));

dmpReady = true;

Serial.println("Sats HDOP Latitude Longitude Fix Date Time Date Alt Course Speed Card Distance Course Card Chars Sentences Checksum");

Serial.println(" (deg) (deg) Age Age (m) --- from GPS ---- ---- to London ---- RX RX Fail");

Serial.println("--------------------------------------------------------------------------------------------------------------------------------------");

// get expected DMP packet size for later comparison

packetSize = mpu.dmpGetFIFOPacketSize();

} else {

// ERROR!

// 1 = initial memory load failed

// 2 = DMP configuration updates failed

// (if it's going to break, usually the code will be 1)

Serial.print(F("DMP Initialization failed (code "));

Serial.print(devStatus);

Serial.println(F(")"));

}

// configure LED for output

pinMode(LED_PIN, OUTPUT);

}

// ================================================================

// === MAIN PROGRAM LOOP ===

// ================================================================

void loop() {

// if programming failed, don't try to do anything

if (!dmpReady) return;

// wait for MPU interrupt or extra packet(s) available

while (!mpuInterrupt && fifoCount < packetSize) {

// other program behavior stuff here

// .

// .

// .

// if you are really paranoid you can frequently test in between other

// stuff to see if mpuInterrupt is true, and if so, "break;" from the

// while() loop to immediately process the MPU data

// .

// .

// .

}

// reset interrupt flag and get INT_STATUS byte

mpuInterrupt = false;

mpuIntStatus = mpu.getIntStatus();

// get current FIFO count

fifoCount = mpu.getFIFOCount();

// check for overflow (this should never happen unless our code is too inefficient)

if ((mpuIntStatus & 0x10) || fifoCount == 1024) {

// reset so we can continue cleanly

mpu.resetFIFO();

Serial.println(F("FIFO overflow!"));

// otherwise, check for DMP data ready interrupt (this should happen frequently)

} else if (mpuIntStatus & 0x02) {

// wait for correct available data length, should be a VERY short wait

while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();

// read a packet from FIFO

mpu.getFIFOBytes(fifoBuffer, packetSize);

// track FIFO count here in case there is > 1 packet available

// (this lets us immediately read more without waiting for an interrupt)

fifoCount -= packetSize;

gpsdump(gps);

float altitude = myPressure.readAltitude();

Serial.print("Altitude(m):");

Serial.print(altitude, 2);

//altitude = myPressure.readAltitudeFt();

//Serial.print(" Altitude(ft):");

//Serial.print(altitude, 2);

//float pressure = myPressure.readPressure();

//Serial.print("Pressure(Pa):");

//Serial.print(pressure, 2);

float temperature = myPressure.readTemp();

Serial.print(" Temp(c):");

Serial.print(temperature, 2);

//float temperature = myPressure.readTempF();

//Serial.print(" Temp(f):");

//Serial.print(temperature, 2);

/*

#ifdef OUTPUT_READABLE_QUATERNION

// display quaternion values in easy matrix form: w x y z

mpu.dmpGetQuaternion(&q, fifoBuffer);

Serial.print("quat\t");

Serial.print(q.w);

Serial.print("\t");

Serial.print(q.x);

Serial.print("\t");

Serial.print(q.y);

Serial.print("\t");

Serial.println(q.z);

#endif

#ifdef OUTPUT_READABLE_EULER

// display Euler angles in degrees

mpu.dmpGetQuaternion(&q, fifoBuffer);

mpu.dmpGetEuler(euler, &q);

Serial.print("euler\t");

Serial.print(euler[0] * 180/M_PI);

Serial.print("\t");

Serial.print(euler[1] * 180/M_PI);

Serial.print("\t");

Serial.println(euler[2] * 180/M_PI);

#endif

*/

#ifdef OUTPUT_READABLE_YAWPITCHROLL

// display Euler angles in degrees

mpu.dmpGetQuaternion(&q, fifoBuffer);

mpu.dmpGetGravity(&gravity, &q);

mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);

Serial.print("ypr\t");

Serial.print(ypr[0] * 180/M_PI);

Serial.print("\t");

Serial.print(ypr[1] * 180/M_PI);

Serial.print("\t");

Serial.println(ypr[2] * 180/M_PI);

#endif

#ifdef OUTPUT_READABLE_ACCELGYRO

// display tab-separated accel/gyro x/y/z values

Serial.print("a/g:\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);

#endif

/*

#ifdef OUTPUT_READABLE_REALACCEL

// display real acceleration, adjusted to remove gravity

mpu.dmpGetQuaternion(&q, fifoBuffer);

mpu.dmpGetAccel(&aa, fifoBuffer);

mpu.dmpGetGravity(&gravity, &q);

mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);

Serial.print("areal\t");

Serial.print(aaReal.x);

Serial.print("\t");

Serial.print(aaReal.y);

Serial.print("\t");

Serial.println(aaReal.z);

#endif

#ifdef OUTPUT_READABLE_WORLDACCEL

// display initial world-frame acceleration, adjusted to remove gravity

// and rotated based on known orientation from quaternion

mpu.dmpGetQuaternion(&q, fifoBuffer);

mpu.dmpGetAccel(&aa, fifoBuffer);

mpu.dmpGetGravity(&gravity, &q);

mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);

mpu.dmpGetLinearAccelInWorld(&aaWorld, &aaReal, &q);

Serial.print("aworld\t");

Serial.print(aaWorld.x);

Serial.print("\t");

Serial.print(aaWorld.y);

Serial.print("\t");

Serial.println(aaWorld.z);

#endif

*/

// blink LED to indicate activity

blinkState = !blinkState;

digitalWrite(LED_PIN, blinkState);

}

}

static void gpsdump(TinyGPS &gps)

{

float flat, flon;

unsigned long age, date, time, chars = 0;

unsigned short sentences = 0, failed = 0;

static const float LONDON_LAT = 51.508131, LONDON_LON = -0.128002;

print_int(gps.satellites(), TinyGPS::GPS_INVALID_SATELLITES, 5);

print_int(gps.hdop(), TinyGPS::GPS_INVALID_HDOP, 5);

gps.f_get_position(&flat, &flon, &age);

print_float(flat, TinyGPS::GPS_INVALID_F_ANGLE, 9, 5);

print_float(flon, TinyGPS::GPS_INVALID_F_ANGLE, 10, 5);

print_int(age, TinyGPS::GPS_INVALID_AGE, 5);

print_date(gps);

print_float(gps.f_altitude(), TinyGPS::GPS_INVALID_F_ALTITUDE, 8, 2);

print_float(gps.f_course(), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2);

print_float(gps.f_speed_kmph(), TinyGPS::GPS_INVALID_F_SPEED, 6, 2);

print_str(gps.f_course() == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(gps.f_course()), 6);

print_int(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0UL : (unsigned long)TinyGPS::distance_between(flat, flon, LONDON_LAT, LONDON_LON) / 1000, 0xFFFFFFFF, 9);

print_float(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : TinyGPS::course_to(flat, flon, LONDON_LAT, LONDON_LON), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2);

print_str(flat == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(TinyGPS::course_to(flat, flon, LONDON_LAT, LONDON_LON)), 6);

gps.stats(&chars, &sentences, &failed);

print_int(chars, 0xFFFFFFFF, 6);

print_int(sentences, 0xFFFFFFFF, 10);

print_int(failed, 0xFFFFFFFF, 9);

Serial.println();

}

static void print_int(unsigned long val, unsigned long invalid, int len)

{

char sz[32];

if (val == invalid)

strcpy(sz, "*******");

else

sprintf(sz, "%ld", val);

sz[len] = 0;

for (int i=strlen(sz); i<len; ++i)

sz = ' ';

if (len > 0)

sz[len-1] = ' ';

Serial.print(sz);

feedgps();

}

static void print_float(float val, float invalid, int len, int prec)

{

char sz[32];

if (val == invalid)

{

strcpy(sz, "*******");

sz[len] = 0;

if (len > 0)

sz[len-1] = ' ';

for (int i=7; i<len; ++i)

sz = ' ';

Serial.print(sz);

}

else

{

Serial.print(val, prec);

int vi = abs((int)val);

int flen = prec + (val < 0.0 ? 2 : 1);

flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;

for (int i=flen; i<len; ++i)

Serial.print(" ");

}

feedgps();

}

static void print_date(TinyGPS &gps)

{

int year;

byte month, day, hour, minute, second, hundredths;

unsigned long age;

gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);

if (age == TinyGPS::GPS_INVALID_AGE)

Serial.print("******* ******* ");

else

{

char sz[32];

sprintf(sz, "%02d/%02d/%02d %02d:%02d:%02d ",

month, day, year, hour, minute, second);

Serial.print(sz);

}

print_int(age, TinyGPS::GPS_INVALID_AGE, 5);

feedgps();

}

static void print_str(const char *str, int len)

{

int slen = strlen(str);

for (int i=0; i<len; ++i)

Serial.print(i<slen ? str : ' ');

feedgps();

}

static bool feedgps()

{

while (nss.available())

{

if (gps.encode(nss.read()))

return true;

}

return false;

}

Link to comment
Share on other sites

  • 2 weeks later...

You should connect the pressure sensor in parallel with the MPU6050 on the I2C bus.  When the Arduino (or host) wants to talk to the MPU6050, it first sends the address (ID) of the MPU6050, 0x68 or 0x69.  Then, the MPU6050 responds to any subsequent commands, and the MPL3115A2 knows that it needs to leave the bus idle.  To talk to the MPL3115A2, the host sends the address(ID) of the MPL3115A2 (look at its datasheet) and the MPU6050 will not respond to any subsequent commands.

Arduino              MPU6050
|------|             |------|
|   SCL|----x--------|SCL   |
|   SDA|--x-|--------|SDA   |
|------|  | |        |------|
          | |
          | |        MPL3115A2
          | |        |------|
          | |--------|SCL   |
          |----------|SDA   |
                     |------|

The external interface on the MPU6050 is so that the MPU can use the data from the external device (magnetometer) in the DMP calculations.  If you want to get sensor data independently of the MPU, you should connect them as you would on any standard I2C bus.

Link to comment
Share on other sites

  • 1 month later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

×
×
  • Create New...