Using an MPU6050 with Adafruit library

The application is, to all intents and purposes, drone related

Hi, I have an MPU6050 and I'm trying to understand how I use the gyroscope with the adafruit library. I'm happily able to read out accelerometer data and I have an Uno beeping with different tones when it is tilted on X/Y/Z planes

When it comes to the gyro, I can read the data which, as I understand it, gives me X/Y/X acceleration in radians per second squared. I thought I would be able to just take the time between two readings and then know how many radians (and therefore degrees) moved.

I keep stumbling into various I2C demos without the adafruit library doing arctan etc. for pitch/roll/yaw but it feels like I should be able to use the adafruit library to do this more easily. Is anybody able to give some pointers?

Thanks

James

//-Include files--------------------------------------------------------------------------------------------------------------------------------------------------------------------------

#include  <Adafruit_MPU6050.h>                                      //Hardware functions specific to the 6050
#include <Adafruit_Sensor.h>                                        //Unified sensor abstration layer
#include <Wire.h>                                                   //I2C interface

//-Globals--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Adafruit_MPU6050      MPU6050;                                      //MPU6050 object
int                   X_POS                     = 0;
int                   Y_POS                     = 0;
int                   Z_POS                     = 0;
long                  OLD_TIME                  = 0;

//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

void setup(void)
{
  //Wait for the serial port to become available
  Serial.begin(115200);
  while (!Serial)
  {
    //Shouldn't enter this loop normally
    delay(10);
  };

  //Try to configure the gyro etc.
  if (SetupAccelerometer() == false)
  {
    //Enter our infinite loop
    DeadMPU6050();
  }
}

//-Sets up the MPU6050--------------------------------------------------------------------------------------------------------------------------------------------------------------------

bool SetupAccelerometer()
{
  bool ReturnValue = false;

  //If we can't talk to the hardware
  if (MPU6050.begin() == false)
  {
    //Display a debug message, we will return false
    Serial.println("MPU6050 failure");
  }
  else
  {
    //Range in +/- 'G', 2 is the default which is most sensitive MPU6050_RANGE_2_G, MPU6050_RANGE_4_G, MPU6050_RANGE_8_G, MPU6050_RANGE_16_G
    MPU6050.setAccelerometerRange(MPU6050_RANGE_2_G);

    //Range in degrees per second, 250 is the default, smaller is more sensitive, MPU6050_RANGE_250_DEG, MPU6050_RANGE_500_DEG, MPU6050_RANGE_1000_DEG, MPU6050_RANGE_2000_DEG
    MPU6050.setGyroRange(MPU6050_RANGE_250_DEG);

    //Digital low pass filter for smoothing, 260 disables, removes high frequency noise, MPU6050_BAND_260_HZ, MPU6050_BAND_184_HZ, MPU6050_BAND_94_HZ, MPU6050_BAND_44_HZ, MPU6050_BAND_21_HZ, MPU6050_BAND_10_HZ, MPU6050_BAND_5_HZ
    MPU6050.setFilterBandwidth(MPU6050_BAND_21_HZ);

    //Flag that it worked OK
    ReturnValue = true;
  }

  return ReturnValue;
}

//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

void loop()
{
  sensors_event_t Accelerometer, Gyroscope, Temperature;

  MPU6050.getEvent(&Accelerometer, &Gyroscope, &Temperature);

  if (Accelerometer.acceleration.x == 0 && Accelerometer.acceleration.y == 0 && Accelerometer.acceleration.z == 0 && Gyroscope.gyro.x == 0 && Gyroscope.gyro.y == 0 && Gyroscope.gyro.z == 0)
  {
    DeadMPU6050();
  }
  else
  {
    //We're crashing now, the Z axis doesn't have 9.8 m/S of gravity pulling on it
    if (Accelerometer.acceleration.z < 7)
    {
      //Serial.println ("Z axis -");
      Beep(100, 300);
    }
    else
    {
      if (Accelerometer.acceleration.x > 3)
      {
        //Serial.println ("X axis +");
        Beep(2500, 50);
      }
      else if (Accelerometer.acceleration.x < -3)
      {
        //Serial.println ("X axis -");
        Beep(2000, 50);
      }

      if (Accelerometer.acceleration.y > 3)
      {
        //Serial.println ("Y axis +");
        Beep(1500, 50);
      }
      else if (Accelerometer.acceleration.y < -3)
      {
        //Serial.println ("Y axis -");
        Beep(1000, 50);
      }
    }

    long NewTime = micros();
    if (OLD_TIME != 0)
    {
      //Multiply the change in time between samples by the number of degrees per second moved (/1000 to convert from mS to S)
      X_POS = X_POS + (((NewTime - OLD_TIME) * (Gyroscope.gyro.x * RAD_TO_DEG ))/1000000);
      Y_POS = Y_POS + (((NewTime - OLD_TIME) * (Gyroscope.gyro.y * RAD_TO_DEG ))/1000000);
      Z_POS = Z_POS + (((NewTime - OLD_TIME) * (Gyroscope.gyro.z * RAD_TO_DEG ))/1000000);
    }
    OLD_TIME = micros();

    delay(200);
  }
}

//-Infinite loop with error messages if the MPU6050 is dead or dies-----------------------------------------------------------------------------------------------------------------------

void DeadMPU6050()
{
  //Stay here forever, alarming
  while (1)
  {
    Beep(BUZZER_LOW_FREQUENCY, 300);
    delay(100);
    Beep(BUZZER_HIGH_FREQUENCY, 300);
    Serial.println ("No MPU6050 found!");
  };
}

No. If the gyro gave results in radians per second, then you could do that. But, as you said, it gives results in radians per second squared, in other words radians per second per second. It's an acceleration, not a speed.

OK thanks, so any tips on how I can do it?

Nobody any ideas at all?

The gyro reports rotational rates about the X, Y and Z axes. The rates can be interpreted in terms of degrees per second or radians per second, depending on how you scale the units.

To measure angle changes, you need to first calibrate the gyro by measuring the stationary offsets, subtract those offsets from later readings, then integrate the corrected rates to get angles. The measured angles will drift due to temperature sensitivity, etc.

You can use the accelerometer to measure stationary tilt angles, following this tutorial.

Many thanks for your response, I'll have a good look through that and come back

I'm not sure this is what I need having reviewed it. This appears to be converting accelerometer readings to interpret pitch/roll/yaw rather than gyro readings?

I don't believe the gyroscope needs to be calibrated, I am not sure if the adafruit library takes care of that but it doesn't appear to be exposed. The readings do appear to be valid already without offsets etc.

I still need to get radins per second per second into a usable angle. If someone could give a pointer in plain English then I can have a go at coding it

I think I need angular displacement from this...

Rate gyroscopes always need to be calibrated. They have an offset rate, and the offset is rather strongly temperature dependent.

If you need to get angular displacement (3D orientation as a function of time) from a rate gyro, then you integrate the rates with respect to time. That won't work for more than a couple of minutes, even with a calibrated gyro, because of the drift problem.

For the MPU-6050 you can try quaternion integration. Simple example here (use the gyro-only code).

Thanks but I think I have cracked it. I haven't done any cal but it appears that the accelerometers return s^2 but the gyro is just radiands per second, I now have pretty graphs of direction changes in all orientations working

You still seem to be confused.

Accelerometer units are proportional to meters per second squared (m*s^-2).

To get motion direction changes, integrate acceleration with respect to time to get velocity, and check for sign changes in the velocity. Of course velocity offsets must be subtracted.

No it's the gyro I was struggling with not the accelerometer and that's not S^2 so I'm sorted

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.