2017年7月29日土曜日

ArduinoでMPU9250(加速度センサ、磁気センサ)を使う方法


欲しい値を取得するのに思っていたよりも時間がかかったので、メモを残します。

目的

9軸センサ MPU9250で加速度と磁気を取得したい。

使ったもの

Arduino


aliexpressで買いました。
秋月電子でも買えます。
今回はNANOを使いましたが、ProMicroもお勧めです。

MPU9250


9軸センサモジュールです。
加速度と角速度が取れる6軸線センサMPU6500と、3軸磁気センサAK8963が合体したモジュールです。
amazonスイッチサイエンスaliexpressなどで買えます。

ブレッドボード


部品を配置するのに使いました。
秋月電子やスイッチサイエンスなど、電子部品取扱店で買えます。

ジャンパワイヤ


部品を配線するのに使いました。
秋月電子やスイッチサイエンスなど、電子部品取扱店で買えます。

PC + ArduinoIDE

Arduinoのプログラムと、値の確認に使いました。
ArduinoIDEは下記のページからダウンロードできます。

Download the Arduino IDE

配線

このように配線しました。

Arduino (Nano) MPU9250
5V VCC
SDA(A4) SDA
SCL(A5) SCL
GND GND


NanoやUno以外のArduinoを使う場合、I2Cに割り当てられているピンが異なる場合があるので、wireライブラリの説明ページでピンを確認してください。

ライブラリの準備

使いやすそうなライブラリが見当たらなかったので、自分が最低限欲しい情報だけ取り出すライブラリを作りました。


ArduinoIDEのライブラリマネージャーを使ってインストールできます。


9250とかで検索すると出てくると思います。


実行

ライブラリをインストールできたらサンプルプログラムが使えるので、それを開いてArduinoに書き込みます。
File -> Examples -> MPU9250_asukiaaa -> getData


シリアルモニタを115200bpsで開くと、値を確認できます。


自分の磁気センサはXが最大110、最低10、Yが最大120、最低20位だったので、Xに対して-60、Yに対して-70のoffsetを設定すると、水平方向の磁気がそれっぽく取れるようになりました。
mySensor.magXOffset = -60;
mySensor.magYOffset = -70;

モジュールによってふさわしいoffsetの値は多分異なると思うので、複数のハードに対して同じプログラムを動かしたい場合は、offsetの値をNANDメモリなどに値を書き込んで実行時に読みだすなどの仕組みが必要になりそうです。

まとめ

Arduinoで加速度センサと磁気センサの出力を取得できました。
磁気センサの値はoffsetでそれらしい値に補正できましたが、別のMPU9250モジュールを利用する場合はoffsetの値を変える必要があるので、プログラムを使い回すときは注意が必要そうです。

共有する情報は以上です。

参考

AK8963
SparkFun_MPU-9250
jrowberg/i2cdevlib/Arduino/AK8963

