2019年12月25日水曜日

AE-BMX055とESP-WROOM-02の接続

ESP-WROOM-02"BMX055使用9軸センサーモジュール"を接続して動作検証してみたいと思います。対象としてはNodeMCUやESP32でも大きな違いはありません。

まずは、AE-BMX055のジャンパ設定。

AE-BMX055のジャンパ設定

  • ESP-WROOM-02の電圧は3.3Vなので、JP7をショート。
  • JP4JP5をショートしてプルアップ抵抗を有効化。
  • JP1JP2JP3を全てのジャンパをショートしてGNDに接続する事で、各センサーのアドレスは以下のようになります。
    • ジャイロセンサ : 0x68
    • 加速度センサ : 0x18
    • 地磁気センサ : 0x10
    これは、BMX055のデータシートのデフォルト設定に準拠したもので、任意のアドレスに設定して問題ありません。

AE-BMX055の配線

事前に、AE-BMX055とESP-WROOM-02で使用するピンを確認。
AE-BMX055 ESP-WROOM-02
Pin# Name Pin# Name
1 GND 9, 13, 18 GND
2 SDA 10 IO4
3 SCL 14 IO5
4 3V3 1 3V3
5 VCCIO
6 VCC 1 3V3
ブレッドボードを使って配線してみます。
※ESP-WROOM-02の配線は、ESP-WROOM-02のATモードでWiFI接続を参照。
ESP-WROOOM-02とESP8266 Arduino CoreのI2Cでは、標準で、
SCLは、IO4
SCLは、IO5
とアサインされているので、それに従って配線します。

動作検証には、"BMX055使用9軸センサーモジュール"のリンク先にあるArduinoサンプルプログラムを使用。

ただし、ESP-WROOM-02を含む32ビットマイコンではint型(整数型)が4バイトで扱われるため、short型(整数型)を使用して2バイトになるように修正しています。
この対応を行わないと正常に値が表示されません。
BMX055_SAMPLE
//================================================================//
//  AE-BMX055             ESP-WROOM-02                            //
//    VCC                    +3.3V                                //
//    GND                    GND                                  //
//    SDA                    IO4(SDA)                             //
//    SCL                    IO5(SCL)                             //
//                                                                //
//   (JP6,JP4,JP5はショートした状態)                                 //
//   http://akizukidenshi.com/catalog/g/gK-13010/                 //
//================================================================//

#include <Wire.h>
// BMX055 加速度センサのI2Cアドレス
#define Addr_Accl 0x18  // (JP1,JP2,JP3 = Closeの時)
// BMX055 ジャイロセンサのI2Cアドレス
#define Addr_Gyro 0x68  // (JP1,JP2,JP3 = Closeの時)
// BMX055 磁気センサのI2Cアドレス
#define Addr_Mag  0x10  // (JP1,JP2,JP3 = Closeの時)

// センサーの値を保存するグローバル関数
float xAccl = 0.00;
float yAccl = 0.00;
float zAccl = 0.00;
float xGyro = 0.00;
float yGyro = 0.00;
float zGyro = 0.00;
short int xMag  = 0.00;
short int yMag  = 0.00;
short int zMag  = 0.00;

void setup()
{
  // Wire(Arduino-I2C)の初期化
  Wire.begin();
  // デバック用シリアル通信は9600bps
  Serial.begin(9600);
  // BMX055 初期化
  BMX055_Init();
  delay(300);
}

void loop()
{
  Serial.println("--------------------------------------"); 

  //BMX055 加速度の読み取り
  BMX055_Accl();
  Serial.print("Accl= ");
  Serial.print(xAccl);
  Serial.print(",");
  Serial.print(yAccl);
  Serial.print(",");
  Serial.print(zAccl);
  Serial.println(""); 

  //BMX055 ジャイロの読み取り
  BMX055_Gyro();
  Serial.print("Gyro= ");
  Serial.print(xGyro);
  Serial.print(",");
  Serial.print(yGyro);
  Serial.print(",");
  Serial.print(zGyro);
  Serial.println(""); 

  //BMX055 磁気の読み取り
  BMX055_Mag();
  Serial.print("Mag= ");
  Serial.print(xMag);
  Serial.print(",");
  Serial.print(yMag);
  Serial.print(",");
  Serial.print(zMag);
  Serial.println(""); 
  
  delay(1000);
}

