STM32 + HAL でMPU-6500と通信する 

2019年7月24日

こんにちは。

STM32F405RGT(STMicroelectronics)のHALドライバを使用して、MPU6500(TDK Invensense)とSPI通信1を使用して通信をするプログラムの作成までを書いていきたいと思います。

データシートは一部抜粋で載せていくので、細かいところは各自データシートに目を通しながら進めていただければと思います。

 




通信について確認する

SPI通信で通信することは決まっていますが、通信規格や通信読度の設定がわからないので

プログラム・マイコンの初期設定をする前に、MPU6500のデータシートを読んでいきたいと思います。

まずは、SPI通信の書き込み、読み込みのできる最高速度、MSB2,LSB3のどちらからデータが返ってくるかということを見ていきたいと思います。

MPU-6500Product SpecificationRevision 1.1より

MPU-6500Product SpecificationRevision 1.1よりMPU-6500Product SpecificationRevision 1.1より

データシートから読み取れたことは、

  • 書き込み、読み込みの速度の最大は1±10%MHz
  • 読み込み専用の時は20±10%MHzまで可能ということがわかりました。
  • データはMSB FirstでLSB last
  • 一回の通信が16クロックのサイクル。
  • アドレスを送った後にデータを送る(読み取る)ことができる4
  • アドレスフォートマットの最上位ビットが1/0でREAD/WRITEが設定できる。
  • 通信をするときはcsPinをLowにする。

これで、マイコンの設定の仕方がわかりました。

 

STM32CubeMxの設定

STM32CubeMxを開いて、使用するマイコン、ボードを検索してプロジェクトを作成しましょう。冒頭で述べた通り、今回のサンプルはstm32f405rgt + makefileでやっていきます。

SPI通信と、ターミナルに文字列の表示を行いたいのでSPIとUSARTを有効、SPI通信のCSピン用に1ポートGPIO OUTPUTに設定し、ラベルをgyro_csとしました。

STM32CubeMx SPI通信の設定

20197/24日 追記: MPU6500では CPHL : High, CPHA : 2 Edgeに設定をする必要があります。データシートを読んでいたらわかりました。

STM32CuveMx USARTの設定

Project Managerの設定で、それぞれのペリフェラルの.c,.hファイルを生成するというところのチェックボックスにチェックを入れてください。そうすることでペリフェラルごとにファイルが分かれるのでプログラムが見やすくなると思います。

Generateボタンを押してファイルを生成してもらいましょう。

 

Visual studio code を実行して、makefile,Inc,Srcなどのディレクトリに移動します。

ファイル→フォルダを開くから移動が可能です。

“Ctr + Shift + p”でターミナルを開き、bashでmakeと実行するとコンパイルができると思います。

 

通信の内容を確認する

今回は、ジャイロのz軸を2000deg/secで読むプログラムを書きたいと考えています。

それを踏まえて、データを読むまでの流れは次のようになりました。

  1. WHO_AM_Iを読み取る。
  2. 1.でちゃんとデータが読めているか確認する
  3. パワーをオンにする
  4. mpu6500のコンフィグを設定する
  5. ジャイロの取得スケールの設定をする
  6. 値を取得する

しかし、MPU6500のどのアドレスに対して書き込みや読み込みをすればいいのかわからないのでデータシートを見ていきたいと思います。

前回同様最低限必要だと思ったところのMPU6500のレジスタマップが書いてあるデータシートを抜粋して見ていきます。説明がないところはデータシート各自読んでください。

1. WHO_AM_I : 0x75 に対して、read_byteする。

2. 読み取った値が0x70ならOK

3. PWR_MGMT_1 : 0x6Bにwrite_byteする。

MPU-6500Register Map and DescriptionsRevision 2.1より

データシートより、0x00を設定すれば、20Mhzで動作をするようになるので、0x00を設定しました。

4. CONFIG : 0x1Aにwrite_byteする。

MPU-6500Register Map and DescriptionsRevision 2.1より

私がチェックする回路ではFSYNC pinはNCなので、これらの機能を使用しません。

そのため、0x00を書き込みます5

5. GYRO_CONFIG : 0x1Bにwrite_byteする

MPU-6500Register Map and DescriptionsRevision 2.1より

2000dpsで取得するために、0x18を書き込みました。

6. z軸のデータは16bitで上位ビットと下位ビットに分かれているので、アクセスをしなければならないアドレスは2つあります。

    GYRO_ZOUT_H : 0x47 , GYRO_ZOUT_H : 0x48
上位ビットを8bitシフトをして、下位ビットと結合すれば値が取れそうだということがわかりました。
また、dpsでは物理量ではないため、deg/secに変換する必要があります。

データシートより、2000dpsのときは16.4で1deg/secであることがわかりました。したがって、取得した値を16.4で割ってあげればdeg/secに変換できるということが読み取れます。

ソースコードを実装

SPI通信のread,write関数を実装する

通信の条件は、

  • 8bitずつでアドレスを送ったのちに書き込みデータまたは、データ読み込みをすればいい。
  • 書き込みの場合はアドレスの最上位ビットを0。読み込みの場合は最上位ビットを1にする。
  • 通信するときはcsピンをLowにする。

ということがわかっているのでこれをもとに実装していきます。

20197/24日 追記: read,write関数の変更。readByte,WriteByteどちらかの初回動作時に正常に動かないことがある。そのため、起動時にwho_am_iをダミーリードするとよさそう。2回目以降はミスがありませんでした。

 

MPU-6500の読み込み書き込みのプログラム

通信内容を確認するを踏まえて実装すると次のようになりました。

 

これで、値の取得ができるようになりました。

プログラム全体

今回実装したプログラムをまとめたものになります。

 

さいごに

mpu6500は色々と設定できるようなのでデータシートを読んでやってみてください。

マイクロマウス競技では、センサの値を一定周期で取得、読み取った値の初期のオフセットがあるのが嫌なので、ソフトでできるだけオフセットがなくなるように対策をしています。

また、加速度を取得して衝突検知などもしています。

是非考えてみてください。

知見のある方で何かありましたらご指摘をしていただきたいです。

 

参考文献

UM1725 User Manual

MPU-6500Product SpecificationRevision 1.1

MPU-6500Register Map and DescriptionsRevision 2.1

 

  1. Serial Peripheral Interface : 同期式シリアル通信のひとつ
  2. Most Significant Bit : 最上位ビット
  3. least Significant Bit : 最下位ビット
  4. マイコン側からみたとき
  5. 初期数値が0x00ですが念のため設定をしています。