こんにちは,けい(@Keimameshiba)です.
今回は,加速度センサーMPU6050を使って,
について,まとめていきたいと思います.
目次
使うプログラム
# -*- coding: utf-8 -*-
import smbus
import math
from time import sleep
import time
DEV_ADDR = 0x68
ACCEL_XOUT = 0x3b
ACCEL_YOUT = 0x3d
ACCEL_ZOUT = 0x3f
TEMP_OUT = 0x41
GYRO_XOUT = 0x43
GYRO_YOUT = 0x45
GYRO_ZOUT = 0x47
PWR_MGMT_1 = 0x6b
PWR_MGMT_2 = 0x6c
bus = smbus.SMBus(1)
time.sleep(0.2)
# 初期設定
bus.write_byte_data(DEV_ADDR, 0x6B, 0x80) # RESET
time.sleep(0.25)
bus.write_byte_data(DEV_ADDR, 0x6B, 0x00) # RESET
time.sleep(0.25)
bus.write_byte_data(DEV_ADDR, 0x6A, 0x07) # RESET
time.sleep(0.25)
bus.write_byte_data(DEV_ADDR, 0x6A, 0x00) # RESET
time.sleep(0.25)
bus.write_byte_data(DEV_ADDR, 0x1A, 0x00) # CONFIG
bus.write_byte_data(DEV_ADDR, 0x1B, 0x18) # +-2000°/s
bus.write_byte_data(DEV_ADDR, 0x1C, 0x08) # +-4g
time.sleep(0.1)
def read_word(adr):
high = bus.read_byte_data(DEV_ADDR, adr)
low = bus.read_byte_data(DEV_ADDR, adr+1)
val = (high << 8) + low
return val
def read_word_sensor(adr):
val = read_word(adr)
if (val >= 0x8000): return -((65535 - val) + 1)
else: return val
def get_temp():
temp = read_word_sensor(TEMP_OUT)
x = temp / 340 + 36.53 # data sheet(register map)記載の計算式.
return x
def getGyro():
x = read_word_sensor(GYRO_XOUT)/ 16.4
y = read_word_sensor(GYRO_YOUT)/ 16.4
z = read_word_sensor(GYRO_ZOUT)/ 16.4
return [x, y, z]
def getAccel():
x = read_word_sensor(ACCEL_XOUT)/ 8192
y= read_word_sensor(ACCEL_YOUT)/ 8192
z= read_word_sensor(ACCEL_ZOUT)/ 8192
return [x, y, z]
file = open("accel_data.csv", "w")
while(True):
for i in range(1000):
ax, ay, az = getAccel()
gx, gy, gz = getGyro()
print ('{0:4.3f}, {0:4.3f}, {0:4.3f}, {0:4.3f}, {0:4.3f}, {0:4.3f},' .format(gx, gy, gz, ax, ay, az))
file.write(str(gx) + "," + str(gy) + "," + str(gz) + "," + str(ax) + "," + str(ay) + "," + str(az) + "\n")
time.sleep(0.02)
break
file.close()
I2C通信をするにあたって,smbusというライブラリを用います.
MPU-6050のデータシートを読む
全部読まなくてもいい?
データシートってページ数が多いし,学校でも読み方を教えてくれないので大変ですよね.
でも大丈夫! 全部読まなくてもオッケー!
独学なので間違っているかもしれませんが,基本的には部分的に見れば問題ないと思っています.
データシート
実際に見ていきましょう. MPU-6050のデータシート
まず,6~8ページのレジスタマップの大事な部分を見ていきます.
レジスタマップから上の3枚を抜き出しました.
基本的にはこの部分しか操作しないと思って大丈夫です.
順に見ていきましょう.
初期化
初めに,MPU-6050を使うにあたって,初期化と初期設定のようなものを行います.
そのため,プログラム上ではレジスタに書き込む操作をします.
こちらは先ほどの写真です.
PWR_MGMTはpower manegementの略です.
PWR_MGMT_1のBit7に1を書き込むとデバイスがリセットされます.10000000→0x80
また,CLKSELでクロック周波数を8MHzに決定します.0→0x00
次に6Aレジスタを設定します.Bit2,Bit1,Bit0にそれぞれ1を書き込むことで,各種のリセットができます.111→0x07
先ほどと同じように0x00をまた書き込みます.
ここまでのプログラムが以下で表せます.
bus.write_byte_data(DEV_ADDR, 0x6B, 0x80) # RESET
bus.write_byte_data(DEV_ADDR, 0x6B, 0x00) # RESET
bus.write_byte_data(DEV_ADDR, 0x6A, 0x07) # RESET
bus.write_byte_data(DEV_ADDR, 0x6A, 0x00) # RESET
初期設定(加速度とジャイロ)
続いて,ジャイロセンサーと加速度センサーのレンジ設定を行います.
こちらは先ほどの写真です.
CONFIGというのは設定を表しています.GYRO_CONFIGのページを見てみます.
ここでは,ジャイロセンサーの設定を行います.
GYRO_CONFIGは0x1Bレジスタで,Bit4とBit3に設定値を書き込むことで,尺度の設定ができます.
Full Scale Rangeが大きくすれば,測れる大きさが大きくなって量子化誤差が大きくなるワン!
逆にFull Scale Rangeが小さくすれば,測れる大きさが小さくなって精度が高く測定できるワン!
今回はFull Scale Rangeが±2000°/sに設定します.FS_SELが3つまり,2進数では11です.その下に0が3つ,11000を16進数に変換すると,0x18を書き込めばよいことになります.
bus.write_byte_data(DEV_ADDR, 0x1B, 0x18)
次は加速度の設定に移ります.
設定の仕方はジャイロと同じです.今回は±4gのスケールで使います.よってAFS_SELに01,つまり,0x08をレジスタに書き込みます.
単位換算
センサーから受け取った数値を,それぞれ単位に換算した値に変換します.
加速度は±4gの設定にしたので,1g[m/s^2]あたり8192という値を持っています.
よって,8192でセンサー値を割ることで,値が1に対して1g[m/s^2]になります.
ジャイロは±2000°/sに設定したので,16.4でセンサー値を割ることで,値1が1°/sを表します.
温度の値は,上の式で°cに合わせることができます.
配線
I2C通信でセンサーと通信するので,信号線2本と電源線2本をつなぎます.
配線後,ターミナルで以下のコマンドを入力してください.
$ sudo i2cdetect -y 1
このように,センサーのアドレス値が返ってきたら,正しくつなげています.
CSVファイルに出力
file = open("accel_data.csv", "w")
この文でファイルを書き込み用のcsvファイルとして指定します.
file.write()関数で,書き込みたい値を文字列で入力します.
最後にfile.close()関数を忘れずに書きます.(with as を使えば書く必要はないです)
エクセルで可視化
実際に上のプログラムを,走りながら 実行してみました.
なかなかいいデータを得ることができました.
ジャイロよりも加速度の方が周期性がありそうです.
今回の測定ではZ軸を体の軸と同じにして測定したので,走っているときは重力の3~4倍の加速度が足にかかることが分かりました.
まとめ
今回はRaspberry piで家にあったMPU-6050を用いて,エクセルで加速度とジャイロの可視化を行ってみました.
今回の方法は他の物でも色々と応用できそうです.
ではまた!!
・データシートの読み方
・配線
・CSVファイルに出力して,Excellで可視化