MPU6050(6軸センサー)をArduino経由で使ってみました。
MPU6050の使い方を中心に、下の動画に使用したArduino側スケッチ(ソース)説明を備忘録として纏めておきます。
動作確認
Processingを使用してリアルタイムで描画してます。なるべくシンプルで高速な処理をしたかったのでライブラリは使用しないでソース書いてます。(あまり変わらないかな?i2c通信はwire.hライブラリ仕様してます)今回はちゃんと3軸ベクトル計算したためyaw軸(z軸)回転もきちんと再現できてます。
MPU6050のセットアップ
void set_up_MPU6050() { Wire.beginTransmission(0x68); Wire.write(0x6B); Wire.write(0x00); Wire.endTransmission(); //Gyro初期設定 Wire.beginTransmission(0x68); Wire.write(0x1B); Wire.write(0x08); Wire.endTransmission(); //加速度センサー初期設定 Wire.beginTransmission(0x68); Wire.write(0x1C); Wire.write(0x10); Wire.endTransmission(); //LPF設定 Wire.beginTransmission(0x68); Wire.write(0x1A); Wire.write(0x03); Wire.endTransmission(); }
▲セットアップ例です。
最初に[0x68]よりデバイスを初期化というか起動します。
▼データシートより[0x6B]Register▼
次にジャイロの初期設定。[0x1B]レジスタのbit4、bit3の2bitでジャイロのスケールレンジが設定できます。
▼レジスタ▼
▼またレンジによるLSB(スケールファクター)は▼
角速度へ変換するときに必要な数値です。例ではレンジ:500deg/s、SF:65.5LSB/(deg/s)で設定してます。
次に加速度センサーの初期設定。[0x1C]レジスタのbit4、bit3の2bitで加速度センサーのスケールレンジが設定できます。
▼レジスタ▼
▼LSB(スケールファクター)▼
今回はレンジ:±8G、SF:4096LSB/Gで設定してます。
最後にローパスフィルターの設定です。ローパスフィルターの設定もできるのですね。[0x1A]レジスタの下位3bitで設定できます。
▼レジスタ▼
フィルター関係は難しくてよく理解できていないんですけどね・・。1次のローパスフィルターは大きくとると波形(値)が鈍って、遅れるという認識です。私の場合はセンサーに乗る高周波ノイズの除去にソフトで実装してたりします。今回は≒43Hzに設定してます。
これで初期設定は完了。続いて値の読み出しです。
センサー値の読み出し
void readMPU6050() { Wire.beginTransmission(0x68); Wire.write(0x3B); Wire.endTransmission(); Wire.requestFrom(0x68, 14); while (Wire.available() < 14); axRaw = Wire.read() << 8 | Wire.read(); ayRaw = Wire.read() << 8 | Wire.read(); azRaw = Wire.read() << 8 | Wire.read(); temperatureRaw = Wire.read() << 8 | Wire.read(); gxRaw = Wire.read() << 8 | Wire.read(); gyRaw = Wire.read() << 8 | Wire.read(); gzRaw = Wire.read() << 8 | Wire.read(); }
加速度センサー(3軸)、デバイス温度、ジャイロ(3軸)の値を取り出します。検出値はそれぞれ16bit(2byte)の長さで、レジスタアドレス[0x3B]から順に14byteで格納されてます。
ですので[0x3B]から14byte分のデータを要求。読みだした値を8bitずつ順に結合していけば生データの読み出し完了です。生データのままでは32767~-32768(2byte)のデータとなるためそれぞれ加速度、温度、角速度へ変換します。
今回は割愛しますが、取得した値をキャリブレーションして、加速度、角速度へ変換、姿勢角計算して、ドリフト補正して、、、とすると記事冒頭のような3軸の傾きを表現できるようになります。ここら辺は要望があるようなら別途紹介したいと思います。
ソース全体
MPU6050から取得した生値をそのままシリアル出力しているスケッチです。
// 2017/10/14 imo lab. // https://garchiving.com/ #include <Wire.h> int16_t axRaw, ayRaw, azRaw, gxRaw, gyRaw, gzRaw, temperature; void setup() { Serial.begin(9600); Wire.setClock(400000); Wire.begin(); Wire.beginTransmission(0x68); Wire.write(0x6B); Wire.write(0x00); Wire.endTransmission(); Wire.beginTransmission(0x68); Wire.write(0x1C); Wire.write(0x10); Wire.endTransmission(); Wire.beginTransmission(0x68); Wire.write(0x1B); Wire.write(0x08); Wire.endTransmission(); Wire.beginTransmission(0x68); Wire.write(0x1A); Wire.write(0x05); Wire.endTransmission(); } void loop() { Wire.beginTransmission(0x68); Wire.write(0x3B); Wire.endTransmission(); Wire.requestFrom(0x68, 14); while (Wire.available() < 14); axRaw = Wire.read() << 8 | Wire.read(); ayRaw = Wire.read() << 8 | Wire.read(); azRaw = Wire.read() << 8 | Wire.read(); temperature = Wire.read() << 8 | Wire.read(); gxRaw = Wire.read() << 8 | Wire.read(); gyRaw = Wire.read() << 8 | Wire.read(); gzRaw = Wire.read() << 8 | Wire.read(); Serial.print(axRaw); Serial.print(","); Serial.print(ayRaw); Serial.print(","); Serial.print(azRaw); Serial.print(","); Serial.print(gxRaw); Serial.print(","); Serial.print(gyRaw); Serial.print(","); Serial.println(gzRaw); }
コメント
MPU6050の勉強をしています。
GithubのJeff Rowbergのスケッチはちょっと長すぎるのでこのブログを
拝見して勉強しているのですが、可能であればスケッチの全文をブログ
に掲載、もしくはメールで教えて頂けないでしょうか。
匿名さん、こんにちは。コメント有難う御座います。
記事内容のままですが・・、MPU6050のセンサー値取得部ソースを記事にアップしておきました。
参考にして下さい。
ありがとうございます。早速試してみます。
無事にデータが取り出せました。ありがとうございます。
「ジャイロ(角速度)から角度の算出方法」も勉強中です。
> 今回は割愛しますが、取得した値をキャリブレーションして、加速度、角速度へ変換、姿勢角計算して、
>ドリフト補正して、、、とすると記事冒頭のような3軸の傾きを表現できるようになります。ここら辺は要望>があるようなら別途紹介したいと思います。
ぜひ教えてください。
無事にデータが取り出せたようですね。センサー値からの角度算出についてはこのサイトでもちらほら触れております。目的や使い方で考え方が様々かと思いますが一例をここである程度纏めてありますので一度ご確認下さい。
13pinがOUTPUTにされている理由が分かりません。
理由を教えていただきたいです。
13pinOUTPUTは何も使ってません(何かの名残かと思います)。無くても問題ないです。紛らわしいので記事からは消しておきました。指摘有難う御座います。
とても参考になりました。
Z軸(Yaw)の角度を算出したいのですがうまくいきません。まだ、高校生で知識と学力が全然ないのであの複雑な計算式を見ても何もわかりませんでした。プログラムの技術も未熟なので何も進まず困っています。
”今回は割愛しますが、取得した値をキャリブレーションして、加速度、角速度へ変換、姿勢角計算して、ドリフト補正して、、、とすると記事冒頭のような3軸の傾きを表現できるようになります。ここら辺は要望があるようなら別途紹介したいと思います。”
ここを教えていただきたいです。ソース全体を見せていただくことはできないでしょうか?
転載などは一切しません。よろしくお願いします。
とある高校生さん、サイト拝見頂き難うございます。
ご質問のz軸(yaw)の角度ですが、6軸センサー(ジャイロ、加速度)からでは算出は非常に困難です。
比較的短い時間の相対的な角度変化であれば算出可能ですが、絶対角度を出すのは恐らくできないかと・・。
別途、地磁気センサーなどで向き(角度)を確認する必要があります。
ソース全体についてはここでは難しいので、差支えなければコメント投稿時に記載いただいたメアドに送付しますがいかがでしょうか?
返信ありがとうございます。
Z軸(yaw)の角度算出はやはり厳しいのですね。X,Y軸の角度算出であれば可能なのでしょうか?(z軸が望ましいですが、X,Y軸でも角度算出が出来ればいいです。)
メールにソース全体を送って頂けるととても嬉しいです!
loop内の5行目”while (Wire.available() < 14);"について質問です。
これはアドレス"0x3B"~"0x48"までのデータが抜けている状態を想定し、全てのデータ(14byte)が埋まるまで待機するという意味でしょうか?
1つ(1byte)欠けていれば、"available"は13を返すとの認識です。
匿名さん、サイト拝見下さり有難うございます。概ねその認識でOKかと思います。14byte 読み取り可能になるまで待ってます。
ただもし万一、何かの問題で正常動作が行われず14byte読み取り可能にならない場合、無限ループに入ってしまうソースなので注意必要です。