6軸IMUモーションセンサー(MPU-6050)入門ガイド
部品と材料
| Arduino UNO | 1 | |
| IMUセンサーモジュール(6自由度) | MPU-6050搭載 | 1 |
このプロジェクトについて
最高性能のIMU(慣性計測ユニット)センサーであるMPU-6050について学び、Arduinoとのインターフェース方法を解説します。次回のチュートリアルでは3Dでのモーション可視化に挑戦します。
MPU-6050は、同一シリコンダイ上に3軸ジャイロスコープと3軸加速度計を搭載し、さらにオンボードのDMP(Digital Motion Processor™)が複雑な6軸MotionFusionアルゴリズムを処理します。
これらのモーショントラッキングデバイスは、スマートフォン、タブレット、ウェアラブルセンサー向けに、低消費電力、低コスト、高性能を実現するよう設計されています。

必要なもの
ハードウェア:
- Arduino UNO
- MPU-6050センサー
- 接続用ワイヤー

ソフトウェア: Arduino IDE
通信プロトコル: I2CバスプロトコルでArduinoと通信します。
加速度計とジャイロスコープを別々に使うこともできますが、この統合モジュールほど正確ではありません。

配線図と接続プロファイル
以下の2つの図のいずれかを参照して接続してください。


上記で不明な場合は、以下のピン接続表を参照してください:
| IMU MPU-6050 の 5V (または VCC) | → Arduino の 5V (または 3.3V) |
| IMU MPU-6050 の SDA | → Arduino アナログ入力 A4 |
| IMU MPU-6050 の SCL | → Arduino アナログ入力 A5 |
| IMU MPU-6050 の GND | → Arduino GND |
| IMU MPU-6050 の INTピン | → Arduino デジタルピン 2 (PWM) |


※モジュールに5VピンがあればArduinoの5Vに、なければ3.3Vに接続して過電圧を防いでください。
ライブラリのインストール
- MPU6050ライブラリ(MPU6050.zip)をダウンロードし、解凍してArduinoの
librariesフォルダに配置 - I2Cdevライブラリ(I2Cdev.zip)も同様にインストール(未導入の場合)
Arduino IDEを再起動し、[ファイル] → [スケッチ例] → [MPU6050] → [Examples] → [MPU6050_DMP6] を開きます。

I2CdevとMPU6050ライブラリをインクルードします。

コンパイルしてエラーがないか確認してください。

アップロードとシリアルモニター
正しいポート(COMポート)が選択されているか確認し、スケッチをアップロードします。

アップロード後、シリアルモニター(Ctrl+Shift+M)を開き、ボーレートを115200に設定します。他のボーレートでは文字化けします。

「Initializing I2C devices…」が表示されない場合はリセットボタンを押してください。
知識コーナー: DMPとは?
画面に「Send any character to begin DMP programming and demo:」と表示されます。DMPはDigital Motion Processing(デジタルモーション処理)の略です。MPU-6050には内蔵モーションプロセッサがあり、加速度計とジャイロスコープの値を処理して正確な3D値(ヨー、ピッチ、ロール)を出力します。

知識コーナー: I2Cとは?
I2Cバスは2本のアクティブな線(SDA、SCL)とグラウンドで構成されます。両線は双方向で、SDAはシリアルデータ、SCLはシリアルクロックです。バス上の各デバイスは固有アドレスを持ち、マスター(ここではArduino)が通信を開始し、スレーブ(MPU-6050)が応答します。マルチマスターバスで、複数のマスターを接続可能です。
次回予告
次回のチュートリアルでは、このモーションデータを3Dで可視化します。

