ArduinoでBMX055モジュールのデータを取得する

組み込みエンジニア
本記事はプロモーションが含まれています。

こんにちは、ENGかぴです。

BMX055はBOSCH社製の9軸(加速度3軸、ジャイロ3軸、磁気3軸)を搭載したセンサーモジュールです。BMX055はI2Cに対応しているため、ArduinoのWireライブラリを使用することでセンサーの情報を取得することができます。

WireライブラリでBMX055から取得した加速度、ジャイロ、磁気のデータをOLED及びシリアルプロッタに表示して動作確認を行いました。

動作確認にはAE-BMX055(秋月電子)、OLEDは0.95インチ(HiLetgo製)を使用しています。Arduinoのライブラリを使用して動作確認したことをまとめています。

Arduinoで学べるマイコンのソフト開発と標準ライブラリの使い方

以下では、Arduino UNOをArduinoと表記します。

BMX055を使用する

AE-BMX055はBOSCH社のBMX055にレベル変換回路を追加してDIP6ピンで使用できるようにコンパクトに設計したモジュールです。AE-BMX055の詳細は下記リンクを参考にしてください。

BMX055使用9軸センサーモジュール: センサ一般 秋月電子通商-電子部品・ネット通販 (akizukidenshi.com)

6ピンの構成でINTピンがないためBMX055のINT設定に関するレジスタを操作しても使用することができません。各種センサーの測定条件に関するレジスタを初期化して使用します。レジスタ等の詳細はBMX055取扱説明書を参照してください。

広告
漠然としたキャリア形成の不安を打ち破る!

レジスタの初期化

加速度センサー、ジャイロセンサー、磁気センサーのレジスタの初期化を行います。デフォルト値から変更する内容についてまとめました。

  レジスタ     内容
0x0F(PMU_RANGE)加速度センサーのgレンジを指定する。
±2g(デフォルト)、±4g、±8g、±16gから指定する。
0x10(PMU_BW)フィルタのバンド幅(BW)を指定する。BW=ODR/2を目安にBWを指定する。Normal Modeは10Hzなので7.81Hzを選択。
加速度センサーのレジスタの初期化
  レジスタ           内容
0x0F(RANGE)ジャイロセンサーの角速度のレンジを指定する。
±125°/s、±250°/s、±500°/s、±1000°/s、±2000°/sから指定する。
0x10(BW)サンプリングのODRお及びフィルタのバンド幅(BW)を指定する。ODRに対してデシメーション係数(間引き)やBWを指定します。ODRを高くするほど測定周期が短くなります。
ジャイロセンサーのレジスタの初期化
レジスタ内容
  0x4B         ソフトリセット(スリープ時)及びSPIモードを指定する。
2ビットのソフトリセットビットを同時に立てるとPORによりソフトリセットとなる。ソフトリセットはスリープモードで有効となるのでPower Control bitを1にしてソフトリセットする。
0x4C動作モードを指定します。ODRを10Hz、Normal Modeを選択。
磁気センサーのレジスタの初期化

基本的に測定のレンジと測定周期の設定を行うことで、測定データを取得できるため測定以外の機能を使用しない場合は他の設定は必要ありません。

データを換算する

加速度センサーの測定データは0x02~0x07レジスタを読み込むことで取得できます。2バイト分のデータから12ビットのデータを生成し換算すると加速度が取得できます。

//0x02~0x08までのデータを読み込む 0x08はtempデータ
Bmx055Read( ACCL_ADRS, 0x02, &accldata[0], sizeof(accldata));

accl_x= (accldata[1] << 4 ) + ( accldata[0] >> 4 );
if( accl_x > 0x7FF){ //12bitのMSBが符号ビット
  accl_x -= 0x1000;
}
accl.x = accl_x * range; //2gの場合はrange=0.00098

