Raspberry pi zero 2Wを入手したので備忘録として書きます。
今回は照度センサ(BH1750)のGY-302モジュールを使用して明るさを測定します。
明るさによってLCDのLEDの明るさを変更してみたいと思います。
照度センサ
Amazonで下記の光センサを購入しました。
BH1750を使用した明るさの測定方法は以下のURLを参考にしました。
🌞️⚫BH1750を使って明るさを計測する - ⭐|ラズベリーパイのレシピ (zenn.dev)
Raspberry pi zeroとの接続
BH1750 |
|
3.3V(1) |
Vcc |
GND(9) |
GND |
GPIO3(5) |
SCL |
GPIO2(3) |
SDA |
GNG(9) or open | ADDR |
※ADDRは後で3.3Vへ接続を変更しています。
Raspberry piの設定
I2C通信の設定
今回はI2C通信で制御しますので、I2Cを使用できるように設定します。
$ sudo raspi-config
接続デバイスの確認
i2cdetectコマンドを使用してI2Cで接続しているデバイスの確認を行います。
下記の用のI2Cのアドレス23hのデバイスが接続されています。(ADDR:GND接続時)
※ADDRへ3.3V接続時はアドレス5Chとなりました。
BH1750の制御モジュールのインストール
pipコマンドで公開されているBH1750の制御モジュールをインストールします。
$ pip install adafruit-circuitpython-bh1750
インストールしたファイルは下記に格納されます。
/home/tomtomst/.local/lib/python3.9/site-packages
サンプルプログラム
import time
import board
import adafruit_bh1750
def main():
# 初期化
i2c = board.I2C()
sensor = adafruit_bh1750.BH1750(i2c)
# ルクスの表示
for _ in range(5):
time.sleep(1)
print("%.2f Lux"%sensor.lux)
return
if __name__ == "__main__":
main()
サンプルプログラムの実行結果
蛍光灯を点けた状態だと262ルクス、消した状態(真っ暗)で0ルクスでした。
手で影を作ると20ルクス程度になるので正常に動作していそうです。
I2Cアドレス
センサのADDR端子を3.3Vへ接続すると、I2Cのデバイスアドレスは0x5cになります。
先のサンプルプログラムは、デバイスアドレスは指定せずにデフォルトの0x23にアクセスしていましたが、
0x5cへアクセスしたい場合は、下記のように8行目で0x5cを追加することで、0x5cのアドレスを指定することができます。
sensor = adafruit_bh1750.BH1750(i2c,0x5c)
LCDの明るさの変更
これまでのLCDのLED点灯は、GPIOの出力をHighレベルとしていました。
これをPWM出力することで明るさを変更しようと思います。
照度センサで周りが暗い場合は、PWM出力で10%の明るさ、
周りが明るい場合は、100%の明るさとします。
初期設定
下記のようにGPIO23を100Hzのpwmピンに設定します。
dutyは0でスタートしておきます。
# libフォルダのライブラリを参照できるようにする。
import sys
sys.path.append('./lib')
#---- LCD LED PWM set ----
import RPi.GPIO as GPIO
# GPIOのピン番号指定を「BCM」に設定します
GPIO.setmode(GPIO.BCM)
# LED用のピンを「Out」に設定します
GPIO.setup(23,GPIO.OUT)
led_pwm = GPIO.PWM( 23 , 100) #pwm 100Hz
led_pwm.start(0)
#---------------------------------------------------------
#人感センサ
import RPi.GPIO as GPIO
import threading
import datetime
PIR_PIN =27
GPIO.setmode(GPIO.BCM)
GPIO.setup(PIR_PIN,GPIO.IN)
PIR_count = 0
人検知時の明るさ設定
callback関数(人検知したときのLED点灯する関数)に照度センサの値が50lux以上の場合は、LEDの明るさをpwm10%に設定する処理を追加しました。
これまで使用していたLCD_led関数は使用しないのでコメントアウトしています。
変更した箇所は赤字です。
読みだした明るさ値(lux)は他の関数でも使用するのでglobal変数として宣言しておきます。
#人感センサ入力を割り込み設定する
# 割り込みルーチンでLED点灯して30sタイマを起動する。
def callback(pin):
global PIR_count,old_PIR_timer,lux
PIR_count = PIR_count + 1
#LCD_led_(23,1)
#照度センサ読み出し
BH1750_sensor = adafruit_bh1750.BH1750(i2c,0x5c)
lux = round(BH1750_sensor.lux , 1)
#明るさ判定
if lux > 50: #50lux以上で100%でLED点灯
led_pwm.ChangeDutyCycle(100)
else:
led_pwm.ChangeDutyCycle(10)
print("LED on ",datetime.datetime.now(),lux,"lux")
new_PIR_timer = threading.Timer(30.0, PIR_check)
old_PIR_timer.cancel()
new_PIR_timer.start()
old_PIR_timer = new_PIR_timer
#GPIO.add_event_detect(PIR_PIN,GPIO.RISING,callback=callback)
#---------------------------------------------------------------------
# 30s後人がいない場合LEDを消灯してタイマも停止する。
def PIR_check():
global PIR,PIR_count,old_PIR_timer
#print("人検知",PIR_count,"LED消灯")
print("LED off",datetime.datetime.now())
#LCD_led(23,0)
led_pwm.ChangeDutyCycle(0)
old_PIR_timer.cancel()
#old_PIR_timer = threading.Timer(60.0, PIR_check)
#old_PIR_timer.start()
def PIR_count_time():
import datetime
global PIR_count,humi,temp,lux
PIR_count_timer = threading.Timer(300.0, PIR_count_time)
PIR_count_timer.start()
now = datetime.datetime.now()
time_now = now.time().strftime("%H:%M:%S")
#humi, temp = sensor.read()
print(time_now,f'{temp:.01f}',"℃",f'{humi:.01f}',"%","PIR=",PIR_count,lux,"lux")
PIR_count = 0
#--------------------------------------------------------------------
初期設定メイン関数とメイン関数01
起動時のLEDは100%で点灯する設定にしました。
def setup_main():
global temp,humi
LCD_set() #LCDの初期設定
#LCD_led(23,1) #LCDのLED点灯
led_pwm.ChangeDutyCycle(100)
setup_disp() #起動中表示
time.sleep(1) #1秒wait
#今の日時を取得
today_n,time_n,now_M_S,now_S = now_daytime()
#時計表示
time_disp(today_n,time_n)
#温度取得
humi, temp = Adafruit_DHT.read_retry(sensor, DHT_pin)
if humi is not None and temp is not None:
#温度表示
temp_disp(temp,humi)
else:
print('Failed to get reading. Try again!')
while True:
if check_wifi():
print('Wi-Fi is available.')
break
else:
print('Wi-Fi is not available.')
time.sleep(1)
#お天気を取得
cor,weather,weather_url = weather_get()
#お天気をLCDへ表示
weather_disp(cor,weather,weather_url)
#weather_text_disp(cor,weather)
#weather_icon_disp()
#-------------------------------------------------
def main_01():
global touch_x,touch_y,temp,humi
now_S_old = "--"
(touch_x,touch_y) = (0,0)
while True:
#今の日時を取得
today_n,time_n,now_M_S,now_S = now_daytime()
if now_S != now_S_old: #1秒に1回処理するためにこの処理を追加
#0秒になったら時計表示
if now_S == "00" :
time_disp(today_n,time_n)
print(today_n,time_n)
if now_S[1] == "0": #10秒毎に処理
#温度取得
humi, temp = Adafruit_DHT.read_retry(sensor, DHT_pin)
if humi is not None and temp is not None:
#print('Temp={0:0.1f}*C Humidity={1:0.1f}%'.format(temp, humi))
#温度表示
temp_disp(temp,humi)
#weather_icon_disp()
else:
print('Failed to get reading. Try again!')
#天気予報表示
if now_M_S == "00:00":
print(time_n)
i = 0
while (i < 10):
if check_wifi():
print('Wi-Fi is available.')
#お天気を取得
cor,weather,weather_url = weather_get()
#お天気をLCDへ表示
weather_disp(cor,weather,weather_url)
break
else:
print('Wi-Fi is not available.')
time.sleep(1)
now_S_old = now_S #1秒の切り替わりを判定するために前の秒数を保存
#print(touch_x,touch_y,toggle)
sel = touch_sel(touch_x,touch_y)
if sel == "end" or sel == "poff":
print(sel)
time.sleep(1)
poff_disp(sel)
return sel
(touch_x,touch_y) = (0,0)
メインプログラム
if __name__ == '__main__':
# libフォルダのライブラリを参照できるようにする。
import sys
sys.path.append('./lib')
from LCD_led import LCD_led
from LCD_disp import LCD_set,setup_disp,time_disp,now_daytime
from LCD_disp import temp_disp,weather_disp,weather_text_disp,weather_icon_disp
from LCD_disp import touch_disp,poff_disp
from weather_get import weather_get
from check_wifi import check_wifi
import time
#---DHT22温度センサの初期設定-----
import Adafruit_DHT
sensor = Adafruit_DHT.DHT22
DHT_pin = 26
#------------------
setup_main()
touch_disp("")
#---- 照度センサ設定 ---
import board
import adafruit_bh1750
i2c = board.I2C()
BH1750_sensor = adafruit_bh1750.BH1750(i2c,0x5c)
lux = round(BH1750_sensor.lux , 1)
#人検知の割り込みを有効にする
GPIO.add_event_detect(PIR_PIN,GPIO.RISING,callback=callback)
#60秒後にPIR_check関数を起動するタイマを設定する
old_PIR_timer = threading.Timer(60.0, PIR_check)
#タイマをスタートする
old_PIR_timer.start()
#5分(300秒)間隔で人検知回数を出力する
PIR_count = 0
PIR_count_time()
sel = main_01()
# import osでシャットダウンできるようにする
import os
import RPi.GPIO as GPIO
time.sleep(1)
if sel =="end":
GPIO.cleanup()
sys.exit()
if sel == "poff":
os.system('sudo shutdown -h now')
実行結果