Arduino 入門 Lesson 32 【6軸モーションセンサ編 その2】

arduino-lesson32-00 Arduino入門編
記事に広告(アフィリエイト広告)が含まれています。
スポンサーリンク
子供と一緒に始める マイコンプログラム
Arduino 入門
Lesson 32
【6軸モーションセンサ編 その2】

「Arduino」を使ったマイコンプログラミングを子供と一緒に学習するブログ。

少しずつ、子供と一緒に楽しみながら気長にアップしてく予定です。

 

本記事はLesson 32 【6軸モーションセンサ編 その2】です。

Lesson 31では、とりあえず動かしてデータを取得して遊びました。

 

そのため、スケッチの記述内容がなんでそうなるのか?

という説明は省略しています。

 

本Lessonでは、スケッチ内で設定しているMPU6050のレジスタについてレジスタマップと照らし合わせて解説していきます。

これで、スケッチで何をしているのか少し理解が進むはず。

 

本Lessonでは安価なMPU-6050(GY-521)の6軸モーションセンサを使用しています。

 

学習、遊び、試行用途であれば、お手頃な値段。

Amazon購入の場合、複数個購入しても1000円以下で購入可能です。

 

Arduino入門編の解説にて使用しているArduinoは互換品です。

互換品とは言え、Arduinoはオープンソースであり複製して販売するのもライセンス的に問題なし。

そのため互換品の品質も悪くなく、それでいて値段は安いです。

正規品本体の値段程度で豊富な部品が多数ついています。

正規品(Arduino UNO R3)の本体単品がほしい方はこちらとなります。

 

Arduino入門編2では「Arduino UNO R4 Minima」「Arduino UNO R4 WIFI」にて遊ぶため今のところは正規品を使用。(まだ互換品が・・・ほぼない)

 

 

スポンサーリンク

はじめに

レジスタマップ内に記載されているレジスタ設定について確認していきます。

そのため、MPU-6050のレジスタマップを確認する必要があります。。

Lesson 31で紹介した、下記サイトでレジスタマップを確認することが可能です。

MPU-6050 | TDK InvenSense
NOT RECOMMENDED FOR NEW DESIGNS MPU-6050 Six-Axis (Gyro + Accelerometer) MEMS MotionTracking™ Devices   The MPU-6050™ pa…

にアクセスしましたらページ中央当たりに下記があります。

MPU-6000 and MPU-6050 Register Maps and Descriptions

ファイルはPDFファイルです。

 

Lesson 32 目標

本Lessonの目標は以下です。

スケッチ内で使用しているMPU-6050(GY-521)のレジスタ設定を理解する。

本Lessonで、レジスタマップのどこに記載されているかを確認しましょう。

 

コード確認の前に

通信にはI2C通信を使用します。

I2C通信に関しては、以下で解説していますので確認しておくことをおすすめします。

本Lessonでは解説は省略します。

 

コードの確認

さっそく、コードを確認していきましょう。

下記はLesson 31で使用したスケッチとなります。

下記スケッチをレジスタマップと突き合せて確認していきます。

//Lesson 31-1 6軸モーションセンサ
//3軸ジャイロスコープ・3軸加速度センサ モジュール
//ジャイロセンサで検知したデータをシリアルモニタに表示
//https://omoroya.com/

// 電子部品
// MPU-0650使用のGY-521基板

//ライブラリインクルード
#include <Wire.h>

void setup() {
  Serial.begin(115200); //シリアル通信のデータ転送レートを設定しポート開放
  Serial.println("--- Started ---");
  
  Wire.begin();         //I2C通信開始
  // センサ開始動作
  Wire.beginTransmission(0x68); //アドレス0x68指定でMPU-6050を選択、送信処理開始
  Wire.write(0x6B);             //MPU6050_PWR_MGMT_1レジスタのアドレス指定
  Wire.write(0x00);             //0を書き込むことでセンサ動作開始
  Wire.endTransmission();       //スレーブデバイスに対する送信を完了
  
}