X軸のデータを算出する例で説明します。0x02(ACCD_X_LSB)レジスタの値をaccladata[0]、0x03(ACCD_X_MSB)レジスタの値をaccladata[1]に格納したものとします。

0x02レジスタはMSBからacc_x_lsb<3:0>が配置されているためaccladata[0]を右に4回シフトします。

0x03レジスタはMSBからacc_X_msb<11:8>、acc_X_msb<7:4>が配置されているためaccldata[1]を左に4回シフトします。

シフトした2つのデータを加算すると12ビットのデータになります。12ビットのデータのうち最上位ビットは符号ビットとなるため、符号付の11ビットの最大値である0x7FFを超えた場合0x1000を引くことで符号変換しています。

12ビットのデータに各レンジの値を乗算すると加速度のデータに換算することができます。

ジャイロセンサーの測定データは0x02~0x07レジスタを読み込むことで取得できます。2バイト分のデータを換算するとジャイロ(角速度)が取得できます。

//0x02~0x07までのデータを読み込む
Bmx055Read( GYRO_ADRS, 0x02, &gyrdata[0], sizeof(gyrdata));

gyro_x= (gyrdata[1] << 8 ) + gyrdata[0];
gyro.x = gyro_x * range; //125 deg/sの場合はrange=0.0038

X軸のデータを算出する例で説明します。0x02(RATE_X_LSB)レジスタの値をgyrdata[0]、0x03(RATE_X_MSB)レジスタの値をgyrdata[1]に格納したものとします。

0x02レジスタはMSBからrate_x_lsb<7:4>及びrate_x_lsb<3:0>が配置されているためgyrdata[0]は下位の1バイトデータとしてそのまま使用できます。

0x03レジスタはMSBからrate_X_msb<15:12>、rate_X_msb<11:8>が配置されているためgyrdata[1]を左に8回シフトします。

2つのデータを加算すると16ビットのデータになります。16ビットのデータに各レンジの値を乗算すると角速度のデータに換算することができます。

磁気センサーの測定データは0x42~0x47レジスタを読み込むことで取得できます。2バイト分のデータから13ビットのデータを生成すると磁気が取得できます。

//0x42~0x47までのデータを読み込む  
Bmx055Read( MAG_ADRS, 0x42, &magdata[0], sizeof(magdata));

mag_x = (magdata[1] << 5 ) + (magdata[0] >> 3);
if( mag_x > 0xFFF){ //13bitのMSBが符号ビット
  mag_x -= 0x2000;
}
mag.x = mag_x;

X軸のデータを算出する例で説明します。0x42レジスタの値をmagdata[0]、0x03レジスタの値をmagdata[1]に格納したものとします。

0x42レジスタはMSBからDATAX_lsb<4:0>が配置されているためmagdata[0]を右に3回シフトします。

0x43レジスタはMSBからDATAX_msb<12:5>が配置されているためmagdata[1]を左に5回シフトします。

13ビットのデータのうち最上位ビットは符号ビットとなるため、符号付の13ビットの最大値である0xFFFを超えた場合0x2000を引くことで符号変換しています。

2つのデータを加算すると13ビットのデータになります。磁気のデータはレンジによる換算がないため、加算したデータが磁気のデータになります。

スポンサーリンク

Wireライブラリを使用する

Arduinoの標準ライブラリであるWireライブラリの使い方を説明します。Wire(I2C)の送信と受信を中心に説明しています。

Wireライブラリの初期化

#include <Wire.h>

void setup() {

  Wire.begin(); //begin()内にアドレスを入れるとスレーブになる
  //Wire.setClock(100000); //クロック周波数を設定する場合にセット初期は100kHz
}

Wire(I2C)を使用する場合はWire.hをインクルードします。begin()関数の引数の有無によってマスタで動作するかスレーブで動作するかが決まります。引数に指定した値でスレーブ動作を開始します。マスタとして使用するため引数は無しとします。