//=====================================================================================//
void BMX055_Init()
{
  //------------------------------------------------------------//
  Wire.beginTransmission(Addr_Accl);
  Wire.write(0x0F);  // PMU_Rangeレジスタを選択
  Wire.write(0x03);  // 範囲 = +/- 2g
  Wire.endTransmission();
  delay(100);
 //------------------------------------------------------------//
  Wire.beginTransmission(Addr_Accl);
  Wire.write(0x10);  // PMU_BWレジスタを選択
  Wire.write(0x08);  // 帯域幅 = 7.81 Hz
  Wire.endTransmission();
  delay(100);
  //------------------------------------------------------------//
  Wire.beginTransmission(Addr_Accl);
  Wire.write(0x11);  // PMU_LPWレジスタを選択
  Wire.write(0x00);  // 通常モード、スリープ時間 = 0.5ミリ秒
  Wire.endTransmission();
  delay(100);
 //------------------------------------------------------------//
  Wire.beginTransmission(Addr_Gyro);
  Wire.write(0x0F);  // Rangeレジスタを選択
  Wire.write(0x04);  // フルスケール= +/- 125度/秒
  Wire.endTransmission();
  delay(100);
 //------------------------------------------------------------//
  Wire.beginTransmission(Addr_Gyro);
  Wire.write(0x10);  // Bandwidthレジスタを選択
  Wire.write(0x07);  // ODR = 100 Hz
  Wire.endTransmission();
  delay(100);
 //------------------------------------------------------------//
  Wire.beginTransmission(Addr_Gyro);
  Wire.write(0x11);  // LPM1レジスタを選択
  Wire.write(0x00);  // 通常モード、スリープ期間 = 2ms
  Wire.endTransmission();
  delay(100);
 //------------------------------------------------------------//
  Wire.beginTransmission(Addr_Mag);
  Wire.write(0x4B);  // Magレジスタを選択
  Wire.write(0x83);  // ソフトリセット
  Wire.endTransmission();
  delay(100);
  //------------------------------------------------------------//
  Wire.beginTransmission(Addr_Mag);
  Wire.write(0x4B);  // Magレジスタを選択
  Wire.write(0x01);  // ソフトリセット
  Wire.endTransmission();
  delay(100);
  //------------------------------------------------------------//
  Wire.beginTransmission(Addr_Mag);
  Wire.write(0x4C);  // Magレジスタを選択
  Wire.write(0x00);  // 通常モード、ODR = 10 Hz
  Wire.endTransmission();
 //------------------------------------------------------------//
  Wire.beginTransmission(Addr_Mag);
  Wire.write(0x4E);  // Magレジスタを選択
  Wire.write(0x84);  // X、Y、Z軸が有効
  Wire.endTransmission();
 //------------------------------------------------------------//
  Wire.beginTransmission(Addr_Mag);
  Wire.write(0x51);  // Magレジスタを選択
  Wire.write(0x04);  // X-Y軸の繰り返し数 = 9
  Wire.endTransmission();
 //------------------------------------------------------------//
  Wire.beginTransmission(Addr_Mag);
  Wire.write(0x52);  // Magレジスタを選択
  Wire.write(0x16);  // Z軸の繰り返し数 = 15
  Wire.endTransmission();
}
//=====================================================================================//
void BMX055_Accl()
{
  int data[6];
  for (int i = 0; i < 6; i++)
  {
    Wire.beginTransmission(Addr_Accl);
    Wire.write((2 + i));            // データレジスタを選択
    Wire.endTransmission();
    Wire.requestFrom(Addr_Accl, 1); // 1バイトのデータをリクエスト
    // 6バイトのデータを読み取る
    // xAccl lsb, xAccl msb, yAccl lsb, yAccl msb, zAccl lsb, zAccl msb
    if (Wire.available() == 1)
      data[i] = Wire.read();
  }
  // データを12ビットに変換します
  xAccl = ((data[1] * 256) + (data[0] & 0xF0)) / 16;
  if (xAccl > 2047)  xAccl -= 4096;
  yAccl = ((data[3] * 256) + (data[2] & 0xF0)) / 16;
  if (yAccl > 2047)  yAccl -= 4096;
  zAccl = ((data[5] * 256) + (data[4] & 0xF0)) / 16;
  if (zAccl > 2047)  zAccl -= 4096;
  xAccl = xAccl * 0.0098; // renge +-2g
  yAccl = yAccl * 0.0098; // renge +-2g
  zAccl = zAccl * 0.0098; // renge +-2g
}
//=====================================================================================//
void BMX055_Gyro()
{
  int data[6];
  for (int i = 0; i < 6; i++)
  {
    Wire.beginTransmission(Addr_Gyro);
    Wire.write((2 + i));            // データレジスタを選択
    Wire.endTransmission();
    Wire.requestFrom(Addr_Gyro, 1); // 1バイトのデータをリクエスト
    // 6バイトのデータを読み取る
    // xGyro lsb, xGyro msb, yGyro lsb, yGyro msb, zGyro lsb, zGyro msb
    if (Wire.available() == 1)
      data[i] = Wire.read();
  }
  // Convert the data
  xGyro = (data[1] * 256) + data[0];
  if (xGyro > 32767)  xGyro -= 65536;
  yGyro = (data[3] * 256) + data[2];
  if (yGyro > 32767)  yGyro -= 65536;
  zGyro = (data[5] * 256) + data[4];
  if (zGyro > 32767)  zGyro -= 65536;

  xGyro = xGyro * 0.0038; //  Full scale = +/- 125 degree/s
  yGyro = yGyro * 0.0038; //  Full scale = +/- 125 degree/s
  zGyro = zGyro * 0.0038; //  Full scale = +/- 125 degree/s
}
//=====================================================================================//
void BMX055_Mag()
{
  int data[8];
  for (int i = 0; i < 8; i++)
  {
    Wire.beginTransmission(Addr_Mag);
    Wire.write((0x42 + i));        // データレジスタを選択
    Wire.endTransmission();
    Wire.requestFrom(Addr_Mag, 1); // 1バイトのデータをリクエスト
    // 6バイトのデータを読み取る
    // xMag lsb, xMag msb, yMag lsb, yMag msb, zMag lsb, zMag msb
    if (Wire.available() == 1)
      data[i] = Wire.read();
  }
  // Convert the data
  xMag = ((data[1] <<8) | (data[0]>>3));
  if (xMag > 4095)  xMag -= 8192;
  yMag = ((data[3] <<8) | (data[2]>>3));
  if (yMag > 4095)  yMag -= 8192;
  zMag = ((data[5] <<8) | (data[4]>>3));
  if (zMag > 16383)  zMag -= 32768;
}
あとは、上のスケッチをArduino IDEにコピペして書き込めば完了。

