稼働中

Raspberry Pi Pico(d_15)BH1750FVI 照度センサー

BH1750FVI GY-302モジュール(I2C)

ローム社製のBH1750FVIは環境光センサー(照度センサー)です。I2C通信で制御します。Raspberry Pi PicoでBH1750FVI搭載のGY-302モジュールを使ってみました。
ADDRの接続状態でスレーブアドレスを変更できます。’L’で0x23(35)、’H’で0x5c(92)です。
測定モードが(Continuously、One Time)×(resolution H、H2、L)の6つあります。
詳細はデータシートを参照してください。
※micro:bitの記事e_13からRaspberry Pi Picoで使えるように追記、修正等をしました。

外観

BH1750FVIモジュールHW-315の外観写真です。(以後はBH1750FVIと記載します)
BH1750FVI GY-302外観

接続例

BH1750FVIの電源電圧は2.4V~3.6VなのでRaspberry Pi Picoと接続できます。
I2C通信にはI2C1のSDA(GP10)SCL(GP11)を使いました。
ADDRをGNDと接続したのでスレーブアドレスは0x23(35)になります。
BH1750FVI 接続図
接続出来たらI2Cデバイスのスレーブアドレスを調べてみます。
ThonnyのShellで確認しました。
BH1750FVIのスレーブアドレスは以下のように35(0x23)でした。


>>> from machine import I2C,Pin
>>> i2c=I2C(1, scl=Pin(11), sda=Pin(10), freq=100_000)
>>> i2c.scan()
[35]

BH1750FVIの説明

データシートから抜粋してBH1750FVIの説明します。
測定モードには連続測定(Continuously)と単測定(One Time)があります。各々、解像度H(1lx)、L(4lx)、H2(0.5lx)が選択できます。測定時間はH、H2では120msec(Max 180msec)、Lで16msec(Max 24msec)です。
下表のOpecodeを送信して測定モードを設定します。
他にPower Down、Power On、Resetなどの処理がI2C送信で可能です。
BH1750FVI Instruction
※ BH1750FVIのデータシートから抜粋
単測定後はPowerDownされています。そのため再測定するには測定モードを再設定するか、PowerOn後にデータを読出しする必要があります。
BH1750FVI 動作
※ BH1750FVIのデータシートから抜粋

測定するには下図のように
①測定モードのOpecodeを送ります(writeto)
②測定時間の待機をします。待機時間は各測定モードで変わります。
③測定データの2byteデータを受けます。(readfrom)
④ルクス計算します。16bitデータを10進数にします。高分解能H2(0.5lx)の場合は16bitデータを1bitシフト下げて10進数にします。10進数の値を1.2で割ります。
例えば、High Byte “10000011” and Low Byte is “10010000”の16bitデータなら
>>> 0b1000001110010000
33680
>>> 33680/1.2
28066.67 [ lx ]
になります。
高分解能H2モードなら
>>> 0b1000001110010000 >>1
16840
>>> 16840/1.2
14033.33 [ lx ]
になります。
※詳細はデータシートを参照ください。
BH1750FVI R/W

スクリプト

BH1750FVIのスクリプトは以下のようにしました。
※開発環境はThonnyです。ThonnyでMicroPythonをRaspberry Pi Pico with RP2040にインストールして使っています。


pico_bh1750_01b.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from machine import I2C,Pin
import time
# BH1750FVI digital Ambient Light Sensor I2C
i2c=I2C(1, scl=Pin(11), sda=Pin(10), freq=100_000)
#ADDR='L'35(0x23) ADDR='H' 92(0x5c)
addr=0x23

# Power Down
def P_Down():
    #mesure mode set
    buf=bytearray(1)
    buf[0]=0x00                #opecode  reset 0x07
    i2c.writeto(addr,buf)
# Power On
def P_On():
    #mesure mode set
    buf=bytearray(1)
    buf[0]=0x01                #opecode  reset 0x07
    i2c.writeto(addr,buf)
# Reset
def D_Reset():
    #mesure mode set
    buf=bytearray(1)
    buf[0]=0x07                #opecode  reset 0x07
    i2c.writeto(addr,buf)

## Mode Setting
# Measurement Mode   Continue('C') Onetime('O')
# Resolution  Mode   High-1lx('H') High2-0.5lx('S') Low-4lx('L')
def S_Mode(con='O',res='H'):
    global mode
    mode=[con,res]      #[Measure Mode,Resolution Mode]
    if mode[0]=='C':
        #Continuously
        if mode[1]=='H':
            wtime=200            
            opecode=0x10 #H-Resolution,Continuously
        if mode[1]=='S':
            wtime=200           
            opecode=0x11 #H-Resolution2,Continuously
        if mode[1]=='L':
            wtime=50            
            opecode=0x13 #L-Resolution,Continuously       
    if mode[0]=='O':
        #One Time
        if mode[1]=='H':
            wtime=200
            opecode=0x20 #H-Resolution,One Time
        if mode[1]=='S':
            wtime=200
            opecode=0x21 #H-Resolution2,One Time
        if mode[1]=='L':
            wtime=50
            opecode=0x23 #L-Resolution,One Time
    # measure mode set
    buf=bytearray(1)
    buf[0]=opecode
    i2c.writeto(addr,buf)
    time.sleep_ms(wtime)  

# lux measure
def L_Meas():
    # H,L 2byte read data
    r_data=i2c.readfrom(addr,2)
    H_byte=r_data[0]
    L_byte=r_data[1]

    # caluculate 
    d_lux=H_byte << 8 | L_byte # high2-mode 0.5 lx/bit if mode[1]=='S': d_lux=d_lux >>1

    lux=d_lux/1.2
    return lux

## main
S_Mode('C','H')
lx=L_Meas()
print('Lux= %6.1f lx' % lx )

部分説明

■S_Mode(con=’O’,res=’H’)
測定のモードを設定します。
連続 Continue(‘C’) 単 Onetime(‘O’)
Resolution High(‘H’) High2(‘S’) Low(‘L’)
それぞれの文字を与えます。
■L_Meas()
測定したlxを返します。
■P_Down()
パワーダウンします。
■P_On()
パワーオンします。
■D_Reset()
照度データのレジスタをリセットします。

実行結果

連続の分解能Highで実行してみました。S_Mode(‘C’,’H’)
結果は以下のようになりました。※Thonnyのshellに表示されます。


>>> %Run -c $EDITOR_CONTENT
Lux= 1025.8 lx
>>> 

次に、リセット動作を確認しました。Thonnyのshellで続けて実行しで確認しました。


>>> mode                    # スクリプト実行後なので 
['C', 'H']                  # 連続の分解能High
>>> D_Reset()               # レジスタのリセット
>>> i2c.readfrom(addr,2)
b'\x00\x00'                 # リセットされている

>>> S_Mode('O','H')         # 単発の分解能Highに変更
>>> L_Meas()
1025.0                      # 照度測定値
>>> D_Reset()               # レジスタのリセット
>>> i2c.readfrom(addr,2)
b'\x04\xce'                 # リセットされていない(単測定後はPower Downのため)
>>> P_On()                  # Power On
>>> D_Reset()               # レジスタのリセット
>>> i2c.readfrom(addr,2)
b'\x00\x00'                 # リセットされた

まとめ

Raspberry Pi PicoでBH1750FVIを使って照度測定ができました。