クロックは設定しなければ初期条件の100kHzで動作します。setClock()関数でクロックを指定する場合は通信誤差が大きくならないように注意する必要があります。

I2Cによる信号はプルアップ抵抗にも影響するためクロックを早く設定しすぎると波形がなまってしまうこともあるので特に意識せず100kHzで十分だと思います。

PR:RUNTEQ(ランテック )- 実践型Webエンジニア養成プログラミングスクール

Wire(I2C)の送信と実装例

Wireライブラリを使った送信の手順は以下の通りです。

  1. beginTransmission()関数で初期化とスレーブアドレスをセット
  2. write()関数で書き込み対象のアドレスをセット
  3. write()関数で書き込むデータをセット
  4. endTransmission()関数で送信

1~3まではデータの準備です。4のendTransmission()関数はスタート・コンディションの発行やコントロール・バイト(7ビットのスレーブアドレスを左詰めにして最下位ビットにWriteフラグ(0)をセット)の処理を行いデータを送信した(書き込んだ)後ストップ・コンディションの発行を行います。以下に実装例を示します。

/* Wireの書き込み */
void Bmx055Write(uint8_t adr, uint8_t reg, uint8_t data){

  Wire.beginTransmission(adr); //スレーブが存在するか確認
  int8_t error = Wire.endTransmission();

  if( error == 0){ //スレーブが存在する場合は以下を処理
    Wire.beginTransmission(adr);
    Wire.write(reg);
    Wire.write(data);
    Wire.endTransmission();
  }
}

Bmx055Write()関数はBMX055にデータを書き込む自作の関数です。第1引数にデバイス番号、第2引数にレジスタ、第3引数に書き込むデータを指定します。

最初にWireのメンバー関数のbeginTransmission()関数で初期化とスレーブアドレスをセットします。endTransmission()関数でアドレスを送信しスレーブが存在するか確認を行います。スレーブが存在する場合は戻り値が0になるためデータの書き込み処理に移ります。

スレーブに送信するデータを準備します。最初にbeginTransmission()関数で初期化とスレーブアドレスをセットします。次にwrite()関数でレジスタのアドレス、書き込むデータをセットします。

最後にendTransmission()関数でスタート・コンディションからストップ・コンディションまでを含めたデータを送信します。

PR:【CreatorsFactory】転職率96%!Webスクール説明会申し込み

Wire(I2C)の受信と実装例

Wireライブラリを使った受信の手順は以下の通りです。

  1. beginTransmission()関数で初期化とスレーブアドレスをセット
  2. write()関数で書き込み対象のアドレスをセット
  3. endTransmission()関数で送信
  4. requestFrom()関数で対象のアドレスのデータを取得する
  5. read()関数で取得したデータを読み込む

1~3まではスレーブアドレスに対して書き込み対象のアドレスを指定します。4のrequestFrom()関数はスタート・コンディションの発行やコントロール・バイト(7ビットのスレーブアドレスを左詰めにして最下位ビットにReadフラグ(1)をセット)の処理を行い指定した数のデータを取得し、ストップ・コンディションの発行を行います。

5は4で取得したデータを読み込みます。送信と異なる点はrequestFrom()でストップ・コンディションを発行するためendTransmission()の発行は必要ありません。以下に実装例を示します。

/* Wireの読み込み */
void Bmx055Read(uint8_t adr, uint8_t reg, uint8_t *data, uint8_t sz){

  Wire.beginTransmission(adr); //スレーブが存在するか確認
  int8_t error = Wire.endTransmission();

  if( error == 0){
    Wire.beginTransmission(adr);
    Wire.write(reg);
    Wire.endTransmission();
    Wire.requestFrom(adr, sz);
    for( uint8_t i=0; i < sz; i++ ){
      *data = Wire.read();
      ++data;
    }
  }
}

Bmx055Read()関数はBMX055のデータを読み込む自作の関数です。第1引数にデバイス番号、第2引数にレジスタ、第3引数に読み込んでデータを格納するアドレス、第4引数に読み込むデータ数を指定します。

