3軸加速度・3軸ジャイロセンサー MPU-6050の使い方

MPU-6050 3軸加速度、3軸ジャイロセンサーの使い方 センサー

3軸加速度・3軸ジャイロセンサーMPU-6050から加速度データと角速度データ、温度データを読み取る方法を紹介します。

使用するマイコンはRaspberry Piで、プログラム言語はPythonです。

サンプルプログラムでは、センサーからデータを読み取るだけでなく測定条件設定も行っています。

センサーの主な仕様
加速度
測定範囲:±2g、±4g、±8g、±16g
分解能:16.384LSB/g、8.192LSB/g、4.096LSB/g、2.048LSB/g
温度特性(測定範囲±2gの時):±0.02%/℃
零g時のオフセット:X軸±50mg、Y軸±50mg、Z軸±80mg

角速度
測定範囲:±250°/sec、±500°/sec 、±1000°/sec 、±2000°/sec
分解能:131LSB/(°/sec)、65.5LSB/(°/sec)、32.8LSB/(°/sec)、16.4/(°/sec)
零°/sec時のオフセット:±20°/sec

温度
測定範囲:-40℃~+85℃
分解能:340LSB/℃
オフセット:-521LSB

センサーの準備

MPU-6050の購入

MPU-6050は24端子のQFNと呼ばれる形状です。
センサーを手ではんだ付けするのは不可能なのでモジュールの購入になると思います。

下の写真はAmazonで購入したMPU-6050モジュールです。今回は、このモジュールを使ったサンプルプログラムを紹介します。

MPU-6050モジュールの写真

モジュールとRaspberry Piの接続

接続図

ブレッドボードを使用したMPU-6050モジュールとRaspberryPiの接続

接続写真

ブレッドボードを使用したMPU-6050の接続写真 1
ブレッドボードを使用したMPU-6050の接続写真 2

Raspberry Piの通信設定とPythonの操作方法

Raspberry PiのI2C通信設定を有効にします。
下の記事でRaspberry Piの通信設定と、Pythonの基本操作を説明しています。

I2C通信プログラミング

プログラムコード

Pythonプログラムです。

import smbus
import time

#I2C設定
i2c = smbus.SMBus(1)
dev_addr = 0x68

#MPU-6050設定
#CONFIGレジスタ
i2c.write_byte_data(dev_addr, 0x1a, 0x00)

#GYRO_CONFIGレジスタ
i2c.write_byte_data(dev_addr, 0x1b, 0x00)

#ACCEL_CONFIGレジスタ
i2c.write_byte_data(dev_addr, 0x1c, 0x00)

#PWR_MGMT_1レジスタ
i2c.write_byte_data(dev_addr, 0x6b, 0x00)

#繰り返し
while True:

    #加速度データ読み込み
    acc_x = i2c.read_word_data(dev_addr, 0x3b)
    acc_y = i2c.read_word_data(dev_addr, 0x3d)
    acc_z = i2c.read_word_data(dev_addr, 0x3f)
        
    #角速度データ読み込み
    gyr_x = i2c.read_word_data(dev_addr, 0x43)
    gyr_y = i2c.read_word_data(dev_addr, 0x45)
    gyr_z = i2c.read_word_data(dev_addr, 0x47)
    
    #温度データ読み込み
    tmp_ = i2c.read_word_data(dev_addr, 0x41)
    
    #加速度データ変換
    acc_x = (acc_x << 8) & 0xFF00 | (acc_x >> 8)
    acc_y = (acc_y << 8) & 0xFF00 | (acc_y >> 8)
    acc_z = (acc_z << 8) & 0xFF00 | (acc_z >> 8)
    
    #角速度データ変換
    gyr_x = (gyr_x << 8) & 0xFF00 | (gyr_x >> 8)
    gyr_y = (gyr_y << 8) & 0xFF00 | (gyr_y >> 8)
    gyr_z = (gyr_z << 8) & 0xFF00 | (gyr_z >> 8)
    
    #温度データ変換
    tmp = (tmp << 8) & 0xFF00 | (tmp >> 8)
    
    #加速度極性判断
    if acc_x >= 32768:
        acc_x -= 65536
    
    if acc_y >= 32768:
        acc_y -= 65536
    
    if acc_z >= 32768:
        acc_z -= 65536
    
    #角速度極性判断
    if gyr_x >= 32768:
        gyr_x -= 65536
    
    if gyr_y >= 32768:
        gyr_y -= 65536
    
    if gyr_z >= 32768:
        gyr_z -= 65536
    
    #温度極性判断
    if tmp >= 32768:
        tmp -= 65536
    
    #加速度を物理量に変換
    acc_x = acc_x / 16384.0
    acc_y = acc_y / 16384.0
    acc_z = acc_z / 16384.0
    
    #角速度を物理量に変換
    gyr_x = gyr_x / 131.0
    gyr_y = gyr_y / 131.0
    gyr_z = gyr_z / 131.0
    
    #温度を物理量に変換
    tmp = tmp / 340 + 36.53
    
    #加速度表示
    print('acc x:' + str(acc_x))
    print('acc y:' + str(acc_y))
    print('acc z:' + str(acc_z))
    
    #角速度表示
    print('gyr x:' + str(gyr_x))
    print('gyr y:' + str(gyr_y))
    print('gyr z:' + str(gyr_z))
    
    #温度表示
    print('tmp:' + str(tmp))
    
    time.sleep(0.5)