で、実行結果。
--------------------------------------
Accl= -0.36,-0.99,10.05
Gyro= -0.18,-0.09,-0.01
Mag= -758,-999,-487
--------------------------------------
Accl= -0.37,-0.99,10.05
Gyro= -0.13,0.13,0.00
Mag= -759,-995,-487
--------------------------------------
Accl= -0.37,-1.01,10.04
Gyro= -0.09,0.05,-0.13
Mag= -760,-997,-487
--------------------------------------
Accl= -0.37,-0.99,10.04
Gyro= -0.05,-0.09,0.02
Mag= -759,-997,-487
--------------------------------------
Accl= -0.37,-1.00,10.04
Gyro= -0.10,0.06,0.01
Mag= -759,-998,-487
値は取得出来たものの適正な値なのかどうかは不明ですが、とりあえず使用されているWireライブラリの関数を確認。

I2C(Wire library)

#include <Wire.h>
Wire libraryは現在、約450KHzまでのマスターモードをサポートしています。I2Cを使用する前に、Wire.begin(int sda, int scl)を呼び出して、SDAおよびSCLのピンを設定する必要があります。※ ESP-01では、Wire.begin(0, 2)と設定されており、それ以外ではWire.begin(4, 5)が標準で設定されています。

Wire.begin()

説明

Wireライブラリを開始し、マスターまたはスレーブとしてI2Cバスに接続します。通常、これは一度だけ呼び出す必要があります。

