第29回 温湿度・気圧センサ(BME280) 〜詳細仕様〜

今回はセンサモジュールの詳細仕様を説明します。

今回の説明内容

前回の記事で、センサモジュール内にはメモリがあり、SPI通信を利用してそのメモリを読み書きすることにより動作設定をしたり測定データを読み出したりすることを説明しました。

この記事では、そのメモリの構成や読み書き方法などについて、詳細を説明します。

 

メモリ構成

センサモジュール内のメモリは、通常のメモリと同様にアドレスが振られています。

「メモリにアドレスが振られている」と説明されても「アドレス???」という方もいらっしゃるかもしれません。このPICマイコン電子工作入門シリーズでは、メモリについて具体的な説明をしていませんので、ここで簡単にメモリについて説明します(メモリをすでにご存知の方は次のセクションに進んでいただいて問題ありません)。

普段使っているPCやスマホの内部、今回使用するマイコンやセンサモジュール内部には、計算結果やデータを保存しておくための「メモリ」があります。このメモリは、8ビット=1バイトを基本単位としています。

Pic practice 29 memory

例えばPIC16F18857では、内部に4096バイトのメモリを持っています。上のように1バイトのデータを保存しておく箱のようなものが4096個用意されているわけです。また、今回使用する温湿度・気圧センサは56バイトのメモリを持っています。また、一般的なPCやスマホは、最近ではギガバイト単位のメモリが搭載されていますよね。

メモリにデータを保存する場合、メモリの「どこに」保存するか指定する必要があります。また、メモリからデータを読み出す場合も同様に、「どこの」メモリからデータを読み出すのか指定する必要があります。このように「どこ」を指定するために、メモリには特定するための番号が振られています。

この番号は、「アドレス」(住所)と呼ばれています。実世界を見てみると、家やビルなどの場所を特定する場合、住所を使いますよね。メモリの場合もこれに見立てて「アドレス」と呼んでいます。なお、「アドレス」は日本語で「住所」の意味ですが、日本語でも「アドレス」と呼んでいます。

Pic practice 29 address

この「アドレス」は、通常16進数で表記します。

Pic practice 29 address hexadecimal

また、アドレスが例えば0xFFFのメモリのことを「0xFFF番地のアドレス」というように〇〇番地、という呼び方をします。さらに、メモリの構成を示したものを「メモリマップ」(メモリの地図)と呼びます。このようにメモリを実世界に見立てて「マップ(地図)」「アドレス(住所)」「番地」という言葉を使用しています。

前回の記事で、センサモジュール内のメモリに、いろいろなデータが格納されていることを説明しました。

例えば、測定データを読み出す場合は、何番地のアドレスから読み出すのか、読み出し時にアドレスを指定する必要があります。センサモジュールのデータシートには、何番地にどのようなデータが格納されているか説明されています。

次のセクションでは、センサ本体BME280のメモリマップの詳細を説明します。

 

BME280のメモリマップ詳細

BME280のメモリマップは以下のように構成されています。

Pic practice 29 bme280 memory map

例えば、湿度は16ビットデータとしてメモリに格納されていて、上位8ビット(=1バイト)は0xFD番地、下位8ビットは0xFE番地に格納されています。湿度データを取得する場合は、0xFD番地と0xFE番地のデータを読み出すことになります。なお、この湿度データは校正されていませんので、別途校正用データで難しい計算をする必要があります。

また、動作設定を行うには、表の中央付近にある0xF5番地に設定値を書き込みます。

前回の記事で説明しました、測定データの取得の流れをメモリマップを見ながら確認しましょう。以下は測定データの取得の流れです。

Pic practice 29 process sequence

1番目の動作設定では、以下のメモリにセンサの動作設定の値を書き込みます。

Pic practice 29 sequence 1

次に2番目、3番目で以下の校正用データを取得します。

Pic practice 29 sequence 2

4番目の測定指示では、再度1番目と同じメモリに測定指示をするための値を書き込みます。

Pic practice 29 sequence 3

測定指示をすると、センサは温室度と気圧のデータを測定し、測定データメモリに測定値を保存しますので、5番目と6番目で以下の測定データを取得します。

Pic practice 29 sequence 4

次に、読み出し方法と書き込み方法について説明します。

 

読み出し方法

特定アドレスからデータを読む場合、SPI通信で最初にマスターからMOSI信号線でアドレスを送信します。アドレスを送信後、マスターからクロック信号を送り続けると、センサはそのアドレスのデータをMISO信号線でマスターに送ってきます。1バイトを読み取る場合は、クロック信号を8回発生すれば読むことができます。

Pic practice 29 read

なお、マスターから続いてクロック信号を発生し続けると、センサはMOSI信号線で次のアドレスのデータをMISO信号線で送ってきます。

Pic practice 29 read burst

先ほどのメモリマップを確認いただければわかると思いますが、校正用データや測定データのメモリはアドレスが連続しています。そのため、このうなデータを読む場合は、「アドレス送信→1バイト読み込み、次のアドレス送信→1バイト読み込み」ということはせずに「アドレス送信→1バイト読み込み→次のアドレスの1バイト読み込み…」と続けて読むことになります。

SPI通信手順にまとめると以下のようになります。以下は1バイト読み取りの例ですが、連続して読み込む場合はクロック信号を必要バイト数分繰り返せばOKです。

Pic practice 29 spi read timing chart