最初にWireのメンバー関数のbeginTransmission()関数で初期化とスレーブアドレスをセットします。endTransmission()関数でアドレスを送信しスレーブが存在するか確認を行います。スレーブが存在する場合は戻り値が0になるためデータの受信処理に移ります。

データの受信はレジスタを選択した状態にするため、beginTransmission()関数で初期化とスレーブアドレスを指定しwrite()関数でレジスタを指定します。endTransmission()関数でデータを送信しレジスタを選択した状態にします。

データの受信はrequestFrom()関数で指定した数のデータを取得します。read()関数で取得したデータを読み込みます。

スポンサーリンク

OLEDライブラリを使用する

HiLetgo製の0.95インチ7ピン 65kカラー対応のOLEDディスプレイモジュールを使用しています。通信方式は3線のSPI通信を使用します。下記リンクにモジュールに関する情報が記載されています。

0.95″ Inch 7 Pin Colorful 65K SPI OLED Display Module

OLED用のドライバーICはSSD1331でありArduino環境に対応しているのでライブラリを追加して文字や記号を表示することができます。Arduino IDEでライブラリを追加して使用する方法を説明します。

Adafruit SSD1331 OLED Driverライブラリを追加する

Adafruit SSD1331 OLED Driver Library for Arduinoの追加
Adafruit SSD1331 OLED Driver Library for Arduinoの追加

Arduino IDEのライブラリマネージャの検索欄にssd1331を入力するとライブラリの候補が表示されます。候補の中から「Adafruit SSD1331 OLED Driver Library for Arduino」をインストールします。

インストールする際にライブラリの依存関係をインストールするかを尋ねられることがあります。ライブラリの依存関係が不足しているとうまく動作しないことがあるためすべてをインストールすることをお勧めします。

PR:技術系の通信教育講座ならJTEX

OLEDライブラリの使用例

#include <Adafruit_SSD1331.h>

#define cs   10 //チップセレクト
#define rst  9 //リセット
#define dc   8 //DATA COMMAND
#define	BLACK 0x0000

Adafruit_SSD1331 oled = Adafruit_SSD1331(&SPI, cs, dc, rst);

void setup() {
  oled.begin();
  oled.fillScreen(BLACK);
}

Adafruit_SSD1331.hをインクルードします。Adafruit_SSD1331クラスの変数としてoled(任意でよい)をインスタンス化します。第1引数にSPIクラスの変数のアドレスを指定します。Arduino環境ではSPIが標準で定義されているのでSPIを指定します。

第2引数にチップセレクトで使用するピン番号を指定します。

第3引数にData/Commandピン番号を指定します。SPI通信を3線で行うためData/Commandピンでデータの方向を選択して送受信します。

第4引数にRESピン番号を指定します。RESピンはHIGHにするとモジュールのリセットを解除します。LOWにするとリセット状態になります。

setup()内でAdafruit_SSD1331クラスのメンバー関数であるbegin()関数でOLEDの初期化を行います。fillScreen()関数は画面全体のカラーを指定した色で塗りつぶします。例ではBLACK(0x0000)0指定しています。色の指定は16bitデータ(0~65535の範囲)で行います。

oled.setTextSize(1); //5×7フォント
oled.setCursor(0, 5);
oled.setTextColor(RED); //テキストの色を指定
oled.print("ACCL:");
oled.setCursor(40, 5);
oled.print(accl.x);

setTextSize()関数でフォントの大きさを指定します。1を指定すると5×7のフォントになります。2以上を指定すると1のフォント基準に倍数したフォントになります。0を指定すると1と同じフォントになります。

setCursor()関数で文字表示する座標を指定します。第1引数にX座標、第2引数にY座標を指定します。座標はピン側を上に見た時OLEDの左上の座標が(X,Y)=(0,0)になります。

