MPU-6050 使用 3軸ジャイロスコープ・3軸加速度センサー モジュールをArduinoでためしてみた
- 2018/03/11
- 17:37
MPU-6050 使用 3軸ジャイロスコープ・3軸加速度センサー モジュールをArduinoでためしてみた
RoboTakaoです。ようこそ「極力ローコスト ロボット製作 ブログ」にお越しくださいました。
今回は3軸ジャイロ&3軸加速度センサーを購入したのでArduino Nanoでテストしてみたいと思います。

情報
製品型番:GY521
商品重量:18.1 g
梱包サイズ:3 x 2.1 x 0.5 cm
入力電圧:3-5V
インターフェイス: I2C (2 wire, IIC)
ジャイロ測定範囲:±250 500 1000 2000 °/s
加速度測定範囲:±2±4±8±16g

MPU-6050 DataSheet
MPU-6050 Register Map
MPU-6050はArduino Playbookでも情報があります。
またこのArduino Playbookを参考にしたという下記サイトを参考(というかほぼコピペ、表示部分のみ変更)にしました。
加速度+ジャイロのGY-521(MPU-6050)を使ってみた -1-
初めての電子工作: Arduinoで6軸センサを動かしてみる
結線

スケッチ
// MPU-6050 Accelerometer + Gyro
// I2CにアクセスするためにWireライブラリを使用
#include
// レジスタアドレス
#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() {
int error;
uint8_t c;
Wire.begin();
// ボーレートを9600bpsにセット
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動作開始
MPU6050_write_reg(MPU6050_PWR_MGMT_1, 0);
}
void loop() {
int error;
float dT;
accel_t_gyro_union accel_t_gyro;
// 加速度、角速度の読み出し
// 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");
// 取得できるデータはビッグエンディアンなので上位バイトと下位バイトの入れ替え(AVRはリトルエンディアン)
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");
// 取得した加速度値を分解能で割って加速度(G)に変換する
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:");
Serial.print(acc_x, 2);
Serial.print(" acc_y:");
Serial.print(acc_y, 2);
Serial.print(" acc_z:");
Serial.print(acc_z, 2);
// 加速度からセンサ対地角を求める
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:");
Serial.print(acc_angle_x, 2);
Serial.print(" acc_angle_y:");
Serial.print(acc_angle_y, 2);
Serial.print(" acc_angle_z:");
Serial.print(acc_angle_z, 2);
// 取得した角速度値を分解能で割って角速度(degrees per sec)に変換する
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:");
Serial.print(gyro_x, 2);
Serial.print(" gyro_y:");
Serial.print(gyro_y, 2);
Serial.print(" gyro_z:");
Serial.println(gyro_z, 2);
}
// 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);
Serial.print("error = ");
Serial.println(error);
return (error);
};
動作確認
無事計測できてそうです。
それでは今回はこの辺で失礼します!ありがとうございます。
スポンサードリンク