Three Axis Accelerometer and Gyrosscope - MPU 6050 breakout board

Introduction

The InvenSense MPU-6050 sensor contains a MEMS accelerometer and a MEMS gyro in a single chip. It is very accurate, as it contains 16-bits analog to digital conversion hardware for each channel. Therefore it captures the x, y, and z channel at the same time. The sensor uses the I2C-bus to interface with the Arduino.

The MPU-6050 is not expensive, especially given the fact that it combines both an accelerometer and a gyro.

mpu-6050-1

Photo: GY-521 breakout board

Also note that Invensense has combined the MPU-6050 with a magnetometer (compass) in a single chip called MPU-9150.

Reading raw values is easy, the rest is not
Reading the raw values for the accelerometer and gyro is easy. The sleep mode has to be disabled, and then the registers for the accelerometer and gyro can be read.

But the sensor also contains a 1024 byte FIFO buffer. The sensor values can be programmed to be placed in the FIFO buffer. And the buffer can be read by the Arduino.

The FIFO buffer is used together with the interrupt signal. If the MPU-6050 places data in the FIFO buffer, it signals the Arduino with the interrupt signal so the Arduino knows that there is data in the FIFO buffer waiting to be read.
A little more complicated is the ability to control a second I2C-device.
The MPU-6050 always acts as a slave to the Arduino with the SDA and SCL pins connected to the I2C-bus.
But beside the normal I2C-bus, it has it's own I2C controller to be a master on a second (sub)-I2C-bus. It uses the pins AUX_DA and AUX_CL for that second (sub)-I2C-bus.
It can control, for example, a magnetometer. The values of the magnetometer can be passed on to the Arduino.

Things get really complex with the "DMP".
The sensor has a "Digital Motion Processor" (DMP), also called a "Digital Motion Processing Unit". This DMP can be programmed with firmware and is able to do complex calculations with the sensor values.
For this DMP, InvenSense has a discouragement policy, by not supplying enough information how to program the DMP. However, some have used reverse engineering to capture firmware.

The DMP ("Digital Motion Processor") can do fast calculations directly on the chip. This reduces the load for the microcontroller (like the Arduino). The DMP is even able to do calculations with the sensor values of another chip, for example a magnetometer connected to the second (sub)-I2C-bus.

Code
The accelerometer and gyro values are called the "raw" values. This is just as with other accelerometer and gyro sensors. A more sophisticated application is using the DMP to retrieve specific computed values from the sensor.

The Short example sketch on this page is a very short sketch that shows all the raw values. Click "Get code" at right, below the sketch, and copy it into a sketch.

The Example sketch (base code) on this page is also just showing the raw values, but it is an attempt to be a complete base for more functions.

For serious use of the MPU-6050, Jeff Rowberg has done an excellent job.
See his I2C lib: http://www.i2cdevlib.com/devices/mpu6050
Or the latest code on GitHub: https://github.com/jrowberg/i2cdevlib/tree/master/Arduino/MPU6050

The FreeIMU library includes the MPU-6050 code from Jeff Rowberg.
The FreeIMU library: http://www.varesano.net/projects/hardware/FreeIMU

To start with the MPU-6050, see the page of InvenSense: http://www.invensense.com/mems/gyro/mpu6050.html

MPU-6050 with raspberry pi

Introduction
The MPU-6050 is the world’s first and only 6-axis motion tracking devices designed for the low power, low cost, and high performance requirements of smartphones, tablets and wearable sensors.

df

Components

  • 1 * Raspberry Pi
  • 1 * Breadboard
  • 4 * Jumper wires (Male to Male, 2 red and 2 black)
  • 1 * Network cable (or USB wireless network adapter)
  • 1 * MPU-6050 module
  • 4 * Jumper wires (M to F) (preferable to the 4-pin anti-reverse cable)

Experimental Principle
In this experiment, use I2C to obtain the values of the three-axis acceleration sensor and three-axis gyroscope for MPU6050 and display them on the screen.

Experimental Procedures
Step 1: Build the circuit