プログラムの説明

プログラムの流れです。

  1. I2C通信の設定
  2. センサーの設定
  3. センサーから加速度データ、角速度データ、温度データを取得
  4. データを物理量に変換し画面に表示
  5. 3.~4.を繰り返します

1.I2C通信の設定

#I2C設定
i2c = smbus.SMBus(1)
dev_addr = 0x68

i2c = smbus.SMBus(1)
インスタンス生成です。使用するBus1を指定します。

dev_addr = 0x68
アドレス指定です。MPU-6050のアドレスは0x68(16進数)で、通信時に指定します。
AD0ピンをGNDに接続すると0x69になります。

Raspberry PiにMPU-6050を接続した状態で、LXTerminalから「i2cdetect -y 1」コマンドを入力すると、アドレスが0x68であることを確認出来ます。

2.センサーの設定

※データシートとは別にレジスタマップ pdfファイルがあるので、設計内容について詳しく知りたい方は、こちもダウンロードしてください。

#CONFIGレジスタ
i2c.write_byte_data(dev_addr, 0x1a, 0x00)

#GYRO_CONFIGレジスタ
i2c.write_byte_data(dev_addr, 0x1b, 0x00)

#ACCEL_CONFIGレジスタ
i2c.write_byte_data(dev_addr, 0x1c, 0x00)

#PWR_MGMT_1レジスタ
i2c.write_byte_data(dev_addr, 0x6b, 0x00)

設定は、write_byte_data(adr, reg, dat)関数を使用します。

第1引数 adr:I2C通信のアドレス
第2引数 reg:レジスタ(設定したい項目の記憶場所)
第3引数 dat :データ(レジスタに設定する内容)

サンプルプログラムでは以下の4つのレジスタ設定をしています。

CONFIGレジスタ(0x1a)

i2c.write_byte_data(dev_addr, 0x1a, 0x00)

0x1a
DLPF_CFG[2:0](加速度と角速度のローパスフィルタ設定)
EXT_SYNC_SET[2:0](外部フレーム同期)

0x00
DLPF_CFG[2:0](00:加速度260Hz、角速度256Hz)
EXT_SYNC_SET[2:0](input disabled)

レジスタマップの『4.3 Register 26 – Configuration』で詳細を確認できます。

Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
 – –  EXT_SYNC_SET[2:0]
DLPF_CFG[2:0]
 – 0 0 0 0 0 0
0 0

GYRO_CONFIGレジスタ(0x1b)

i2c.write_byte_data(dev_addr, 0x1b, 0x00)

0x1b
XG_ST(X軸ジャイロセルフテスト)
YG_ST(Y軸ジャイロセルフテスト)
ZG_ST(Z軸ジャイロセルフテスト)
FS_SEL[1:0](フルスケールレンジ)

0x00
XG_ST(0:しない)
YG_ST(0:しない)
ZG_ST(0:しない)
FS_SEL[1:0](00:±250°/sec)

レジスタマップの『4.4 Register 27 – Gyroscope Configuration』で詳細を確認できます。

Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
XG-ST YG-ST ZG-ST FS_SEL[1:0]
0 0 0 0 0
0 0

ACCEL_CONFIGレジスタ(0x1c)

i2c.write_byte_data(dev_addr, 0x1c, 0x00)

0x1c
XA_ST(X軸加速度セルフテスト)
YA_ST(Y軸加速度セルフテスト)
ZA_ST(Z軸加速度セルフテスト)
AFS_SEL[1:0](フルスケールレンジ)

0x00
XA_ST(0:しない)
YA_ST(0:しない)
ZA_ST(0:しない)
AFS_SEL[1:0](00:±2g)

レジスタマップの『4.5 Register 28 – Accelerometer Configuration』で詳細を確認できます。

Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
XA_ST YA_ST ZA_ST AFS_SEL[1:0]
0 0 0 0
0 0

PWR_MGMT_1レジスタ(0x6b)

i2c.write_byte_data(dev_addr, 0x6b, 0x00)

0x6b
CLKSEL[2:0](クロックソース)
TEMP_DIS(温度センサー 有効/無効)
CYCLE(SLEEPが無効でCYCLEが有効の時サイクルする)
SLEEP(スリープ 有効/無効)
DEVICE_RESET(デフォルトへリセット)

0x00
CLKSEL[2:0](00:内部8MHz発振)
TEMP_DIS(0:有効)
CYCLE(0:無効)
SLEEP(0:無効)
DEVICE_RESET(リセットしない)