void loop() {
  // スタートアドレスの設定とデータの要求処理
  Wire.beginTransmission(0x68);     //アドレス0x68指定でMPU-6050を選択、送信処理開始
  Wire.write(0x3B);                 //ACCEL_XOUT_Hレジスタのアドレス指定
  Wire.endTransmission(false);      //false設定で接続維持
  Wire.requestFrom(0x68, 14, true); //MPU-6050に対して14byte分データを要求、I2Cバス開放
  
  int16_t ax, ay, az, gx, gy, gz, Temp; //符号付き整数を格納する16ビットの変数型の設定

  //シフト演算と論理和で16bitのデータを変数に格納
  //ax~gzまで、16bit(2byte) × 7 = 14byte
  ax = Wire.read() << 8 | Wire.read();    //x軸の加速度の読み取り 16bit
  ay = Wire.read() << 8 | Wire.read();    //y軸の加速度の読み取り 16bit
  az = Wire.read() << 8 | Wire.read();    //z軸の加速度の読み取り 16bit
  Temp  = Wire.read() << 8 | Wire.read(); //温度の読み取り 16bit
  gx = Wire.read() << 8 | Wire.read();    //x軸の角速度の読み取り 16bit
  gy = Wire.read() << 8 | Wire.read();    //y軸の角速度の読み取り 16bit
  gz = Wire.read() << 8 | Wire.read();    //z軸の角速度の読み取り 16bit

  //データの表示 1LSBの値はデータシートに記載
  //AFS_SEL設定 = 0, ±2g, 16384LSB/g
  //FS_SEL設定  = 0, ±250deg/s, 131LSB/deg/s 
  Serial.print(ax/16384.0); Serial.print(" g,  ");     //1LSBを加速度(G)に換算してシリアルモニタに表示
  Serial.print(ay/16384.0); Serial.print(" g,  ");     //1LSBを加速度(G)に換算してシリアルモニタに表示
  Serial.print(az/16384.0); Serial.print(" g,  ");     //1LSBを加速度(G)に換算してシリアルモニタに表示
  Serial.print(gx/131.0); Serial.print(" deg/s,  ");   //1LSBを角速度(deg/s)に換算してシリアルモニタに表示
  Serial.print(gy/131.0); Serial.print(" deg/s,  ");   //1LSBを角速度(deg/s)に換算してシリアルモニタに表示
  Serial.print(gz/131.0); Serial.println(" deg/s,  "); //1LSBを角速度(deg/s)に換算してシリアルモニタに表示
  //Serial.print(Temp/340.00+36.53); Serial.println(" deg.");    //温度換算シリアルモニタに表示

  delay(20);
}

 

センサ開始動作

スケッチ内のセンサ開始動作について確認していきます。

スケッチ内では以下のコードの部分が該当箇所となります。

Wire.begin(); //I2C通信開始
// センサ開始動作
Wire.beginTransmission(0x68); //アドレス0x68指定でMPU-6050を選択、送信処理開始
Wire.write(0x6B);             //MPU6050_PWR_MGMT_1レジスタのアドレス指定
Wire.write(0x00);             //0を書き込むことでセンサ動作開始
Wire.endTransmission();       //スレーブデバイスに対する送信を完了

 int16_t ax, ay, az, gx, gy, gz, Temp; //符号付き整数を格納する16ビットの変数型の設定

 

1つ1つ解説していきます。

Wire.begin();
I2C用の制御関数を使えるようにするための記述です。

 

Wire.beginTransmission(0x68);
対象のI2Cデバイスに接続しています。
0x68」はこのデバイスのアドレスとなります。

レジスタの0x75番地にデバイスアドレスが格納されていて読み出して確認することも可能です。

WHO_AM_Iレジスタ(0x75)
arduino-lesson32-01

 

上記レジスタの説明には、以下と記載されています。

  • このレジスタがデバイスのidentityを確認するために使用されること
  • このレジスタのデフォルト値が「0x68」であること
  • 最下位ビットはAD0の状態で決定されること

ここでLesson 31を思い出してください。

AD0はどうしていたか?

そう、このピンはGY-521基板上で4.7kΩでプルダウンされているのです。

最下位bitは0ということですね。

よって、デフォルト値に変更はなくMPU-6050のデバイスアドレスは「0x68」

実際に、レジスタ内容を確認したいかたはレジスタ値を読み出して確認してみてください。

 

Wire.write(0x6B);
1つ目のwrite関数で「レジスタのアドレス」を指定しています。
0x6B」はPWR_MGMT_1レジスタです。

PWR_MGMT_1レジスタ(0x6B)へ書き込みしますよってことです。

 

Wire.write(0x00);
2つ目のwrite関数で「指定したレジスタにデータを格納」。
PWR_MGMT_1レジスタを「0x00」にするということ。

PWR_MGMT_1レジスタ(0x6B)
arduino-lesson32-02

上記レジスタの説明には、以下と記載されています。

代表的な内容だけ抜粋。

  • 電力モードとクロックの設定
  • デバイスのリセット、温度センサの無効化するためのbitあり
  • 電力スリープモードの設定
  • 供給するクロックの選択

このレジスタでにデータを送信し上記の設定をするということです。

 