コード
Arduino code for MPU sensor (Arduino)
DMP(Digital Motion Processor)を使用した完全なサンプルコードです。ヨー/ピッチ/ロール角度を出力する設定(OUTPUT_READABLE_YAWPITCHROLL)が有効になっています。
// I2Cdev and MPU6050 must be installed as libraries
#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"
//#include "MPU6050.h" // not necessary if using MotionApps include file
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include "Wire.h"
#endif
MPU6050 mpu; // AD0=LOWで0x68、HIGHで0x69
// ================================================================
// 注意: INTピンをArduinoの外部割り込み#0(Uno/Megaではデジタルピン2)に接続必須
// ================================================================
#define OUTPUT_READABLE_YAWPITCHROLL
#define LED_PIN 13
bool blinkState = false;
bool dmpReady = false;
uint8_t mpuIntStatus;
uint8_t devStatus;
uint16_t packetSize;
uint16_t fifoCount;
uint8_t fifoBuffer[64];
Quaternion q;
VectorInt16 aa, aaReal, aaWorld;
VectorFloat gravity;
float euler[3];
float ypr[3];
uint8_t teapotPacket[14] = { '$', 0x02, 0,0, 0,0, 0,0, 0,0, 0x00, 0x00, '\r', '\n' };
volatile bool mpuInterrupt = false;
void dmpDataReady() { mpuInterrupt = true; }
void setup() {
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
Wire.begin();
TWBR = 24; // 400kHz I2Cクロック
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
Fastwire::setup(400, true);
#endif
Serial.begin(115200);
while (!Serial); // Leonardo対応
Serial.println(F("Initializing I2C devices..."));
mpu.initialize();
Serial.println(F("Testing device connections..."));
Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));
Serial.println(F("\nSend any character to begin DMP programming and demo: "));
while (Serial.available() && Serial.read());
while (!Serial.available());
while (Serial.available() && Serial.read());
Serial.println(F("Initializing DMP..."));
devStatus = mpu.dmpInitialize();
// ジャイロ/加速度オフセット(各チップで調整必要)
mpu.setXGyroOffset(220);
mpu.setYGyroOffset(76);
mpu.setZGyroOffset(-85);
mpu.setZAccelOffset(1788);
if (devStatus == 0) {
Serial.println(F("Enabling DMP..."));
mpu.setDMPEnabled(true);
Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));
attachInterrupt(0, dmpDataReady, RISING);
mpuIntStatus = mpu.getIntStatus();
Serial.println(F("DMP ready! Waiting for first interrupt..."));
dmpReady = true;
packetSize = mpu.dmpGetFIFOPacketSize();
} else {
Serial.print(F("DMP Initialization failed (code "));
Serial.print(devStatus);
Serial.println(F(")"));
}
pinMode(LED_PIN, OUTPUT);
}
void loop() {
if (!dmpReady) return;
while (!mpuInterrupt && fifoCount < packetSize) {
// 他の処理をここに記述可能
}
mpuInterrupt = false;
mpuIntStatus = mpu.getIntStatus();
fifoCount = mpu.getFIFOCount();
if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
mpu.resetFIFO();
Serial.println(F("FIFO overflow!"));
} else if (mpuIntStatus & 0x02) {
while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();
mpu.getFIFOBytes(fifoBuffer, packetSize);
fifoCount -= packetSize;
#ifdef OUTPUT_READABLE_YAWPITCHROLL
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetGravity(&gravity, &q);
mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
Serial.print("ypr\t");
Serial.print(ypr[0] * 180/M_PI);
Serial.print("\t");
Serial.print(ypr[1] * 180/M_PI);
Serial.print("\t");
Serial.println(ypr[2] * 180/M_PI);
#endif
blinkState = !blinkState;
digitalWrite(LED_PIN, blinkState);
}
}
回路図

製造プロセス
- Raspberry Piでライントラッキングセンサー – シンプルなKY-033ドア/ライン検出器
- GY-91モジュールでRaspberry Pi上に堅牢な温度・センサーAPIを構築
- Raspberry PiでPIRモーションセンサーとLEDを制御
- Raspberry Pi GPIOマスター:PIRモーションセンサーをB+/Model 2でインターフェース
- HC-SR501 PIRモーションセンサーをRaspberry Piで接続・調整・プログラミングする方法
- TJBot入門:組み立て、設定、音声制御で自分だけのAIロボットを構築
- RAK 831 LoRaゲートウェイをRaspberry Pi 3に導入するステップバイステップガイド
- Raspberry Pi 3 と RAK831 モジュールで LoRa ゲートウェイを構築するステップバイステップガイド
- Arduino初心者チュートリアル01: 最初のプロジェクトを始めよう
- Eagle Groupを知る:コンセプトから完成まで一貫した高品質金属加工のパートナー
- 保険業界における AI:実践的スターターガイド