Raspberry Pi T-Cobbler MPU-6050 Module
SCL SCL1 SCL
SDA SDA1 SDA
5V 5V0 VCC
GND GND GND

MPU6050

Step2: Setup I2C (see Appendix 1. If you have set I2C, skip this step.)
For C language users:
Step 3: Change directory
cd /home/pi/SunFounder_SensorKit_for_RPi2/C/32_mpu6050/
Step 4: Compile
gcc 32_mpu6050_accel.c –lwiringPi –lm
gcc 32_mpu6050_gyro.c –lwiringPi –lm
Step 5: Run
sudo ./a.out

For Python users:
Step 3: Change directory
cd /home/pi/SunFounder_SensorKit_for_RPi2/Python/
Step 4: Run
sudo python 32_mpu6050.py

Now you can see the values of the acceleration sensor, gyroscope, and XY-axis rotation read by MPU6050 printed on the screen constantly.

rwerew

C Code

 
#include  <wiringPiI2C.h>
#include  <stdio.h>
#include  <math.h>

int fd;
int acclX, acclY, acclZ;
int gyroX, gyroY, gyroZ;
double acclX_scaled, acclY_scaled, acclZ_scaled;
double gyroX_scaled, gyroY_scaled, gyroZ_scaled;

int read_word_2c(int addr)
{
  int val;
  val = wiringPiI2CReadReg8(fd, addr);
  val = val << 8;
  val += wiringPiI2CReadReg8(fd, addr+1);
  if (val >= 0x8000)
    val = -(65536 - val);

  return val;
}

double dist(double a, double b)
{
  return sqrt((a*a) + (b*b));
}

double get_y_rotation(double x, double y, double z)
{
  double radians;
  radians = atan2(x, dist(y, z));
  return -(radians * (180.0 / M_PI));
}

double get_x_rotation(double x, double y, double z)
{
  double radians;
  radians = atan2(y, dist(x, z));
  return (radians * (180.0 / M_PI));
}

int main()
{
  fd = wiringPiI2CSetup (0x68);
  wiringPiI2CWriteReg8 (fd,0x6B,0x00);//disable sleep mode 
  printf("set 0x6B=%X\n",wiringPiI2CReadReg8 (fd,0x6B));
  
  while(1) {

    acclX = read_word_2c(0x3B);
    acclY = read_word_2c(0x3D);
    acclZ = read_word_2c(0x3F);

    acclX_scaled = acclX / 16384.0;
    acclY_scaled = acclY / 16384.0;
    acclZ_scaled = acclZ / 16384.0;
    
    printf("My acclX_scaled: %f\n", acclX_scaled);
    printf("My acclY_scaled: %f\n", acclY_scaled);
    printf("My acclZ_scaled: %f\n", acclZ_scaled);

    printf("My X rotation: %f\n", get_x_rotation(acclX_scaled, acclY_scaled, acclZ_scaled));
    printf("My Y rotation: %f\n", get_y_rotation(acclX_scaled, acclY_scaled, acclZ_scaled));

    
    delay(100);
  }
  return 0;
}




 
#include  <wiringPiI2C.h>
#include  <stdio.h>
#include  <math.h>

int fd;
int acclX, acclY, acclZ;
int gyroX, gyroY, gyroZ;
double acclX_scaled, acclY_scaled, acclZ_scaled;
double gyroX_scaled, gyroY_scaled, gyroZ_scaled;

int read_word_2c(int addr)
{
  int val;
  val = wiringPiI2CReadReg8(fd, addr);
  val = val << 8;
  val += wiringPiI2CReadReg8(fd, addr+1);
  if (val >= 0x8000)
    val = -(65536 - val);

  return val;
}