「0x00」をレジスタに書き込むということは、上位4bitが0000、下位4bitが0000となります。

上位4bitは0000としているので特に機能を使用していません。

下位4bitの0000の設定は、上位ビットから考えると・・・

0:温度センサ enable(1設定でdisable)

000:3bitを使用してクロックを選択します。

選択できるクロックが以下となります。

arduino-lesson32-03

000は10進数で0ですから、「Internal 8MHz oscillator」を選択していることになります。

 

Wire.endTransmission();
スレーブデバイスに対する送信完了しています。

 

スタートアドレス設定とデータ要求処理

スタートアドレス設定とデータ要求処理について確認していきます。

スケッチ内では以下のコードの部分が該当箇所となります。

 // スタートアドレスの設定とデータの要求処理
  Wire.beginTransmission(0x68);     //アドレス0x68指定でMPU-6050を選択、送信処理開始
  Wire.write(0x3B);                 //ACCEL_XOUT_Hレジスタのアドレス指定
  Wire.endTransmission(false);      //false設定で接続維持
  Wire.requestFrom(0x68, 14, true); //MPU-6050に対して14byte分データを要求、I2Cバス開放

 

1つ1つ解説していきます。

Wire.beginTransmission(0x68);
対象のI2Cデバイスに接続しています。
0x68」はこのデバイスのアドレスとなります。

すでに解説済みですので省略します。

 

Wire.write(0x3B);
1つ目のwrite関数で「レジスタのアドレス」を指定しています。
0x3B」はACCEL_XOUT_H(x軸加速度データの上位バイト)が格納されているレジスタの番地となります。

ここで何をしているかというと

加速度センサ(3軸)、デバイス温度、ジィイロ(3軸)の値を取り出すための準備をしています。

センサの検出値はそれぞれ、16bit(2byte)で構成されています。
※1つのデータが2byteで構成されているということ。

レジスタの「0x3B」番地から順に全ての検出値を取得。

そのためには14byte読み出す必要があるということです。

1つのデータが2byteですから、14byte / 2byte = 7。

7つのデータ = 加速度3軸、デバイス温度、ジャイロ3軸

ということがわかります。

下記に示す3Bから順に48まで読み出したいので、読み出す先頭の番地を指定しているとお考え下さい。

arduino-lesson32-04

 

Wire.endTransmission(false);
アドレス指定とデータの読み込みを1つの通信をするための手法です。
デバイスとの接続を維持しつづけます。
※リピーテッド・スタート・コンディションと呼ばれる手法です。
Wire.requestFrom(0x68, 14, true);
0x68のデバイスの0x3Bアドレスから14byte分のデータを要求しています。

Wire.endTransmission()、Wire.requestForm()に引数を指定しているのが動作のミソとなります。

 

int16_t ax, ay, az, gx, gy, gz, Temp;
16bitの整数を格納するための宣言です。
1つのデータが2byte(16bit)だからです。

 

16bitのデータ読み込み処理

16bitデータの読み込み処理について解説します。

スケッチ内では以下のコードの部分が該当箇所となります。

  //シフト演算と論理和で16bitのデータを変数に格納
  //ax~gzまで、16bit(2byte) × 7 = 14byte
  ax = Wire.read() << 8 | Wire.read();    //x軸の加速度の読み取り 16bit
  ay = Wire.read() << 8 | Wire.read();    //y軸の加速度の読み取り 16bit
  az = Wire.read() << 8 | Wire.read();    //z軸の加速度の読み取り 16bit
  Temp  = Wire.read() << 8 | Wire.read(); //温度の読み取り 16bit
  gx = Wire.read() << 8 | Wire.read();    //x軸の角速度の読み取り 16bit
  gy = Wire.read() << 8 | Wire.read();    //y軸の角速度の読み取り 16bit
  gz = Wire.read() << 8 | Wire.read();    //z軸の角速度の読み取り 16bit

 

ax = Wire.read() << 8 | Wire.read();
検出するデータ長は16bitです。
しかし、I2C通信が1回で送ることができるデータは8bitとなります。
上記は、2回のI2C読み込み処理をすることで16bitのデータをaxに格納している処理となります。

Wire.read()でデータを読み取り、8bitシフトさせ、もう一度Wire.read()で読み取り16bit文のデータ長としています。

センサが検出する7つ分のデータを取得するために、同じ処理を、ay、az、Temp、gx、gy、gzでもしています。

 

シリアルモニタに表示

シリアルモニタ表示の処理となります。

