Go Down

Topic: (GY-87) ...10DOF MPU6050+HMC5883L +BMP180  (Read 11091 times) previous topic - next topic

pacheco

Mar 07, 2016, 01:34 am Last Edit: Mar 07, 2016, 01:51 am by pacheco
Hello....
I bought the 10DOF described on "Subject" in order to combine output data to help myself with clinometer, course, temperature and pressure on a boat.
Searching on libraries I have found that GY-87 has some difficulties to send magnetometer data due to the fact that hmc5883l is located behind the MPU6050. So I have to activate a bypass mode in the MPU6050....
In others words, first I can´t get data... so, I can´t think to go further on my project.
Please.. take a look at http://www.control.aau.dk/~jdn/edu/doc/arduino/gy80gy87/

the partial code included seems to solve the problem adding the following code  to MPU6050
Code: [Select]
#include <Wire.h>
#include <MPU6050.h>
#include <hmc5883l.h>

MPU6050 mpu;  // the mpu6050

hmc5883l compass; // Store our compass as a variable.


void setup()
{
  Wire.begin();
  mpu.begin();  // initalise MPU6050
  mpu.setI2CBypassEnabled(true); // set bypass mode
  // now we can reach hmc5883l
  compass = hmc5883l(); // Construct a new HMC5883 compass.
  ...


I don´t really know how to accomplish the mentioned "bypass"
Thanks in advance..

PD.. The final project aims to send to a display on the boat all data from the GY-87 so, after solving the "internals" between MPU6050 vs HMC5883l, I´m seeking a way to see on the serial COM port all data available.

Koepel

The setI2CBypassEnabled() is part of the i2cdevlib MPU-6050 library.

This is the function in the library : https://github.com/jrowberg/i2cdevlib/blob/master/Arduino/MPU6050/MPU6050.cpp
Code: [Select]

void MPU6050::setI2CBypassEnabled(bool enabled) {
    I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, enabled);
}

pacheco

Thanks a lot Koepel.
I solved the main trouble using this code:
Code: [Select]
#include "Wire.h"
#include "I2Cdev.h"
#include "MPU6050.h"
#include "HMC5883L.h"

MPU6050 accelgyro;
HMC5883L mag;

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

#define LED_PIN 13
bool blinkState = false;