構文

Wire.begin()
Wire.begin(address)

パラメータ

address 7-bitのスレーブアドレス(オプション)。無指定の場合、マスターとしてバスに接続。

Wire.beginTransmission()

説明

指定されたアドレスでI2Cスレーブデバイスへの送信を開始します。続いて、write()関数で送信するバイトをキューに入れ、endTransmission()を呼び出して送信します。

構文

WiFi.beginTransmission(address)

パラメータ

address 送信先のデバイスの7-bitアドレス

Wire.write()

説明

マスターからの要求に応答してスレーブデバイスからデータを書き込むか、またはマスターからスレーブデバイスへの送信用にバイトをキューイングします(beginTransmission()とendTransmission()の間で呼び出します)。

構文

Wire.write(value)
Wire.write(string)
Wire.write(data, length)

パラメータ

value  シングルバイトとして送信する値
string  一連のバイトとして送信する文字列
data  バイトとして送信するデータの配列
length  送信するバイト数

Wire.endTransmission()

説明

beginTransmission()によって開始されたスレーブデバイスへの送信を終了し、write()によってキューに入れられたバイトを送信します。

Arduino 1.0.1以降、endTransmission()は、特定のI2Cデバイスとの互換性のために動作を変更するブール引数を受け入れます。

trueの場合、endTransmission()は送信後に停止メッセージを送信し、I2Cバスを解放します。

falseの場合、endTransmission()は送信後に再起動メッセージを送信します。バスは解放されないため、メッセージ間で別のマスターデバイスが送信できなくなります。これにより、1つのマスターデバイスが制御中に複数の送信を送信できます。

デフォルト値はtrueです。

構文

WiFi. endTransmission()
WiFi.endTransmission(stop)

パラメータ

stop  boolean
  • true 停止メッセージを送信し、送信後にバスを解放します。
  • false 再起動を送信し、接続をアクティブに保ちます。

戻り値

送信のステータスを示すバイト:
  1. 成功
  2. データが長すぎて送信バッファに収まらない
  3. アドレスの送信時にNACKを受信しました
  4. データの送信時にNACKを受信しました
  5. その他のエラー

Wire.requestFrom()

説明

マスターがスレーブデバイスからバイトを要求するために使用します。その後、バイトはavailable()およびread()関数を使用して取得できます。

Arduino 1.0.1の時点で、requestFrom()は特定のI2Cデバイスとの互換性のために動作を変更するブール引数を受け入れます。

trueの場合、requestFrom()は要求の後に停止メッセージを送信し、I2Cバスを解放します。

falseの場合、requestFrom()はリクエストの後に再起動メッセージを送信します。バスは解放されないため、別のマスターデバイスがメッセージ間で要求することはできません。これにより、1つのマスターデバイスが制御中に複数の要求を送信できます。

デフォルト値はtrueです。

構文

WiFi.requestFrom(address,quantity)
WiFi.requestFrom(address,quantity,stop)

パラメータ

address バイトを要求するデバイスの7ビットアドレス
quantity 要求するバイト数
stop  boolean
  • true リクエストの後に停止メッセージを送信します。
  • false リクエスト後に継続的に再起動が送信され、接続がアクティブになります。

戻り値

byte  スレーブデバイスから返されたバイト数

Wire.available()

説明

read()で取得できるバイト数を返します。これは、requestFrom()の呼び出し後のマスターデバイスまたはonReceive()ハンドラー内のスレーブで呼び出す必要があります。

available()は、Streamユーティリティクラスを継承します。

構文

WiFi.available()

パラメータ

なし

戻り値

読み取りに使用できるバイト数

Wire.read()

説明

requestFrom()の呼び出し後にスレーブデバイスからマスターに送信されたバイト、またはマスターからスレーブに送信されたバイトを読み取ります。read()は、Streamユーティリティクラスを継承します。

構文

WiFi.read()

パラメータ

なし

戻り値

受信した次のバイト
以上となります。

正直、繋がった!値が出た!ってだけの状態なので、その辺りをデータシートとサンプルスケッチを眺めつつ調査したいと思います。
次回ですけどね。

0 件のコメント:

コメントを投稿