スケッチ内では以下のコードの部分が該当箇所となります。

  //データの表示 1LSBの値はデータシートに記載
  //AFS_SEL設定 = 0, ±2g, 16384LSB/g
  //FS_SEL設定  = 0, ±250deg/s, 131LSB/deg/s 
  Serial.print(ax/16384.0); Serial.print(" g,  ");     //1LSBを加速度(G)に換算してシリアルモニタに表示
  Serial.print(ay/16384.0); Serial.print(" g,  ");     //1LSBを加速度(G)に換算してシリアルモニタに表示
  Serial.print(az/16384.0); Serial.print(" g,  ");     //1LSBを加速度(G)に換算してシリアルモニタに表示
  Serial.print(gx/131.0); Serial.print(" deg/s,  ");   //1LSBを角速度(deg/s)に換算してシリアルモニタに表示
  Serial.print(gy/131.0); Serial.print(" deg/s,  ");   //1LSBを角速度(deg/s)に換算してシリアルモニタに表示
  Serial.print(gz/131.0); Serial.println(" deg/s,  "); //1LSBを角速度(deg/s)に換算してシリアルモニタに表示
  //Serial.print(Temp/340.00+36.53); Serial.println(" deg.");    //温度換算シリアルモニタに表示

シリアルモニタへの表示に関しては、これまでも解説していますので省略します。

 

計算部分についてのみ解説します。

//AFS_SEL設定 = 0, ±2g, 16384LSB/g
//FS_SEL設定 = 0, ±250deg/s, 131LSB/deg/s
上記コメントにある値で計算することで、加速度(G)、角速度(deg/s)に変換しています。

上記は1LSBの値を示しています。

こちらもアドレスマップに記載されています。

arduino-lesson32-05

arduino-lesson32-06

 

arduino-lesson32-07

arduino-lesson32-08

 

Lessonで使用しているスケッチ内ではこのレジスタ設定値を変更していません。

そのため、0(10進数)の設定値が使われることになります。

 

まとめ

本Lessonはスケッチをより深く理解することを目標としました。

スケッチ内で使用しているMPU-6050(GY-521)のレジスタ設定を理解する。

 

レジスタマップを見ると、他にも設定できる項目がたくさんあります。

ノイズ除去のためにフィルター設定をおこなったりなど。

データシートとレジスタマップを読み込んで色々と試してみるのも良いと考えます。

 

Lesson 32 【6軸モーションセンサ編 その2】 はここまで。

本Lessonはでは、まず動かして検知したデータを読み取ってみました。

疑問点、質問などありましたら気軽にコメントください。

 

次回、Lesson 33も6軸モーションセンサを掘り下げる予定でしたが変更。

他にも色々なセンサーがあります。

違うセンサーで遊ぶことにしました。

Arduino 入門 Lesson 33 【リニアホールIC・磁気センサ】
世の中には、まだまだ色々なセンサーがあります。まだまだ色々なセンサーで遊んでいきます。Lesson 33は【リニアホールIC(磁気センサ)】。本Lessonで使用する「リニアホールIC」はアナログ・ホール磁気センサとも呼ばれます。使用するセ…

 

最後に

疑問点、質問などありましたら気軽にコメントください。

この電子部品の解説をしてほしい!などなどなんでもOKです。

リンク切れ、間違いなどあればコメントいただけると助かります。

 

Arduino入門編、番外編、お役立ち情報などなどサイトマップで記事一覧をぜひご確認ください。

 

Arduino入門編Arduino入門編2で使用しているUNOはAmazonにて購入可能です。

Arduino入門編では互換品を使用。

Arduinoはオープンソース。

複製して販売するのもライセンス的に問題なし。

 

そのため互換品の品質も悪くなく、それでいて値段は安いです。

正規品本体の値段程度で豊富な部品が多数ついています。

 

学習用、遊び用、お試し用には安価な互換品がおすすめです。

 

上記のものでも十分に多数の部品が入っていますが、最初からもっと多数の部品が入っているこちらもお勧めです。

 

Arduino入門編2では「Arduino UNO R4 Minima」「Arduino UNO R4 WIFI」にて遊ぶため今のところは正規品を使用。(まだ互換品が・・・ほぼない)

 

Amazonでお得に買う方法

Amazonでお得に購入するならAmazon MastercardAmazonギフト券がおすすめです。

時期により異なりますが、様々なキャンペーンを実施しています。

\Amazonギフト券/
Amazonギフトカード キャンペーン

Amazon Mastercard お申込み
Amazon Mastercard 申し込み 

 

いずれの場合もプライム会員である方がお得!!

\Amazon Prime 30日間の無料会員を試す/
無料会員登録 

 

 

コメント

タイトルとURLをコピーしました