12 件のコメント :

  1. はじめまして、マイコン初心者の者です。
    ESP32-DevKitC のマイコンと 私も同じMPU9250 センサーを買いました。
    MPU9250_asukiaaa のライブラリを使わせていただいています。ありがとうございます。
    Arduino 1.8.5 IDEで コードを送ったのですが、 センサーのデータが取得できませんでした。
    これはやっぱり ESP32-DevKitC は別の製品だからでしょうか?

    もし、よろしければ、どの部分をどのように変更すればデータが取得できるかヒントを教えていただけないでしょうか?
    よろしくお願いいたします。

    返信削除
    返信
    1. 自分もESP32の開発基板でMPU9250の値を取得したことがあるので、多分動くと思いますよ。
      動かない原因としては、下記の点が気になります。

      - SDA、SCLピンの指定が合っているか
      - setWireでi2c接続に必要なWireをライブラリに渡しているか
      - MPU9250が動いているか


      # SDA、SCLピンの指定が合っているか
      ESP32はいくつかのピンをI2Cに割り当てられますが、フォーラムの情報によると、34-39は入力だけなので、それ以外のピンを割り当てる必要があるようです。
      Wire.beginに渡す第一引数がSDA、第二引数がSCLです。

      Wire.begin(26, 25);


      # setWireでi2c接続に必要なWireをライブラリに渡しているか
      自分の作ったライブラリは、i2cに必要なクラスを渡す仕組みになっています。
      下記のような記述で、Wireを設定できていますか?

      mySensor.setWire(&Wire);


      # MPU9250が動いているか
      MPU9250が動いていないとライブラリは使えません。
      こちらこちらのプログラムを利用して、I2Cデバイスのスキャンをして、MPU9250が動いていることを確認してみるのはいかがでしょう?
      その場合も回路に合わせてSDA, SCLのピンを合わせる必要があります。
      これでも動作を確認できない場合、お使いのMPU9250モジュールが壊れている可能性があります。


      いかがでしょう?
      お役に立てれば嬉しいです。

      削除
  2. asuki さん

    動きました!数値でました!!本当にありがとうございます!!連絡が遅くなってしまい申し訳ありません。
    先日、丸一日やってうまくいかなくて本当に苦労しました。おかげさまで一発でうまく行きまして本当に感謝です。
    また、貴サイトで勉強させていただきます。すごく親切に教えていただきまして、ありがとうございました。

    返信削除
    返信
    1. 期待通りに動いたようで良かったです。
      他の記事も何かの参考になれば嬉しいです。

      削除
  3. 初めまして。すぐ、実験できとてもよいライブラリです。助かりました。
    設定を自分で細かくしたいと思い、頑張ってみたのですが、スレーブアドレスが0x68以外見つかりません(本当はak8963のアドレス0x0Cもほしい)。mpu9250側で何か設定しないといけないのでしょうか?

    返信削除
    返信
    1. AK8963を使う場合は、beginMag関数(ソースコード参照)で行っているように、MPU9250に対してAK8963を起動させるための信号を送る必要があります。
      サンプルプログラムでmagXなどの磁気センサに関する情報が取得できているのであれば、起動のための信号を送ればAK8963は動くと思います。
      上記のサンプルプログラムの出力は、どのようになっていますか?

      削除
    2. MPU9250の0x37に0x02を送ったところ、解決しました。お騒がせしました。すみません。

      削除
    3. 解決されたようで良かったです。
      謝罪されると罪悪感を感じるので。謝罪よりも感謝していただける方が、個人的に嬉しいです。

      削除
    4. 丁寧な返信とてもありがたいです。
      現在、電磁石の磁界を調べることを目的に実験しているのですが、その前段階として、センサーの感度調整をしたいのですが、地磁気ベクトルのノルムは一定であるはずなのですが、一定でないのはどのように調整するとよいと思いますか?
      固定につかう、ねじ自体にも磁性が多少あったりするので、オフセットと感度両方を調整する方法を考えあぐねています。

      削除
    5. 磁石を近づけて大きく変動させた後(オーバーフローはさせない程度)、磁石を離すと元のデータとは違う値で安定するのですが(650->600みたいに)どう思いますか?

      削除
    6. Mpu9250のxyzの表示方向とak8963のレジスタxyzによる方向が違う気がします。xとyが逆だと、磁石をちかづけて最も変化した軸を見たところ感じたのですが、どう思いますか?

      削除
    7. 情報共有ありがとうございます。

      > 磁石を近づけて大きく変動させた後、磁石を離すと元のデータとは違う値で安定する

      こういうことが起こるのですか、知りませんでした。
      温度によっても適切なオフセット値が変わるように思うので、変になったら補正し直すのが一つの解決策でしょうか。

      > Mpu9250のxyzの表示方向とak8963のレジスタxyzによる方向が違う気がします。xとyが逆だと、磁石をちかづけて最も変化した軸を見たところ感じたのですが、どう思いますか?

      自分も磁石を近づけて試してみたところ、加速度の軸に磁気センサの軸合わせるには、下記のような変換が必要そうな動きをしていました。
      y = -x
      x = -y
      z = -z

      しかし、プログラムを見直しても、MPU9250のレジスタマップ(PDF)のHXL to HZH: Measurement Dataに沿って値は取得できているように見えます。
      (AK8963_RA_HXL(0x03)から7バイト取得し、先頭からそれぞれ、XのLow,XのHigh,YのLow,YのHigh,ZのLow,ZのHighに利用。)

      自分の把握していない軸の違いがあるのかもしれませんが、何が正しいのかは、今のところよく分かりません。

      値を取得した後、使いたい軸の向きに合わせて独自に変数を定義して、それにセンサの値を保持して使ってもらうのが、今の所の解決策のように思います。

      削除