46.照度センサーBH1750FVIの検証 (2023.10.31-2023.11.3)

GARDEN-TECにも使用した照度センサーBH1750FVIについて、今まで良く分からないままに使ってきました。それと言うのもネット上にはなかなか正しく理解できるような情報が無かったからです。色々紹介はされているのですが、何となくデータを読み出して使用した気分になっている例が多くて、このデバイスに対して本気で利用しようとする人が少ないように思えます。確かに照度変化だけを重視するなら、相対的な値が得られれば十分なのでしょう。しかし、それでは応用に困ることから、今回は自分自身でデータシートを確認することにしました。もしかすると解釈にミスがあるかもしれませんが、指針となる結果は得られたと考えています。方針としては、繰り返し照度を測定する前提で考えていきたいと思います。

手持ちのBH1750FVIのI2C通信におけるアドレスは23Hに固定されていたため、このアドレスに対して読み書きすることで照度測定を行います。まずは簡単なところで、リセットコマンドを送ることから始めてみます。仕様書の5ページに示された「Instruction Set Architecture」によると、リセットコマンドは07H(2進数で0000_0111)となっています。つまりこの1バイトのデータをアドレス23Hに送れば良いわけです。リセットを行った後にデータレジスタの値を読み出すと値が0になるはずなので、次のプログラムで確認してみます。最初にデータを読み出した後にリセットをかけ、その後2回読み出してみれば、照度→0→照度になるはずです。動作モードの変更等、BH1750FVIに対してコマンドを送るには同様の方法をとります。上は通常のH-Resolution modeの場合(分解能:1lux)で、下は2倍の感度で測定するH-Resolution mode-2(分解能:0.5lux)です。2倍の感度のため2で割ることで、測定値自体は同じ値になります。より精密な値を得たい時はmode-2を使えば良いことになりますが、測定できる最大照度は半分になるので注意が必要です。(プログラムを使用する場合は拡張子を.pyにする)

BH1750FVI検証用プログラム(H-Resolution mode)
●測定結果

BH1750FVI検証用プログラム(H-Resolution mode-2)
●測定結果

実際に実験してみると、予想通りの値になっていることが分かります。なお、照度データの読み出しはプログラムの次の部分で行っています。

luxRead = bus.read_i2c_block_data(addr, 0x10)

デバイスアドレスに対して、デバイス内のレジスタの指定アドレス(本例では10H:Continuously H-resolution modeとして測定)から2バイトのブロックデータを読み出します。仕様書の7ページを見てイメージをつかんで下さい。この場合、コマンド発行と同時に照度データの読み出しを行うため、本来必要な光の蓄積時間を確保できません。実際には1つ前のコマンドで蓄積された照度データを読み出す形になると思われ、この方法には気がかりな点が残ります。

BH1750FVIは更に細かく分解能を変更することができます。それを決定するのがMTregと呼ばれるレジスタの値で、デフォルトでは69がセットされています。これが本デバイスの基本となる計測値と考えられます。通常はそのままで構わないと思いますが、検証のため最低(31)、デフォルト(69)、最高(254)の3つの値で実験してみました。

BH1750FVIのMTreg検証用プログラム
●測定結果

照度の計算方法はBH1750FVIの仕様書で示されていて、プログラムはそれを反映した形で組んでいます。途中のデータ変換は上位ビットデータを8bit左シフトして下位ビットデータに加えるのが仕様書の方法ですが、コメントアウトした方法でも得られます。行っていることは同じなので、どちらを使っても構いません。

測定はMTreg=69(デフォルト)、31(最小値)、254(最大値)の順です。感度が変われば上限の値も変わるため、測定しようとする環境に合わせて適切な値を設定します。特に問題無ければデフォルトのままで使うのが無難です。なお、モードを変更したりMTregの値を変更した場合は、データを読み出すタイミングに注意する必要があります。配慮せずにブロック転送を行うと、誤った値となってしまいます。特に待ち時間を1秒とした部分は、実験では最低0.6秒待たないとダメでした。

得られた照度データはどれもほとんど変わらないので、生の値を小数点以下2桁まで得た上で、最終的に整数値になるよう四捨五入したため、このテストでは少し面倒なprint文になっています。単なる比較なので通常使用ではここまでする必要はありません。

デバイスが電源オフになると初期状態に戻るので、デフォルト状態のままで使うならば特に配慮は不要です。太陽光を扱う場合は高光度になるため、デフォルトで上限に達する場合はMTregの値をより大きな値(最大は254)に変更する必要があります。逆に暗い部屋の中等では低光度となり、より精密な測定を行うためMTregの値を小さな値(最小は31)にします。参考までにH-Resolution mode-2のプログラムも追記しておきます。感度補正のため取得値を1/2していることに注目して下さい。結果、得られる値は通常modeと同じになります。

BH1750FVIのMTreg検証用プログラム(H-Resolution mode-2)

MTregの値を求める方法はデータシートに従うと次のようになります。MTregの値は2バイトで構成されていて、
上位バイト:01000_MT[7,6,5]
下位バイト:011_MT[4,3,2,1,0]
で表されます。例えば最小値の31(10進数)の場合、16進数では1fHとなります。これを2進数で表すと0001_1111です。最初の3ビットは000で、残りは11111です。これをMTregの値に当てはめると、
上位バイト:01000_000
下位バイト:011_11111
になります。これらを4ビットずつで区切ると、
上位バイト:0100_0000
下位バイト:0111_1110
です。16進数に直せば、
上位バイト:40H
下位バイト:7fH
つまり、この2つのバイトデータをデバイスに対して書き込めば良いわけです。同様に考えれば、
デフォルトの69(10進数)は上位バイトが01000_010で下位バイトが011_00101になるので、求める結果は42Hと65H
最大値の254(10進数)は上位バイトが01000_111で下位バイトが011_11110になるので、求める結果は47Hと7eH
であることが理解できるでしょう。

BH1750FVIにはL-Resolution modeと言うものもあります。分解能が1/4(粗い)になりますが、4倍の照度まで測定できるため、強い光度下で使用するのに適しています。太陽光の下で使用する場合、L-Resolution mode(コマンド:13H)を使う必要が出てくるかもしれません。実はこのモードでもテストしてみたのですが、得られた結果は通常modeと変わりませんでした。どこかに解釈の誤りがあるようで、今のところ不明のままです。いずれ機会があれば検証したいと思います。