N006 Arduinoで加速度センサーモジュールGY-521(MPU-6050)を使う

N***の記事は、購入したデバイスの動作確認を掲載しています。接続は簡単なので、特別な事情がない限り、配線図はないです。

Amazonで以下の商品を購入
MPU-6050 使用 3軸ジャイロスコープ・3軸加速度センサー モジュール
(2014/09/09時点 ¥430税込)
電源は3.3V/5VともOKでした。
I2C addressは0x68でした。

MPU-6050センサーモジュール(購入品)
2014-09-08 18.57.51
チップは基板実装済みだけど、基板に端子を半田付けしないといけない。

MPU-6050センサーモジュール(端子をはんだ付け)
2014-09-08 18.22.35


参考にしたソフトウェア

動作確認の際に利用させていただいたソフトウェア
加速度+ジャイロのGY-521(MPU-6050)を使ってみた
作者の方々に感謝いたします。

GY-521(MPU-6050)とArduinoの接続ピン情報
GY-521 Arduino UNO
------------------
VCC   POWER 5V or 3.3V
GND   POWER GND
SCL   A5(SCL)
SDA   A4(SDA)
XDA   -
XCL   -
AD0   -
INT   D2
------------------

GY-521 Arduino MEGA
------------------
VCC   POWER 5V or 3.3V
GND   POWER GND
SCL   D21(SCL)
SDA   D20(SDA)
XDA   -
XCL   -
AD0   -
INT   D2
------------------
組み立てた様子
2014-09-08 18.54.32

サンプルを動作させた時のコンソール画面
スクリーンショット 2014-09-08 18.51.20
温度と9種類の情報が表示されているので動作OKです。
115200bpsで接続すると文字化けしまくったので9600bpsにしています。
対応策もあるようですが、今回はモジュールの動作テストだけですので、9600bpsでよしとします。


スケッチ
// MPU-6050 Accelerometer + Gyro
  #include <Wire.h>

  #define MPU6050_ACCEL_XOUT_H       0x3B   // R
  #define MPU6050_WHO_AM_I           0x75   // R
  #define MPU6050_PWR_MGMT_1         0x6B   // R/W
  #define MPU6050_I2C_ADDRESS 0x68

typedef union accel_t_gyro_union{
  struct{
    uint8_t x_accel_h;
    uint8_t x_accel_l;
    uint8_t y_accel_h;
    uint8_t y_accel_l;
    uint8_t z_accel_h;
    uint8_t z_accel_l;
    uint8_t t_h;
    uint8_t t_l;
    uint8_t x_gyro_h;
    uint8_t x_gyro_l;
    uint8_t y_gyro_h;
    uint8_t y_gyro_l;
    uint8_t z_gyro_h;
    uint8_t z_gyro_l;
  }
  reg;
  struct{
    int16_t x_accel;
    int16_t y_accel;
    int16_t z_accel;
    int16_t temperature;
    int16_t x_gyro;
    int16_t y_gyro;
    int16_t z_gyro;
  }
  value;
};