setTextColor()関数はテキストの色を指定します。16ビットの値で色を指定します。

print()関数で文字を書き込んで表示します。例ではACCL:を表示後カーソルを移動して加速度を文字列で出力しています。

スポンサーリンク

動作確認

動作確認用の回路図
動作確認用の回路図

AE-BMX055はJP6、JP4、JP5をジャンパーして使用しています。Wireを使用するためA4(SDA)、A5(SCL)に接続します。

OLEDはSPI通信を3線式で行うためArduinoのMISO(12ピン)は使用しません。MOSI(11ピン)で送信と受信をDCピンでデータとコマンドを切り替えながら通信を行います。RESピンはリセットを使用しない場合はHIGHに固定しても問題ありません。CSピンはLアクティブとなるのでモジュールを常に使用する場合はLOWに固定しても問題ありません。

OLEDの結果(1段目 X軸 2段目 Y軸 Z軸)
OLEDの結果(1段目 X軸 2段目 Y軸 Z軸)

電源を入れるとOLEDにBMX055から取得したデータを表示します。磁石のN極をX軸側に近づけているためMAG: 2094になっています。また重力加速度がZ軸方向にかかっているため0.98になっています。

次にBMX055を動かした測定値の様子をシリアルプロッタでグラフ表示して確認しました。

シリアルプロッタの結果(加速度)
シリアルプロッタの結果(加速度)

加速度はBMX055を各軸方向に向きを変えて測定しました。シリアルプロッタに表示すると向きによってY軸が-1.0、Z軸が1.0、X軸が1.0、X軸が-1.0など重力加速度に対応した値になっていることが確認できました。

シリアルプロッタの結果(ジャイロ)
シリアルプロッタの結果(ジャイロ)

ジャイロはBMX055の各軸を基準に回転させて測定しました。シリアルプロッタに表示すると回転軸に応じて測定値が変化していることが確認できました。また角速度が最大である125°(レンジの設定で125°/sにしている)で頭打ちになっていることも確認できました。

シリアルプロッタの結果(磁気)
シリアルプロッタの結果(磁気)

磁気はデータをX軸、Y軸、Z軸に対しては磁石のN極とS局の向きを変えたり磁石を近づけたり遠ざけたりして測定を行いました。シリアルプロッタに表示すると磁石の向きや距離によって値が増減することが確認できました。磁石の強度を確認する手段がないため値の変化のみの確認になりました。

広告

ソースコード全体

以下のソースコードはコンパイルして動作確認をしております。コメントなど細かな部分で間違っていたりやライブラリの更新などにより動作しなくなったりする可能性があります。参考としてお使いいただければと思います。

#include <MsTimer2.h>
#include <Wire.h>
#include <Adafruit_SSD1331.h>

#define ACC_PLOT
//#define GYRO_PLOT
//#define MAG_PLOT

#define ACCL_ADRS 0x19
#define GYRO_ADRS 0x69
#define MAG_ADRS 0x13

#define ACCL_RANGE_2 0x03
#define ACCL_RANGE_4 0x05
#define ACCL_RANGE_8 0x08
#define ACCL_RANGE_16 0x0C

#define GYRO_RANGE_2000 0x00 //2000 deg/s
#define GYRO_RANGE_1000 0x01 //1000 deg/s
#define GYRO_RANGE_500 0x02 //500 deg/s
#define GYRO_RANGE_250 0x03 //250 deg/s
#define GYRO_RANGE_125 0x04 //125 deg/s

#define TIME_UP 0
#define TIME_OFF -1
#define TIME_MEASURE 50

// Color definitions
#define	BLACK           0x0000
#define	BLUE            0x001F
#define	RED             0xF800
#define	GREEN           0x07E0
#define CYAN            0x07FF
#define MAGENTA         0xF81F
#define YELLOW          0xFFE0
#define WHITE           0xFFFF

#define CS   10
#define RST  9
#define DC   8