レジスタマップの『4.28 Register 107 – Power Management 1』で詳細を確認できます。

Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
DEVICE
_RESET
SLEEP CYCLE TEMP_DIS CLKSEL[2:0]
0 0 0 0 0
0 0

3.センサーから加速度、角速度、温度データを取得

#加速度データ読み込み
acc_x = i2c.read_word_data(dev_addr, 0x3b)
#省略#
        
#角速度データ読み込み
gyr_x = i2c.read_word_data(dev_addr, 0x43)
#省略#
    
#温度データ読み込み
tmp_ = i2c.read_word_data(dev_addr, 0x41)

取得は read_word_data(adr, reg)関数を使用します。

第1引数 adr:I2C通信のアドレス
第2引数 reg:レジスタ(測定データの記憶場所)

サンプルプログラムは各データの先頭のレジスタを指定し、2バイトで取得しています。

i2c.read_byte_data(dev_addr, レジスタ)

0x3b, 0x3c:ACCEL_XOUT
0x3d, 0x3e:ACCEL_YOUT
0x3f, 0x40:ACCEL_ZOUT

0x41, 0x42:TEMP

0x43, 0x44:GYR_XOUT
0x45, 0x46:GYR_YOUT
0x47, 0x48:GYR_ZOUT

レジスタマップ『4.17 Registers 59 to 64 – Accelerometer Measurements』、『4.18 Registers 65 and 66 – Temperature Measurement』、『4.19 Registers 67 to 72 – Gyroscope Measurements』 で、詳細を確認できます。

4.データを物理量に変換し画面に表示

#加速度データ変換
acc_x = (acc_x << 8) & 0xFF00 | (acc_x >> 8)
#省略#
    
#角速度データ変換
gyr_x = (gyr_x << 8) & 0xFF00 | (gyr_x >> 8)
#省略#

#温度データ変換
tmp = (tmp << 8) & 0xFF00 | (tmp >> 8)

各データのフォーマットが上位と下位で逆なので入れ替えます。

16bitデータ
#加速度極性判断
if acc_x >= 32768:
    acc_x -= 65536
#省略#

#角速度極性判断
if gyr_x >= 32768:
    gyr_x -= 65536
#省略#

#温度極性判断
if tmp >= 32768:
    tmp -= 65536

if acc_x >= 32768:
acc_x -= 65536

2の補数表現を符号ありに変換します。

2の補数の詳しい説明はこちら
2の補数」(2021年10月12日 (火) 17:00 UTCの版)『ウィキペディア日本語版』

#加速度
acc_x = acc_x / 16384.0
#省略#

#角速度
gyr_x = gyr_x / 131.0
#省略#

#温度
tmp = tmp / 340 + 36.53

acc_x = acc_x / 16384.0
gyr_x = gyr_x / 131.0
tmp = tmp / 340 + 36.53

物理量への変換の計算は、レジスタマップの『4.17』、『4.18』、『4.19』で確認できます。

#加速度表示
print('acc x:' + str(acc_x))
#省略#
    
#角速度表示
print('gyr x:' + str(gyr_x))
#省略#
    
#温度表示
print('tmp:' + str(tmp))

print(‘acc x:’ + str(acc_x))
3軸加速度、3軸角速度、温度データを画面に表示します。

5.3.~4.を繰り返します

#繰り返し
while True:

while True:
Stopボタンが押されるまで繰り返します。

※この『while True:』は、22行目のwhile文です。

プログラムの実行結果

プログラムを実行します。

①Runボタンを押します。
②3軸加速度データ、3軸角速度データ、温度データを0.5秒間隔で画面に表示します。
③Stopボタンを押すとプログラムを終了します。

センサーの設置を、上記『モジュールとRaspberry Piの接続』の『接続写真』の様にした場合は、X軸、Y軸ともにほぼ0g付近となり、Z軸は1g付近となります。

ブレッドボードを90°傾けるとX軸もしくはY軸が1g付近になります。
逆に傾けると-1gです。
これは重力加速度1gを検出しています。
90°で1gなので、これを利用すれば加速度計で角度の検出が可能です。

また、ブレッドボードを水平の状態で回転させるとZ軸の数値が変化することがわかると思います。

PythonのRunボタンとStopボタン
MPU-6050のプログラムの実行結果
加速度 角速度 6軸

以上、MPU-6050モジュールからI2C通信で3軸加速度データ、3軸角速度データ、温度データを読み込んで表示するサンプルでした。

まとめ

3軸加速度・ジャイロセンサー MPU-6050のサンプルプログラムと、その動作について紹介しました。如何でしたでしょうか。

加速度の校正については、重力加速度の1gは静的な校正であり、動的な校正をどのようにして行うか?などを考え始めると、いろいろ面白いです。

MPU-6050は、いろいろ設定を変えられるので、レジスタマップの資料を見ながら、それらの設定を変えて確認してみてはいかがでしょうか。

プログラミングやソフトウェアの記事です。

コメント