void setup(){
  Wire.begin();
  int error;
  uint8_t c;
  Serial.begin(9600);
  Serial.print("InvenSense MPU-6050");
  Serial.print("June 2012");
  error = MPU6050_read (MPU6050_WHO_AM_I, &c, 1);
  Serial.print("WHO_AM_I : ");
  Serial.print(c,HEX);
  Serial.print(", error = ");
  Serial.println(error,DEC);
  error = MPU6050_read (MPU6050_PWR_MGMT_1, &c, 1);
  Serial.print("PWR_MGMT_1 : ");
  Serial.print(c,HEX);
  Serial.print(", error = ");
  Serial.println(error,DEC);
  MPU6050_write_reg (MPU6050_PWR_MGMT_1, 0);
}

  void loop(){
  int error;
  float dT;
  accel_t_gyro_union accel_t_gyro;
  error = MPU6050_read (MPU6050_ACCEL_XOUT_H, (uint8_t *) &accel_t_gyro, sizeof(accel_t_gyro));
  Serial.print(error,DEC);
  Serial.print("\t");

    uint8_t swap;
#define SWAP(x,y) swap = x; x = y; y = swap
  SWAP (accel_t_gyro.reg.x_accel_h, accel_t_gyro.reg.x_accel_l);
  SWAP (accel_t_gyro.reg.y_accel_h, accel_t_gyro.reg.y_accel_l);
  SWAP (accel_t_gyro.reg.z_accel_h, accel_t_gyro.reg.z_accel_l);
  SWAP (accel_t_gyro.reg.t_h, accel_t_gyro.reg.t_l);
  SWAP (accel_t_gyro.reg.x_gyro_h, accel_t_gyro.reg.x_gyro_l);
  SWAP (accel_t_gyro.reg.y_gyro_h, accel_t_gyro.reg.y_gyro_l);
  SWAP (accel_t_gyro.reg.z_gyro_h, accel_t_gyro.reg.z_gyro_l);

  dT = ( (float) accel_t_gyro.value.temperature + 12412.0) / 340.0;
  Serial.print(dT, 1);
  Serial.print("\t");

  float acc_x = accel_t_gyro.value.x_accel / 16384.0; //FS_SEL_0 16,384 LSB / g
  float acc_y = accel_t_gyro.value.y_accel / 16384.0;
  float acc_z = accel_t_gyro.value.z_accel / 16384.0;

  Serial.print(acc_x, 2);
  Serial.print("\t");
  Serial.print(acc_y, 2);
  Serial.print("\t");
  Serial.print(acc_z, 2);
  Serial.print("\t");

  float acc_angle_x = atan2(acc_x, acc_z) * 360 / 2.0 / PI;
  float acc_angle_y = atan2(acc_y, acc_z) * 360 / 2.0 / PI;
  float acc_angle_z = atan2(acc_x, acc_y) * 360 / 2.0 / PI;

  Serial.print(acc_angle_x, 2);
  Serial.print("\t");
  Serial.print(acc_angle_y, 2);
  Serial.print("\t");
  Serial.print(acc_angle_z, 2);
  Serial.print("\t");

  float gyro_x = accel_t_gyro.value.x_gyro / 131.0;  //FS_SEL_0 131 LSB / (°/s)
  float gyro_y = accel_t_gyro.value.y_gyro / 131.0;
  float gyro_z = accel_t_gyro.value.z_gyro / 131.0;

  Serial.print(gyro_x, 2);
  Serial.print("\t");
  Serial.print(gyro_y, 2);
  Serial.print("\t");
  Serial.print(gyro_z, 2);
  Serial.println("");
}

// MPU6050_read
int MPU6050_read(int start, uint8_t *buffer, int size){
  int i, n, error;
  Wire.beginTransmission(MPU6050_I2C_ADDRESS);
  n = Wire.write(start);
  if (n != 1)
    return (-10);
  n = Wire.endTransmission(false);   // hold the I2C-bus
  if (n != 0)
    return (n);
  // Third parameter is true: relase I2C-bus after data is read.
  Wire.requestFrom(MPU6050_I2C_ADDRESS, size, true);
  i = 0;
  while(Wire.available() && i<size){
    buffer[i++]=Wire.read();
  }
  if ( i != size)
    return (-11);
  return (0);  // return : no error
}

// MPU6050_write
int MPU6050_write(int start, const uint8_t *pData, int size){
  int n, error;
  Wire.beginTransmission(MPU6050_I2C_ADDRESS);
  n = Wire.write(start);        // write the start address
  if (n != 1)
    return (-20);
  n = Wire.write(pData, size);  // write data bytes
  if (n != size)
    return (-21);
  error = Wire.endTransmission(true); // release the I2C-bus
  if (error != 0)
    return (error);
  return (0);         // return : no error
}

// MPU6050_write_reg
int MPU6050_write_reg(int reg, uint8_t data){
  int error;
  error = MPU6050_write(reg, &data, 1);
  return (error);
}


前の記事: N005 照度計測モジュール(BH1750FVI)
この記事: N006 加速度センサーモジュールGY-521(MPU-6050)
次の記事: N007 デジタル・コンパスモジュールGY-271(HMC5883L)