void setup() {
 
   Wire.begin();
   accelgyro.setI2CMasterModeEnabled(false);
   accelgyro.setI2CBypassEnabled(true) ;
   accelgyro.setSleepEnabled(false);

   Serial.begin(9600);

   // initialize device
   Serial.println("Initializing I2C devices...");
   accelgyro.initialize();
   mag.initialize();
   Serial.println(mag.testConnection() ? "HMC5883L connection successful" : "HMC5883L connection failed");

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

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

void loop() {
   
   accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
   mag.getHeading(&mx, &my, &mz);

   // 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.print("\t");
   
   Serial.print("mag:\t");
   Serial.print(mx); Serial.print("\t");
   Serial.print(my); Serial.print("\t");
   Serial.print(mz); Serial.print("\t");
   
// To calculate heading in degrees. 0 degree indicates North
   float heading = atan2(my, mx);
   if(heading < 0)
     heading += 2 * M_PI;
   Serial.print("heading:\t");
   Serial.println(heading * 180/M_PI);

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


Serial monitor (COM3) displays and updates data as I move the hasdware.
Now I plan to add to the same sketch the output of BMP180...
Any advice about the way to implement the bove code including BMP180?
Thanks a lot for your help.

Koepel

The BMP180 has a few delays. For example in the ultra-high-resolution, a delay of about 26 ms is needed.
You might have to split the source code of an existing library for the BMP180. Send the command to read the pressure, and at another moment read the data.

You don't use the FIFO and interrupt of the MPU-6050 ? You let the loop() run and the delay(50) slows it down ? That is not very accurate, a call to a Serial function will change the timing. But is makes it easier to add the BMP180. Try to find how long it takes, and reduce the delay(50).

pacheco

Hello again..
Thanks Koepel.
As you probably have noticed, I´m just a beginner in Arduino stuff..
I was good in electronics before I retired from Navy but, even I tried to make some progress in software, it was too hard/too difficult in the 80´s when sofware was mainly implemented in Machine Language with punched cards..
OK..
I have download libraries from https://github.com/sparkfun/BMP180_Breakout
Then, I load the next code:
Code: [Select]
#include <SFE_BMP180.h>
#include <Wire.h>
SFE_BMP180 pressure;
#define ALTITUDE 1655.0

void setup()
{
  Serial.begin(9600);
  Serial.println("REBOOT");

  // Initialize the sensor (it is important to get calibration values stored on the device).

  if (pressure.begin())
    Serial.println("BMP180 init success");
  else
  {
    // Oops, something went wrong, this is usually a connection problem,
    // see the comments at the top of this sketch for the proper connections.

    Serial.println("BMP180 init fail\n\n");
    while(1); // Pause forever.
  }
}

void loop()
{
  char status;
  double T,P,p0,a;

  // Loop here getting pressure readings every 10 seconds.

  // If you want sea-level-compensated pressure, as used in weather reports,
  // you will need to know the altitude at which your measurements are taken.
  // We're using a constant called ALTITUDE in this sketch:
 
  Serial.println();
  Serial.print("provided altitude: ");
  Serial.print(ALTITUDE,0);
  Serial.print(" meters, ");
  Serial.print(ALTITUDE*3.28084,0);
  Serial.println(" feet");
 
  // If you want to measure altitude, and not pressure, you will instead need
  // to provide a known baseline pressure. This is shown at the end of the sketch.

  // You must first get a temperature measurement to perform a pressure reading.
 
  // Start a temperature measurement:
  // If request is successful, the number of ms to wait is returned.
  // If request is unsuccessful, 0 is returned.

  status = pressure.startTemperature();
  if (status != 0)
  {
    // Wait for the measurement to complete:
    delay(status);

    // Retrieve the completed temperature measurement:
    // Note that the measurement is stored in the variable T.
    // Function returns 1 if successful, 0 if failure.

    status = pressure.getTemperature(T);
    if (status != 0)
    {
      // Print out the measurement:
      Serial.print("temperature: ");
      Serial.print(T,2);
      Serial.print(" deg C, ");
      Serial.print((9.0/5.0)*T+32.0,2);
      Serial.println(" deg F");
     
      // Start a pressure measurement:
      // The parameter is the oversampling setting, from 0 to 3 (highest res, longest wait).
      // If request is successful, the number of ms to wait is returned.
      // If request is unsuccessful, 0 is returned.

      status = pressure.startPressure(3);
      if (status != 0)
      {
        // Wait for the measurement to complete:
        delay(status);

        // Retrieve the completed pressure measurement:
        // Note that the measurement is stored in the variable P.
        // Note also that the function requires the previous temperature measurement (T).
        // (If temperature is stable, you can do one temperature measurement for a number of pressure measurements.)
        // Function returns 1 if successful, 0 if failure.

        status = pressure.getPressure(P,T);
        if (status != 0)
        {
          // Print out the measurement:
          Serial.print("absolute pressure: ");
          Serial.print(P,2);
          Serial.print(" mb, ");
          Serial.print(P*0.0295333727,2);
          Serial.println(" inHg");

          // The pressure sensor returns abolute pressure, which varies with altitude.
          // To remove the effects of altitude, use the sealevel function and your current altitude.
          // This number is commonly used in weather reports.
          // Parameters: P = absolute pressure in mb, ALTITUDE = current altitude in m.
          // Result: p0 = sea-level compensated pressure in mb

          p0 = pressure.sealevel(P,ALTITUDE); // we're at 1655 meters (Boulder, CO)
          Serial.print("relative (sea-level) pressure: ");
          Serial.print(p0,2);
          Serial.print(" mb, ");
          Serial.print(p0*0.0295333727,2);
          Serial.println(" inHg");

          // On the other hand, if you want to determine your altitude from the pressure reading,
          // use the altitude function along with a baseline pressure (sea-level or other).
          // Parameters: P = absolute pressure in mb, p0 = baseline pressure in mb.
          // Result: a = altitude in m.

          a = pressure.altitude(P,p0);
          Serial.print("computed altitude: ");
          Serial.print(a,0);
          Serial.print(" meters, ");
          Serial.print(a*3.28084,0);
          Serial.println(" feet");
        }
        else Serial.println("error retrieving pressure measurement\n");
      }
      else Serial.println("error starting pressure measurement\n");
    }
    else Serial.println("error retrieving temperature measurement\n");
  }
  else Serial.println("error starting temperature measurement\n");

  delay(5000);  // Pause for 5 seconds.
}

The above code displays data as in attached pic.
Now..
¿How I "merge" the MPU6050+HMC5883L (solved previously) with the BMP180 code detailed in this post?..
I´ve been digging, including BMP libraries in the 6050/5883L sketch. The serial port shows data from BMP180 but very difficult to read on the Serial window in the middle of Gyro/Mag data..
As I said fro the beggining, I want to get all possible data from GY-87 for navigation purposes.
Once I achieve data at a reasonable speed from GY-87 (without software conflicts), I´ll decide what is the best Arduino compatible screen (TFT or similar) to install it on board..
Best regards...


Koepel

As a beginner you should have started with Neopixels : https://learn.adafruit.com/adafruit-neopixel-uberguide/overview
Or an other well documented tutorial from Adafruit.

Now you have three sensors, that is not easy. They are not the newest sensors, which makes it extra hard.
Modern sensor have accelerometer + gyro + magnetometer in a single chip.

Adafruit has a 10-DOF board which comes with a good tutorial and software : https://www.adafruit.com/product/1604

The Kalman Guide has software for the MPU-6050 + HMC8553L. There is a link at the bottom of the first post : http://forum.arduino.cc/index.php?topic=58048.0

You are using the i2cdevlib at this moment. I suggest to keep using that. What is the problem with the extra BMP180 code ? You can stop the serial monitor from scrolling to have a better look at the numbers. Or slow down the loop() by increasing the delay at the end of the loop().

For navigation ? Why not use a GPS ? https://www.adafruit.com/products/746

Go Up