AE-BMX055とESP-WROOM-02の接続の続き。
ですが、、、加速度センサのみに絞っての確認となります。
前回のスケッチから加速度センサの箇所のみを抜粋。
BMX055_ACCELEROMETER
#include
<Wire
.h>
// BMX055 加速度センサのI2Cアドレス
#define
Addr_Accl 0x18 // (JP1,JP2,JP3 = Closeの時)
// センサーの値を保存するグローバル関数
float
xAccl = 0.00;
float
yAccl = 0.00;
float
zAccl = 0.00;
void
setup()
{
// Wire(Arduino-I2C)の初期化
Wire
.begin
();
// デバック用シリアル通信は9600bps
Serial
.begin
(9600);
//BMX055 初期化
//------------------------------------------------------------//
Wire
.beginTransmission
(Addr_Accl);
Wire
.write
(0x0F); // PMU_Rangeレジスタを選択
Wire
.write
(0x03); // Range = +/- 2g
Wire
.endTransmission
();
delay
(100);
//------------------------------------------------------------//
Wire
.beginTransmission
(Addr_Accl);
Wire
.write
(0x10); // PMU_BWレジスタを選択
Wire
.write
(0x08); // Bandwidth = 7.81 Hz
Wire
.endTransmission
();
delay
(100);
//------------------------------------------------------------//
Wire
.beginTransmission
(Addr_Accl);
Wire
.write
(0x11); // PMU_LPWレジスタを選択
Wire
.write
(0x00); // Normal mode, Sleep duration = 0.5ms
Wire
.endTransmission
();
delay
(100);
}
void
loop()
{
Serial
.println
("--------------------------------------");
//BMX055 加速度の読み取り
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.00098; // renge +-2g
yAccl = yAccl * 0.00098; // renge +-2g
zAccl = zAccl * 0.00098; // renge +-2g
Serial
.print
("Accl= ");
Serial
.print
(xAccl);
Serial
.print
(",");
Serial
.print
(yAccl);
Serial
.print
(",");
Serial
.print
(zAccl);
Serial
.println
("");
delay
(1000);
}
以降では、スケッチ内で使用されているレジスタアドレスをピックアップして取り上げていきます。
BMX055レジスタへの書き込み
加速度センサーを初期化するためのレジスタアドレスと設定値です。
詳細はデータシートを参照。
ACC Register 0x0F (PMU_RANGE) Read/Write
このレジスタにより、加速度計の重力範囲を選択できます。
スケッチ内での設定値は0x03。
Bit |
Resolution |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
Content |
reserved |
range |
±2g range |
0.98mg/LSB |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
0x03 |
±4g range |
1.95mg/LSB |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
1 |
0x05 |
±8g range |
3.91mg/LSB |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
0 |
0x08 |
±16g range |
7.81mg/LSB |
0 |
0 |
0 |
0 |
1 |
1 |
0 |
0 |
0x12 |
0: 予約値 /
赤字: 起動時の初期値
ACC Register 0x10 (PMU_BW) Read/Write
このレジスタにより、加速データフィルタの帯域幅を選択できます。
スケッチ内での設定値は
0x08。
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
Content |
reserved |
bw |
7.81 Hz |
0 |
0 |
0 |
0 |
0 |
x |
x |
x |
0x00-0x07 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
0 |
0x08 |
15.63 Hz |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
1 |
0x09 |
31.25 Hz |
0 |
0 |
0 |
0 |
1 |
0 |
1 |
0 |
0x0A |
62.5 Hz |
0 |
0 |
0 |
0 |
1 |
0 |
1 |
1 |
0x0B |
125 Hz |
0 |
0 |
0 |
0 |
1 |
1 |
0 |
0 |
0x0C |
250 Hz |
0 |
0 |
0 |
0 |
1 |
1 |
0 |
1 |
0x0D |
500 Hz |
0 |
0 |
0 |
0 |
1 |
1 |
1 |
0 |
0x0E |
1000 Hz |
0 |
0 |
0 |
0 |
1 |
1 |
1 |
1 |
0x0F |
0 |
0 |
0 |
1 |
x |
x |
x |
x |
0x10-0x1F |
0: 予約値 /
赤字: 起動時の初期値
ACC Register 0x11 (PMU_LPW) Read/Write
メイン電力モードと低電力スリープ期間の選択。
スケッチ内での設定値は
0x00。
主電源モードの構成設定:
Bit |
7 |
6 |
5 |
Content |
suspend |
lowpower_en |
deep_suspend |
NORMAL mode |
0 |
0 |
0 |
0x00 |
DEEP_SUSPEND mode |
0 |
0 |
1 |
0x20 |
LOW_POWER mode |
0 |
1 |
0 |
0x40 |
未適応 |
0 |
1 |
1 |
SUSPEND mode |
1 |
0 |
0 |
0x80 |
未適応 |
1 |
0 |
1 |
1 |
1 |
0 |
1 |
1 |
1 |
LOW_POWERモードでスリープフェーズ期間を設定:
Bit |
4 |
3 |
2 |
1 |
0 |
NORMAL |
DEEP
SUSPEND |
LOW
POWER |
SUSPEND |
Content |
sleep_dur |
reserved |
0.5 ms |
0 |
0 |
0 |
0 |
0 |
0x00 |
0x20 |
0x40 |
0x80 |
0 |
0 |
0 |
1 |
0 |
0x02 |
0x22 |
0x42 |
0x82 |
0 |
0 |
1 |
0 |
0 |
0x04 |
0x24 |
0x44 |
0x84 |
0 |
0 |
1 |
1 |
0 |
0x06 |
0x26 |
0x46 |
0x86 |
0 |
1 |
0 |
0 |
0 |
0x08 |
0x28 |
0x48 |
0x88 |
0 |
1 |
0 |
1 |
0 |
0x0A |
0x2A |
0x4A |
0x8A |
1 ms |
0 |
1 |
1 |
0 |
0 |
0x0C |
0x2C |
0x4C |
0x8C |
2 ms |
0 |
1 |
1 |
1 |
0 |
0x0E |
0x2E |
0x4E |
0x8E |
4 ms |
1 |
0 |
0 |
0 |
0 |
0x10 |
0x30 |
0x50 |
0x90 |
6 ms |
1 |
0 |
0 |
1 |
0 |
0x12 |
0x32 |
0x52 |
0x92 |
10 ms |
1 |
0 |
1 |
0 |
0 |
0x14 |
0x34 |
0x54 |
0x94 |
25 ms |
1 |
0 |
1 |
1 |
0 |
0x16 |
0x36 |
0x56 |
0x96 |
50 ms |
1 |
1 |
0 |
0 |
0 |
0x18 |
0x38 |
0x58 |
0x98 |
100 ms |
1 |
1 |
0 |
1 |
0 |
0x1A |
0x3A |
0x5A |
0x9A |
500 ms |
1 |
1 |
1 |
0 |
0 |
0x1C |
0x3C |
0x5C |
0x9C |
1 s |
1 |
1 |
1 |
1 |
0 |
0x1E |
0x3E |
0x5E |
0x9E |
0: 予約値 /
赤字: 起動時の初期値
BMX055レジスタへからの値の読み込み
加速度センサーから加速度を取得するためのレジスタアドレスを確認します。
詳細はデータシートを参照。
ACC Register 0x02 (ACCD_X_LSB) Read Only
レジスタにはXチャネル加速度読み出し値の最下位ビットが格納されます。
Xチャネル加速度値を読み取るとき、ACCD_X_MSBおよびshadow_dis='0'の前にACCD_X_LSBが読み取られるとACCD_X_MSBレジスタの値は読み取りが行われるまでロックされ、それによりデータの整合性が保証されています。バーストモード読み出しアクセスが実行される場合、この条件は本質的に満たされます。加速データは、電源投入時とDEEP_SUSPENDモード時を除き、ACCD_X_MSBからいつでも読み出すことができます。
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
Content |
acc_x_lsb |
undefined |
new_data_x |
acc_x_lsb | : | 最下位4ビットの加速リードバック値(2の補数形式) |
undefined | : | 使用されないランダムデータ |
new_data_x | : | - 加速度値が更新されていない場合
- 加速度値が更新されている場合
|
ACC Register 0x03 (ACCD_X_MSB) Read Only
このレジスタには、Xチャネル加速度読み出し値の最上位ビットが含まれています。
Xチャネル加速度値を読み取るとき、ACCD_X_MSBおよびshadow_dis=’0’の前にACCD_X_LSBが読み取られると、データの整合性が保証される。この場合、ACCD_X_LSBが読み取られた後、ACCD_X_MSBレジスタの値は、ACCD_X_MSBが読み取られるまでロックされます。バーストモードの読み取りアクセスが実行される場合、この条件は本質的に満たされます。加速データは、電源投入時およびDEEP_SUSPENDモード時を除き、ACCD_X_MSBからいつでも読み出すことができます。
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
Content |
acc_x_msb |
acc_x_msb | : | 加速リードバック値の最上位8ビット(2の補数形式) |
ACC Register 0x04 (ACCD_Y_LSB) Read Only
このレジスタには、Yチャネル加速度読み出し値の最下位ビットが格納されます。
Yチャネル加速度値を読み出す場合、ACCD_Y_MSBおよびshadow_dis='0'の前にACCD_Y_LSBが読み取られるとACCD_Y_MSBレジスタの値は読み取りが行われるまでロックされ、それによりデータの整合性が保証されています。バーストモード読み出しアクセスが実行される場合、この条件は本質的に満たされます。加速データは、電源投入時およびDEEP_SUSPENDモード時を除き、ACCD_Y_LSBレジスタから読み出すことができます。
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
Content |
acc_y_lsb |
undefined |
new_data_y |
acc_y_lsb | : | 加速リードバック値の最下位4ビット(2の補数形式) |
undefined | : | 使用されないランダムデータ |
new_data_y | : | - 加速度値が更新されていない場合
- 加速度値が更新されている場合
|
ACC Register 0x05 (ACCD_Y_MSB) Read Only
このレジスタには、Yチャネル加速度読み出し値の最上位ビットが格納されます。
Yチャネル加速度値を読み出す場合、ACCD_Y_MSBおよびshadow_dis='0'の前にACCD_Y_LSBが読み取られるとACCD_Y_MSBレジスタの値は読み取りが行われるまでロックされ、それによりデータの整合性が保証されています。バーストモード読み出しアクセスが実行される場合、この条件は本質的に満たされます。加速データは、電源投入時およびDEEP_SUSPENDモード時を除き、ACCD_Y_MSBからいつでも読み出すことができます。
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
Content |
acc_y_msb |
acc_y_msb | : | 加速リードバック値の最上位8ビット(2の補数形式) |
ACC Register 0x06 (ACCD_Z_LSB) Read Only
このレジスタには、Zチャネル加速度読み出し値の最下位ビットが格納されます。
Zチャネル加速度値を読み出す場合、ACCD_Z_MSBおよびshadow_dis='0'の前にACCD_Z_LSBが読み取られるとACCD_Z_MSBレジスタの値は読み取りが行われるまでロックされ、それによりデータの整合性が保証されています。バーストモード読み出しアクセスが実行される場合、この条件は本質的に満たされます。加速データは、電源投入時およびDEEP_SUSPENDモード時を除き、ACCD_Z_LSBレジスタから読み出すことができます。
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
Content |
acc_z_lsb |
undefined |
new_data_z |
acc_z_lsb | : | 加速リードバック値の最下位4ビット(2の補数形式) |
undefined | : | 使用されないランダムデータ |
new_data_z | : | - 加速度値が更新されていない場合
- 加速度値が更新されている場合
|
ACC Register 0x07 (ACCD_Z_MSB) Read Only
このレジスタには、Zチャネル加速度読み出し値の最上位ビットが格納されます。Zチャネル加速度値を読み出す場合、ACCD_Z_MSBおよびshadow_dis='0'の前にACCD_Z_LSBが読み取られるとACCD_Z_MSBレジスタの値は読み取りが行われるまでロックされ、それによりデータの整合性が保証されています。バーストモード読み出しアクセスが実行される場合、この条件は本質的に満たされます。加速データは、電源投入時およびDEEP_SUSPENDモード時を除き、ACCD_Z_MSBからいつでも読み出すことができます。
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
Content |
acc_z_msb |
acc_z_msb | : | 加速リードバック値の最上位8ビット(2の補数形式) |
取得した値の処理
スケッチの中では以下のように処理されている。
ちなみに"?"の箇所には、"x"、"y"、"z"のいずれかが入る。
Accl = ((ACCD_MSB * 256) + (ACCD_LSB & 0xF0)) / 16;
まず、上位ビット"ACCD_MSB"の処理。
(ACCD_MSB * 256)
256 = 28の事なので、
ACCD_MSB <<8
とも表記できる。
やっている事は、
short int msb = 165; // 二進数 0000000010100101
msb = msb <<8; // 二進数 1010010100000000
8bit(1byte)の数値を、16bit(2byte)の上位ビットにシフトしているだけです。
次に下位8ビット"ACCD_LSB"の処理。
ACCD_LSB & 0xF0
AND演算子を使用して0xF0(二進数で'11110000')で比較。
AND演算は、比較する各ビットが1 : 1 だと1、それ以外では全て0となります。
よって、以下のような感じで演算。
short int lsb = 92; // 二進数の 0000000001011100
lsb = lsb & 0xF0; // 二進数の 0000000001010000
結果として下位4ビットを0としてクリアする事になります。
で、最終的には、2つの値を加算して16で除算。
((ACCD_MSB <<8) + (ACCD_LSB & 0xF0)) / 16
16 = 24の事なので、
((ACCD_MSB <<8) + (ACCD_LSB & 0xF0)) >>4
と表せる。4ビット右へシフトするので、12ビット(0〜4095)の値が得られる。
例えば、
accd = msb + lsb; // 二進数の1010010101010000
accd >>4 // 二進数の0000101001010101
な感じ。
それに続けて行われている条件分岐では、
if (Accl > 2047) Accl -= 4096;
取得した値は、2の補数なので2047(4096の半分)より大きければ、4096で減算する事で正負の符号を明確にしています。
最後に、ここまで得られた値にPMU_RANGEで設定したレンジに対応する分解能を乗算するわけですが。。。
Accl = Accl * 0.0098; // renge +-2g
サンプルのスケッチでは0.0098となっていますが、データシートでは、
±2g range |
0.98mg/LSB |
0x03 |
---|
と、記載されているので、
0.98mg/LSB =
0.00098g/LSBが正解な気がします。
なので、上のスケッチは
0.00098に変更してあります。
"ここまで"のまとめ
スケッチの内容も理解出来たので、実際に動作させてみます。
--------------------------------------
Accl= -0.05,-0.10,1.00
--------------------------------------
Accl= -0.05,-0.10,1.00
--------------------------------------
Accl= -0.05,-0.10,1.00
--------------------------------------
Accl= -0.05,-0.10,1.00
--------------------------------------
Accl= -0.05,-0.10,1.00
Z軸に1Gがかかり、XY軸は微妙に傾斜している事を示しています。
このように元々のスケッチでも動作については全く問題ないのですが、ここまで知り得た情報を追記。
BMX055_ACCELEROMETER
#include
<Wire
.h>
// BMX055 加速度センサのI2Cアドレス
#define
Addr_Accl 0x18 // (JP1,JP2,JP3 = Closeの時)
// センサーの値を保存するグローバル関数
float
Accl[3];
void
setup()
{
// Wire(Arduino-I2C)の初期化
Wire
.begin
();
// デバック用シリアル通信は9600bps
Serial
.begin
(9600);
//BMX055 初期化
//------------------------------------------------------------//
Wire
.beginTransmission
(Addr_Accl);
Wire
.write
(0x0F); // PMU_Rangeレジスタを選択
Wire
.write
(0x03); // Range = +/- 2g
Wire
.endTransmission
();
delay
(100);
//------------------------------------------------------------//
Wire
.beginTransmission
(Addr_Accl);
Wire
.write
(0x10); // PMU_BWレジスタを選択
Wire
.write
(0x08); // Bandwidth = 7.81 Hz
Wire
.endTransmission
();
delay
(100);
//------------------------------------------------------------//
Wire
.beginTransmission
(Addr_Accl);
Wire
.write
(0x11); // PMU_LPWレジスタを選択
Wire
.write
(0x00); // Normal mode, Sleep duration = 0.5ms
Wire
.endTransmission
();
delay
(100);
}
void
loop()
{
//BMX055 加速度の読み取り
short int
data[6];
Wire
.beginTransmission
(Addr_Accl);
Wire
.write
(0x02); // データレジスタを選択
Wire
.endTransmission
();
Wire
.requestFrom
(Addr_Accl, 6); // 6バイトのデータを要求する
for
(int
i = 0; i < 6; i++)
data[i] = Wire
.read
();
// データを変換する
bitWrite
(data[0], 15, bitRead
(data[1], 7));
Accl[0] = (((data[1] <<8) | data[0]) >>4) * 0.00098;
bitWrite
(data[2], 15, bitRead
(data[3], 7));
Accl[1] = (((data[3] <<8) | data[2]) >>4) * 0.00098;
bitWrite
(data[4], 15, bitRead
(data[5], 7));
Accl[2] = (((data[5] <<8) | data[4]) >>4) * 0.00098;
Serial
.print
("Accl= ");
Serial
.print
(Accl[0];
Serial
.print
(","
);
Serial
.print
(Accl[1]);
Serial
.print
(","
);
Serial
.print
(Accl[2]);
Serial
.println
(""
);
delay
(300);
}
目新しく追記した箇所は、更新の値の取得とそれに基づく条件分岐、符号ビットの取得と格納、他は配列で管理するように変更したぐらいです。
で、これらで新規に使用したコマンドが以下。
bitRead()
説明
指定したビットの数値を読み取ります。
構文
bitRead(x
,n
)
パラメータ
x
読み取りたい数値変数の名前
n
読み取るビットの指定。最下位(右端)ビットの0から始まります。
戻り値
ビットの値(0または1)
bitWrite()
説明
数値変数にビットを書き込みます。
構文
bitWrite(x
,n
,b
)
パラメータ
x
書き込む対象となる数値変数
n
どのビットに書き込むか,最下位ビット(LSB)側が0。
b
書き込むビットの値(0または1)。
スケッチの内容は理解出来ましたが、現時点では加速度センサーを使っていると言うよりは、傾斜センサーを使っている印象です。
実用的にするためには、ここから重力方向を基準に加速度ベクトルを求め、加速度による移動距離推定などを計算したり、ジャイロセンサと組み合わせて回転角の精度を高めるなどする必要があります。この辺りについては改めて記載出来ればと思っています。
おまけ
加速度センサのレジスタは、他にも様々な機能に割り当てられています。
残念ながら、ここで全てを解説できる知識も技術も持ち合わせていないので、実際に触ってみて理解出来た"一部"だけを紹介しておきます。
ACC Register 0x08 (ACCD_TEMP) Read Only
レジスタには、2の補数形式で表される現在のチップ温度が含まれています。
temp <7:0>の読み出し値は、0x00 = 23°Cと換算して計算します。
また、温度の変化は0.5K(kelvin)/LSB単位で変化します。
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
Content |
temp |
動作するスケッチは下記。
BMX055_ACC_TEMP
#include
<Wire
.h>
// BMX055 加速度センサのI2Cアドレス
#define
Addr_Accl 0x18
void
setup()
{
// Wire(Arduino-I2C)の初期化
Wire
.begin
();
// デバック用シリアル通信は9600bps
Serial
.begin
(9600);
}
void
loop()
{
float
temp;
Wire
.beginTransmission
(Addr_Accl);
Wire
.write
(0x08);// データレジスタを選択
Wire
.endTransmission
();
Wire
.requestFrom
(Addr_Accl, 1);// 1バイトのデータを要求する
temp = Wire
.read
();
if
(temp > 0x7F) temp -= 256;
temp = (temp*0.5)+23;
Serial
.println
(temp);
delay
(300);
}
以降で加速度と少々異なる箇所だけをピックアップ。
if (temp > 0x7F) temp -= 256;
2の補数形式に対応して、1byteの数値を127を基準に正負に二分しています。
temp = (temp*0.5)+23;
これは、1bitに対して0.5K変化するので、得られた値に対して0.5を積算。
また、本来ケルビンから摂氏への変換は、
℃ = K - 273.15
となるのですが、K=0x00、つまりK=0の場合に23℃となる事が前提なので、23を加算しています。
実行結果。
26.00
26.00
26.00
25.50
25.50
25.50
まぁ、これを使用するほど厳密な精度を求める事もないと思うのですけどね。
0 件のコメント:
コメントを投稿