struct ACCL_TYP{
  float x;
  float y;
  float z;
  float temp;
};

struct GYRO_TYP{
  float x;
  float y;
  float z;
};

struct MAG_TYP{
  int16_t x;
  int16_t y;
  int16_t z;
  uint16_t hall;
};

ACCL_TYP accl;
GYRO_TYP gyro;
MAG_TYP mag;
int16_t timMeasure;
uint8_t accldata[7];
uint8_t gyrdata[6];
uint8_t magdata[8];
uint8_t acclrange;
uint8_t gyrorange;
Adafruit_SSD1331 oled = Adafruit_SSD1331(&SPI, CS, DC, RST);

/* Local function prototypes */
void mainTimer(void);
void mainApp(void);
void Bmx055Init(void);
void Bmx055Init_accl(void);
void Bmx055Init_gyro(void);
void Bmx055Init_mag(void);
void Bmx055Write(uint8_t adr, uint8_t reg, uint8_t data);
void Bmx055Read(uint8_t adr, uint8_t reg, uint8_t *data, uint8_t sz);
void AcclMeasure(void);
void GyroMeasure(void);
void MagMeasure(void);
void OledShow(void);

void setup() {
  
  Wire.begin();
  Serial.begin(9600);
  Bmx055Init();

  oled.begin();
  oled.fillScreen(BLACK);
  MsTimer2::set(10, mainTimer); // 10ms period
  MsTimer2::start();
}