int main()
{
  fd = wiringPiI2CSetup (0x68);
  wiringPiI2CWriteReg8 (fd,0x6B,0x00);//disable sleep mode 
  printf("set 0x6B=%X\n",wiringPiI2CReadReg8 (fd,0x6B));
  
  while(1) {

    gyroX = read_word_2c(0x43);
    gyroY = read_word_2c(0x45);
    gyroZ = read_word_2c(0x47);

    gyroX_scaled = gyroX / 131.0;
    gyroY_scaled = gyroY / 131.0;
    gyroZ_scaled = gyroZ / 131.0;
    
    printf("My gyroX_scaled: %f\n", gyroX_scaled);
    printf("My gyroY_scaled: %f\n", gyroY_scaled);
    printf("My gyroZ_scaled: %f\n", gyroZ_scaled);

    
    delay(100);
  }
  return 0;
}

**Python Code **


#!/usr/bin/python

import smbus
import math
import time

# Power management registers
power_mgmt_1 = 0x6b
power_mgmt_2 = 0x6c

def read_byte(adr):
    return bus.read_byte_data(address, adr)

def read_word(adr):
    high = bus.read_byte_data(address, adr)
    low = bus.read_byte_data(address, adr+1)
    val = (high << 8) + low
    return val

def read_word_2c(adr):
    val = read_word(adr)
    if (val >= 0x8000):
        return -((65535 - val) + 1)
    else:
        return val

def dist(a,b):
    return math.sqrt((a*a)+(b*b))

def get_y_rotation(x,y,z):
    radians = math.atan2(x, dist(y,z))
    return -math.degrees(radians)

def get_x_rotation(x,y,z):
    radians = math.atan2(y, dist(x,z))
    return math.degrees(radians)


bus = smbus.SMBus(1) # or bus = smbus.SMBus(1) for Revision 2 boards
address = 0x68       # This is the address value read via the i2cdetect command

# Now wake the 6050 up as it starts in sleep mode
bus.write_byte_data(address, power_mgmt_1, 0)

while True:
    time.sleep(0.1)
    gyro_xout = read_word_2c(0x43)
    gyro_yout = read_word_2c(0x45)
    gyro_zout = read_word_2c(0x47)

    print "gyro_xout : ", gyro_xout, " scaled: ", (gyro_xout / 131)
    print "gyro_yout : ", gyro_yout, " scaled: ", (gyro_yout / 131)
    print "gyro_zout : ", gyro_zout, " scaled: ", (gyro_zout / 131)

    accel_xout = read_word_2c(0x3b)
    accel_yout = read_word_2c(0x3d)
    accel_zout = read_word_2c(0x3f)

    accel_xout_scaled = accel_xout / 16384.0
    accel_yout_scaled = accel_yout / 16384.0
    accel_zout_scaled = accel_zout / 16384.0

    print "accel_xout: ", accel_xout, " scaled: ", accel_xout_scaled
    print "accel_yout: ", accel_yout, " scaled: ", accel_yout_scaled
    print "accel_zout: ", accel_zout, " scaled: ", accel_zout_scaled

    print "x rotation: " , get_x_rotation(accel_xout_scaled, accel_yout_scaled, accel_zout_scaled)
    print "y rotation: " , get_y_rotation(accel_xout_scaled, accel_yout_scaled, accel_zout_scaled)

    time.sleep(0.5)

**Accelerometer Using Arduino 101 **

  • COMPONENTS AND SUPPLIES
  1. Arduino 101 & Genuino 101
    ArdGen_101
  2. Jumper wires (generic)
    11026-02
  3. Breadboard (generic)
    12002-04
  4. LED (generic)
    09590-01
  5. Resistor 221 ohm
    MFR-25FBF52-221R_sml
  • APPS AND ONLINE SERVICES
  1. Arduino IDE

Introduction
Learn how to read Accelerometer Sensor on Arduino 101 and show tilt status on LED.

Arduino 101 is good for IOT starters. Having the Intel® Curie™ Module, designed to integrate the core's low power-consumption and high performance with the Arduino's ease-of-use, Bluetooth Low Energy capabilities and on-board 6-axis accelerometer/gyroscope, this board will provide exciting opportunities for building creative projects in the connected world.

More information about the technical specifications and documentation can be found on the Arduino/Genuino 101 main page.

Build Circuit

