MAKER UNO + で始めるSTEM (9) WireライブラリでBoschのセンサ③補償データ

センサ・データの読み出し手順

 BME680は、気圧、温度、湿度、ガスの四つの機能をもったセンサです。それぞれ、デバイスごとに異なる補償データ(補正係数。Compensation)が記録されています。最初に読み出します。
 気圧、湿度、ガスは、温度の関数です。したがって、温度のレジスタを読み出し、補償データを使って温度を求めます。そのあと、湿度、気圧、ガスのレジスタを読み出して、補償データと温度を使って目的の値を得ます。

 BME680は、パワーオン・リセットがかかったのちスリープ・モードの省エネ状態で待機していて、レジスタの値は0x8000が読み出されます。刻々と変化するセンサのデータを読み出すには、最初に、二つあるコントロール・レジスタで、各測定するセンサの変換を有効(実行モード)にして測定をします。四つの測定が終わったらスリープ・モードに戻り、消費電力を下げます。

最初に補償データを読み出す

 最初は温度を求めるので、温度の補償データだけあればよいのですが、四つをまとめて読み出します。BME280/BMP280のデータシートには読み出す番地のメモリ・マップが記載されていましたが、BME680のデータシートには見つかりません。GitHubにあるソースを見なさいと書かれています。しかし、メモリ・マップという形では掲載されていません。

 /** Array Index to Field data mapping for Calibration Data*/

という構造体とそれぞれの型、並びの情報と、

 #define BME680_COEFF_ADDR1 0x89
 #define BME680_COEFF_ADDR2 0xe1

から、具体的なメモリ・マップを作成し、アクセスして読み出します。H1/H2は3バイトに二つのデータが入っているので、分離します。

#include <Wire.h>
#define BME680_address 0x76
#define reset 0xe0
#define ID_register 0xd0
#define BME680_COEFF_ADDR1 0x89
#define BME680_COEFF_ADDR2 0xe1

// calibrated humidity data
uint16_t dig_H1;
uint16_t dig_H2;
int8_t dig_H3;
int8_t dig_H4;
int8_t dig_H5;
uint8_t dig_H6;
int8_t dig_H7;
// calibrated gas data
int8_t dig_G1;
int16_t dig_G2;
int8_t dig_G3;
// calibrated temperature data
uint16_t dig_T1;
int16_t dig_T2;
int8_t dig_T3;
// calibrated pressure data
uint16_t dig_P1;
int16_t dig_P2;
int8_t dig_P3;
int16_t dig_P4;
int16_t dig_P5;
int8_t dig_P6;
int8_t dig_P7;
int16_t dig_P8;
int16_t dig_P9;
uint8_t dig_P10;

byte readbuffer[6];

void setup() {
Wire.begin();
Serial.begin(9600);
Serial.println("\nstart ");
Wire.beginTransmission(BME680_address);
Wire.write(reset);
Wire.endTransmission();
delay(10);
Wire.beginTransmission(BME680_address);
Wire.write(ID_register);
Wire.endTransmission();
Wire.requestFrom(BME680_address, 1);
uint8_t ID = Wire.read();
Serial.println("\nID = " + String(ID,HEX));

readCoefficients();
}

unsigned int read16(byte dig_registor){
Wire.beginTransmission(BME680_address);
Wire.write(dig_registor);
Wire.endTransmission();
Wire.requestFrom(BME680_address, 2);
readbuffer[0] = Wire.read();
readbuffer[1] = Wire.read();
return ( readbuffer[1] << 8 | readbuffer[0] );
}

unsigned int read8(byte dig_registor){
Wire.beginTransmission(BME680_address);
Wire.write(dig_registor);
Wire.endTransmission();
Wire.requestFrom(BME680_address, 1);
return ( Wire.read() );
}

void readCoefficients(){
dig_T1 = read16(0xE9); 
dig_T2 = (int16_t)read16(0x8A);
dig_T3 = (int8_t)read8(0x8C);

dig_P1 = read16(0x8E);
dig_P2 = (int16_t)read16(0x90);
dig_P3 = (int8_t)read8(0x92);
dig_P4 = (int16_t)read16(0x94);
dig_P5 = (int16_t)read16(0x96);
dig_P6 = (int8_t)read8(0x99); 
dig_P7 = (int8_t)read8(0x98); 
dig_P8 = (int16_t)read16(0x9C);
dig_P9 = (int16_t)read16(0x9E);
dig_P10 = (uint8_t)read8(0xA0);

dig_H1 = read8(0xE3) << 4 | read8(0xE2) & 0x0f ;
dig_H2 = read8(0xE1) << 4 | read8(0xE2) >> 4 ;
dig_H3 = (int8_t)read8(0xE4); 
dig_H4 = (int8_t)read8(0xE5); 
dig_H5 = (int8_t)read8(0xE6); 
dig_H6 = (uint8_t)read8(0xE7);
dig_H7 = (int8_t)read8(0xE8); 

dig_G1 = (int8_t)read8(0xEd); 
dig_G2 = (int16_t)read16(0xEb); 
dig_G3 = (int8_t)read8(0xEe); 

Serial.print("dig_T1="); Serial.println(dig_T1);
Serial.print("dig_T2="); Serial.println(dig_T2);
Serial.print("dig_T3="); Serial.println(dig_T3);

Serial.print("dig_P1="); Serial.println(dig_P1);
Serial.print("dig_P2="); Serial.println(dig_P2);
Serial.print("dig_P3="); Serial.println(dig_P3);
Serial.print("dig_P4="); Serial.println(dig_P4);
Serial.print("dig_P5="); Serial.println(dig_P5);
Serial.print("dig_P6="); Serial.println(dig_P6);
Serial.print("dig_P7="); Serial.println(dig_P7);
Serial.print("dig_P8="); Serial.println(dig_P8);
Serial.print("dig_P9="); Serial.println(dig_P9);
Serial.print("dig_P10="); Serial.println(dig_P10);

Serial.print("dig_H1="); Serial.println(dig_H1);
Serial.print("dig_H2="); Serial.println(dig_H2);
Serial.print("dig_H3="); Serial.println(dig_H3);
Serial.print("dig_H4="); Serial.println(dig_H4);
Serial.print("dig_H5="); Serial.println(dig_H5);
Serial.print("dig_H6="); Serial.println(dig_H6);
Serial.print("dig_H7="); Serial.println(dig_H7);

Serial.print("dig_G1="); Serial.println(dig_G1);
Serial.print("dig_G2="); Serial.println(dig_G2);
Serial.print("dig_G3="); Serial.println(dig_G3);
}

void loop() {
// put your main code here, to run repeatedly:
}

 この出力と、C:\Users\ユーザ名\Documents\Arduino\libraries\Adafruit_BME680_LibraryにあるAdafruit_BME680.cppの32行目のコメントアウトを外して、出力された補償データを比べて一致していることを確かめました。

#define BME680_DEBUG

 実行結果です。このデータは個々のデバイスによって値は異なります。

(※)AdafruitのBME680ライブラリは、ボッシュのGitHubにあるソース3本をそのまま変更せずに利用しています。Arduinoで利用しやすいように、インターフェースの部分を追加しています。

前へ

MAKER UNO + で始めるSTEM (8) WireライブラリでBoschのセンサ②IDの読み出し

次へ

MAKER UNO + で始めるSTEM (10) WireライブラリでBoschのセンサ④温度