void loop() {
  mainApp();
}
/* メイン処理 */
void mainApp(void){

  if( timMeasure == TIME_UP ){
    timMeasure = TIME_MEASURE;
    AcclMeasure();
    GyroMeasure();
    MagMeasure();
    OledShow();
  }
}
/* 加速度測定 */
void AcclMeasure(void){
  int16_t accl_x;
  int16_t accl_y;
  int16_t accl_z;
  float range;
  float temp;
  
  //0x02~0x08までのデータを読み込む 0x08はtempデータ
  Bmx055Read( ACCL_ADRS, 0x02, &accldata[0], sizeof(accldata));

  accl_x= (accldata[1] << 4 ) + ( accldata[0] >> 4 );
  if( accl_x > 0x7FF){ //12bitのMSBが符号ビット
    accl_x -= 0x1000;
  }

  accl_y= (accldata[3] << 4 ) + ( accldata[2] >> 4 );
  if( accl_y > 0x7FF){ //12bitのMSBが符号ビット
    accl_y -= 0x1000;
  }

  accl_z= (accldata[5] << 4 ) + ( accldata[4] >> 4 );
  if( accl_z > 0x7FF){ //12bitのMSBが符号ビット
    accl_z -= 0x1000;
  }

  switch(acclrange){
    case ACCL_RANGE_2: 
      range = 0.00098; // range = +/-2g
      break;
    case ACCL_RANGE_4:
      range = 0.0019; // range = +/-4g
      break;
    case ACCL_RANGE_8:
      range = 0.0039; // range = +/-8g
      break;
    case ACCL_RANGE_16:
      range = 0.0078; // range = +/-16g
      break;
    default:
      range = 0;
  }

  accl.x = accl_x * range;
  accl.y = accl_y * range;
  accl.z = accl_z * range;
  accl.temp = (float)accldata[6] * 0.5 +23;
 
#ifdef ACC_PLOT
  Serial.print("X:");
  Serial.print(accl.x);
  Serial.print(",");
  Serial.print("Y:");
  Serial.print(accl.y);
  Serial.print(",");
  Serial.print("Z:");
  Serial.print(accl.z);
  //Serial.print(",");
  //Serial.print(accl.temp);
  Serial.println(""); 
#endif  
}
/* ジャイロの測定 */
void GyroMeasure(void){
  int16_t gyro_x;
  int16_t gyro_y;
  int16_t gyro_z;
  float range;

  Bmx055Read( GYRO_ADRS, 0x02, &gyrdata[0], sizeof(gyrdata));

  gyro_x= (gyrdata[1] << 8 ) + gyrdata[0];
  gyro_y= (gyrdata[3] << 8 ) + gyrdata[2];
  gyro_z= (gyrdata[5] << 8 ) + gyrdata[4];

  switch(gyrorange){
    case GYRO_RANGE_2000: 
      range = 0.061; //range = +/-2000 deg/s
      break;
    case GYRO_RANGE_1000:
      range = 0.0305; //range = +/-1000 deg/s
      break;
    case GYRO_RANGE_500:
      range = 0.0153; //range = +/-500 deg/s
      break;
    case GYRO_RANGE_250:
      range = 0.0076; //range = +/-250 deg/s
      break;
    case GYRO_RANGE_125:
      range = 0.0038; //range = +/-125 deg/s
      break;
    default:
      range = 0;
  }

  gyro.x = gyro_x * range;
  gyro.y = gyro_y * range;
  gyro.z = gyro_z * range;

#ifdef GYRO_PLOT
  Serial.print("X:");
  Serial.print(gyro.x);
  Serial.print(",");
  Serial.print("Y:");
  Serial.print(gyro.y);
  Serial.print(",");
  Serial.print("Z:");
  Serial.print(gyro.z);
  Serial.println(""); 
#endif
}
/* マグネット測定 */
void MagMeasure(void){
  int16_t mag_x;
  int16_t mag_y;
  int16_t mag_z;
  uint16_t hall;

  Bmx055Read( MAG_ADRS, 0x42, &magdata[0], sizeof(magdata));

  mag_x = (magdata[1] << 5 ) + (magdata[0] >> 3);
  if( mag_x > 0xFFF){ //13bitのMSBが符号ビット
    mag_x -= 0x2000;
  }

  mag_y = (magdata[3] << 5 ) + (magdata[2] >> 3);
  if( mag_y > 0xFFF){ //13bitのMSBが符号ビット
    mag_y -= 0x2000;
  }

  mag_z = ((int16_t)magdata[5] << 7 ) + ((int16_t)magdata[4] >> 1);
  if( mag_z > 0x3FFF){ //15bitのMSBが符号ビット
    mag_z -= 0x8000;
  }

  hall = ((uint16_t)magdata[7] << 6 ) + ((uint16_t)magdata[6] >> 2);

  mag.x = mag_x;
  mag.y = mag_y;
  mag.z = mag_z;

 #ifdef MAG_PLOT
  Serial.print("X:");
  Serial.print(mag_x);
  Serial.print(",");
  Serial.print("Y:");
  Serial.print(mag_y);
  Serial.print(",");
  Serial.print("Z:");
  Serial.print(mag_z);
  //Serial.print(",");
  //Serial.print(hall);  
  Serial.println("");
#endif
  Bmx055Init_mag(); //途中で停止してしまう対策
}
/* タイマ管理 */
void mainTimer(void){

  if( timMeasure > TIME_UP ){
    --timMeasure;
  }

}
/* Wireの書き込み */
void Bmx055Write(uint8_t adr, uint8_t reg, uint8_t data){

  Wire.beginTransmission(adr); //スレーブが存在するか確認
  int8_t error = Wire.endTransmission();

  if( error == 0){
    Wire.beginTransmission(adr);
    Wire.write(reg);
    Wire.write(data);
    Wire.endTransmission();
  }
}
/* Wireの読み込み */
void Bmx055Read(uint8_t adr, uint8_t reg, uint8_t *data, uint8_t sz){

  Wire.beginTransmission(adr); //スレーブが存在するか確認
  int8_t error = Wire.endTransmission();

  if( error == 0){
    Wire.beginTransmission(adr);
    Wire.write(reg);
    Wire.endTransmission();
    Wire.requestFrom(adr, sz);
    for( uint8_t i=0; i < sz; i++ ){
      *data = Wire.read();
      ++data;
    }
  }
}
/* 各センサー初期化 */
void Bmx055Init(void){

  Bmx055Init_accl();
  Bmx055Init_gyro();
  Bmx055Init_mag();
}
/* 加速度センサーの初期化 */
void Bmx055Init_accl(void){

  acclrange = ACCL_RANGE_2;
  Bmx055Write(ACCL_ADRS, 0x0F, acclrange ); //ACC Register 0x0F PMU_RANGE 2g
  Bmx055Write(ACCL_ADRS, 0x10, 0x08 ); //ACC Register 0x10 PMU_BW
  //Bmx055Write(ACCL_ADRS, 0x11, 0x00 ); //ACC Register 0x11 PMU_LPW
}
/* ジャイロセンサーの初期化 */
void Bmx055Init_gyro(void){
  gyrorange = GYRO_RANGE_125;
  Bmx055Write(GYRO_ADRS, 0x0F, gyrorange); //GYR Register 0x0F RANGE 125deg/s
  Bmx055Write(GYRO_ADRS, 0x10, 0x07); //GYR Register 0x10 BW ODR 100Hz BW 32Hz
  //Bmx055Write(GYRO_ADRS, 0x11, 0x00); //GYR Register 0x11 LPM1 NORMAL
}
/* マグネットセンサーの初期化 */
void Bmx055Init_mag(void){
  Bmx055Write(MAG_ADRS, 0x4B, 0x83); //MAG Register 0x4B リセット
  Bmx055Write(MAG_ADRS, 0x4B, 0x01); //MAG Register 0x4B mode切替
  Bmx055Write(MAG_ADRS, 0x4C, 0x00); //MAG ODR 10Hz
  //Bmx055Write(MAG_ADRS, 0x4E, 0x84); //MAG Register 0x4C X, Y, Z-Axis enabled
  //Bmx055Write(MAG_ADRS, 0x51, 0x10); //MAG Register 0x51 xy繰り返し
  //Bmx055Write(MAG_ADRS, 0x52, 0x10); //MAG Register 0x52 z繰り返し
}
/* OLED表示*/
void OledShow(void){
  
  oled.fillScreen(BLACK);
  oled.setTextSize(1);
  oled.setCursor(0, 5);
  oled.setTextColor(RED);
  oled.print("ACCL:");
  oled.setCursor(40, 5);
  oled.print(accl.x); 
  oled.setCursor(5, 15);
  oled.print(accl.y);
  oled.setCursor(40, 15);
  oled.print(accl.z);

  oled.setCursor(0, 25);
  oled.setTextColor(BLUE);
  oled.print("GYRO:");
  oled.setCursor(40, 25);
  oled.print(gyro.x); 
  oled.setCursor(5, 35);
  oled.print(gyro.y);
  oled.setCursor(40, 35);
  oled.print(gyro.z);

  oled.setCursor(0, 45);
  oled.setTextColor(GREEN);
  oled.print("MAG:");
  oled.setCursor(40, 45);
  oled.print(mag.x); 
  oled.setCursor(5, 55);
  oled.print(mag.y);
  oled.setCursor(40, 55);
  oled.print(mag.z);
}

磁気センサーは加速度やジャイロセンサーの動作確認を行っている途中で動作停止することがありました。対策としてデータを読み込んだ後でソフトリセットしています。

関連リンク

Arduinoのライブラリを使って動作確認を行ったことを下記リンクにまとめています。

Arduinoで学べるマイコンのソフト開発と標準ライブラリの使い方

Seeeduino XIAOで学べるソフト開発と標準ライブラリの使い方

ESP32-WROOM-32Eで学べるソフト開発と標準ライブラリの使い方

PR:テックジム:プログラミングの「書けるが先で、理解が後」を体験しよう!

最後まで、読んでいただきありがとうございました。

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