PICマイコンのプログラムは、このタイミングチャートに合わせて作成しますので、このタイミングチャートを理解しておきましょう! タイミングチャートが十分理解できないようでしたら、もう一度SPI通信手順の説明を確認してみてください。

 

書き込み方法

書き込み方法は、以下のようにマスター(PICマイコン)からスレーブ(センサ)に書き込みアドレスを指定した後、書き込みデータを送信するだけです。

Pic practice 29 write

ただ、アドレス指定は読み出し方法とは一点だけ異なります。書き込む際のアドレス指定は、アドレスの最上位1ビットを0にします。例えば動作設定のアドレスは0xF5(=11110101)ですが、書き込む場合のアドレスは0x75(=01110101)になります。動作設定を行う場合は以下のようなアドレス指定となります。

Pic practice 29 write address

SPI通信手順をまとめると以下のようになります。

Pic practice 29 spi write timing chart

 

測定データ計算方法

最後に取得したデータの計算方法の概要を説明します。

取得した測定データは、校正用データで校正する必要があります。ただ、、、計算方法の意味はよくわからないんです。なんと無責任な、という説明ですが、校正はセンサの特性に合わせて計算する必要があり、その計算方法はセンサのメーカーから指定されていますので、その計算方法に従う必要があります。

データシートには計算式ではなく、C言語のプログラムで説明されていますので、測定データの校正はそのプログラムをコピペして作成します。

以下はその校正プログラムですが、、、何をしているのかわからないですよね。

以下のプログラムで、dig_T、dig_P、dig_Hはそれぞれ温度、気圧、湿度の校正用データで、adc_T、adc_P、adc_Hはそれぞれ測定データ(校正前の生データ)になります。何をしているのかはあまり深入りしないほうがいいと思います。

[BOSCH社 BME280データシートより引用]

// Returns temperature in DegC, resolution is 0.01 DegC. Output value of “5123” equals 51.23 DegC. // t_fine carries fine temperature as global value
BME280_S32_t t_fine;
BME280_S32_t BME280_compensate_T_int32(BME280_S32_t adc_T)
{
BME280_S32_t var1, var2, T;
var1 = ((((adc_T>>3) – ((BME280_S32_t)dig_T1<<1))) * ((BME280_S32_t)dig_T2)) >> 11;
var2 = (((((adc_T>>4) – ((BME280_S32_t)dig_T1)) * ((adc_T>>4) – ((BME280_S32_t)dig_T1))) >> 12) *
((BME280_S32_t)dig_T3)) >> 14; t_fine = var1 + var2;
T =(t_fine*5+128)>>8;

return T;
}

// Returns pressure in Pa as unsigned 32 bit integer in Q24.8 format (24 integer bits and 8 fractional bits). // Output value of “24674867” represents 24674867/256 = 96386.2 Pa = 963.862 hPa
BME280_U32_t BME280_compensate_P_int64(BME280_S32_t adc_P)
{
BME280_S64_t var1, var2, p;
var1 = ((BME280_S64_t)t_fine) – 128000;
var2 = var1 * var1 * (BME280_S64_t)dig_P6;
var2 = var2 + ((var1*(BME280_S64_t)dig_P5)<<17);
    var2 = var2 + (((BME280_S64_t)dig_P4)<<35);
    var1 = ((var1 * var1 * (BME280_S64_t)dig_P3)>>8) + ((var1 * (BME280_S64_t)dig_P2)<<12); var1 = (((((BME280_S64_t)1)<<47)+var1))*((BME280_S64_t)dig_P1)>>33;
if (var1 == 0)
{
return 0; // avoid exception caused by division by zero
}
p = 1048576-adc_P;
p = (((p<<31)-var2)*3125)/var1;
    var1 = (((BME280_S64_t)dig_P9) * (p>>13) * (p>>13)) >> 25; var2 = (((BME280_S64_t)dig_P8) * p) >> 19;
p = ((p + var1 + var2) >> 8) + (((BME280_S64_t)dig_P7)<<4); return (BME280_U32_t)p;
}

// Returns humidity in %RH as unsigned 32 bit integer in Q22.10 format (22 integer and 10 fractional bits). // Output value of “47445” represents 47445/1024 = 46.333 %RH
BME280_U32_t bme280_compensate_H_int32(BME280_S32_t adc_H)
{
    BME280_S32_t v_x1_u32r;
    v_x1_u32r = (t_fine – ((BME280_S32_t)76800));
    v_x1_u32r = (((((adc_H << 14) – (((BME280_S32_t)dig_H4) << 20) – (((BME280_S32_t)dig_H5) * v_x1_u32r)) +
        ((BME280_S32_t)16384)) >> 15) * (((((((v_x1_u32r * ((BME280_S32_t)dig_H6)) >> 10) * (((v_x1_u32r *
((BME280_S32_t)dig_H3)) >> 11) + ((BME280_S32_t)32768))) >> 10) + ((BME280_S32_t)2097152)) *
((BME280_S32_t)dig_H2) + 8192) >> 14));
v_x1_u32r = (v_x1_u32r – (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * ((BME280_S32_t)dig_H1)) >> 4)); v_x1_u32r = (v_x1_u32r < 0 ? 0 : v_x1_u32r);
    v_x1_u32r = (v_x1_u32r > 419430400 ? 419430400 : v_x1_u32r);

return (BME280_U32_t)(v_x1_u32r>>12);
}

次回はセンサモジュールとのSPI通信の動作確認プログラムを作成します。

 

更新履歴

日付 内容
2018.4.22 新規投稿