Lets build our circuit!

  • Connect Arduino 101 pin GND (ground) to one of the bread board pins. I picked the upper left pin.
  • Connect 3 resistor on the same column of the GND jumper wire
  • Add 3 LEDs each negative pin is connected to the other end of its resistor
  • Grab 3 jumper wire
  • Connect 1st LED's positive pin to Digita Pin ~9
  • Connect 2nd LED's positive pin to Digita Pin ~6
  • Connect 3d LED's positive pin to Digita Pin ~5
  • Our circuit must be look like the images below.

Program our Board
Plug in your Arduino 101.

Download ReadSensorsLed source code and upload it.

Testing our accelerometer

  • Tilt Sideways - The yellow LED will light up if we are in positive X axis
  • Tilt Upside down - The Orange LED will light up if we are in positive Y axis
  • Tilt - The Red LED will light up if we are in positive Z axis.

The brightness of the LED corresponds to the value of the positive axis.
The maximum readings for each axis is 17000.
So we calculated the brightness (0-255) of the analogWrite by brightness = axis/66.66 ;

About the Code

Arduino 101 has Intel Curie Module that uses Arduino api CurieIMU.h We can read the accelerometer and gyroscope using this function.

CurieIMU.readMotionSensor(ax, ay, az, gx, gy, gz);

The axis variables are used as parameter and will be referenced by the api to update the values.

Finally get the brightness of led using the formula and update the LED

if(ax>0)
    axBrightness = ax/66.66;  
 else     axBrightness=0;   analogWrite(axLed,axBrightness);
 if(ay>0)     
    ayBrightness = ay/66.66;   
else     
    ayBrightness=0;   
analogWrite(ayLed,ayBrightness);      
if(az>0)
     azBrightness = az/66.66;
else
     azBrightness=0;   
analogWrite(azLed,azBrightness);

SCHEMATICS

Create 3 LED in Arduino Circuit (Download)
untitled_1_03_56_pm_rjOvU0PXo9

CODE

#include "CurieIMU.h"
int ax, ay, az;         // accelerometer values
int gx, gy, gz;         // gyrometer values

int axBrightness = 0;
int axLed = 9;

int ayBrightness = 0;
int ayLed = 6;


int azBrightness = 0;
int azLed = 5;

void setup(){
  
  pinMode(axLed, OUTPUT); 
  pinMode(ayLed, OUTPUT); 
  Serial.begin(9600); // initialize Serial communication
  CurieIMU.begin();
  delay(5000); // Allow the user to set everything down
  CurieIMU.autoCalibrateGyroOffset();
  CurieIMU.autoCalibrateAccelerometerOffset(X_AXIS, 0);
  CurieIMU.autoCalibrateAccelerometerOffset(Y_AXIS, 0);
  CurieIMU.autoCalibrateAccelerometerOffset(Z_AXIS, 0);
}

String jsonEncodeValue(String key, float keyVal){
  return "\"" + key + "\":" + String(keyVal) + "";
}

String assembleJson(String keysAndVals){
  return "{" + keysAndVals + "}";
}

void loop(){
  // read raw accel/gyro measurements from device
  CurieIMU.readMotionSensor(ax, ay, az, gx, gy, gz);

  // display JSON formatted accel/gyro x/y/z values
  String keyVals = jsonEncodeValue("ax", ax) + ",";
  keyVals += jsonEncodeValue("ay", ay) + ",";
  keyVals += jsonEncodeValue("az", az) + ",";
  keyVals += jsonEncodeValue("gx", gx) + ",";
  keyVals += jsonEncodeValue("gy", gy) + ",";
  keyVals += jsonEncodeValue("gz", gz);
  
  if(Serial){
    Serial.println(keyVals);
  }
  delay(100);

  if(ax>0)
    axBrightness = ax/66.66;
  else
    axBrightness=0;
  analogWrite(axLed,axBrightness);

  if(ay>0)
    ayBrightness = ay/66.66;
  else
    ayBrightness=0;
  analogWrite(ayLed,ayBrightness);
  
  if(az>0)
    azBrightness = az/66.66;
  else
    azBrightness=0;
  analogWrite(azLed,azBrightness);
}