3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ラズパイで自動ライトON/OFF機能付きの温湿度計をつくる

Posted at

こんにちは。

自宅のテレワーク部屋にこもるとすぐに風邪をひくので「乾燥してるからだ!」と思い、封印されていたラズベリーパイで『オレオレ温湿度計』を作ってみました。

できたもの

オレオレ温湿度計.jpg

ラズパイの起動と同時にLCDに部屋の温度と湿度(ついでにCPU温度も)を表示します。

ただ、人がいない間も常時LCDが点灯しているのがなんか嫌だったので、カメラで動体検知したらLCDのバックライトを点灯するようにしてみました。
無題のプレゼンテーション.png

環境

  • RaspberryPi 4 Model B
  • RaspberryPi OS 5.4.51
  • Python 3.7.3
  • 赤外線付きカメラ
  • LCDモジュール(I2Cインタフェース付)

実装手順

LCDにI2Cインターフェースをつける

まず温湿度を表示するためのLCDを調達しました。

Amazonでいろいろと安く売られており私はラズパイ接続が簡単なI2Cインターフェース付きのこちらの商品を購入しました。

IMG_20211124_222919.jpg

ただしこのモジュールはI2Cインターフェースを使うためにはんだ付けが必要です。

はんだ付けの道具を持っていない人はこのラズパイキットにはんだ付けされた、同様のLCDモジュールが付いているようなのでそちらをお勧めします。

私もはんだ付け道具持っていませんでしたが、LCDモジュール届いた後に気づいたので泣く泣くはんだ付け道具も購入しました……

こんな感じではんだ付けしました。はんだ付けはど素人ですが問題なく動いています。

IMG_20211206_222932.jpg

IMG_20211206_222943.jpg

ラズパイにLCDをつなげる

I2CインターフェースはVCC,GND,SDA,SCLをラズパイ側と接続します。

ラズパイはデフォルトでI2Cバス1がGPIOピン2と3で有効になっています。しかし私のラズパイのGPIOピン3はワンタッチでラズパイを起動/停止するボタンで使っているので、I2Cバス3を使います。

無効になっているI2Cバスを有効にするには/boot/config.txtで設定をオーバーライドします。

/boot/config.txt
# 以下の設定を追加する
dtoverlay=i2c3

このバスがどのGPIOピンを使うのかはdtoverlay -hで確認します。バス3はデフォルトでGPIOピン4,5を使うようです。

pi@raspberrypi:~ $ dtoverlay -h i2c3
Name:   i2c3
Info:   Enable the i2c3 bus
Usage:  dtoverlay=i2c3,<param>
Params: pins_2_3                Use GPIOs 2 and 3
        pins_4_5                Use GPIOs 4 and 5 (default)
        baudrate                Set the baudrate for the interface (default
                                "100000")

I2CインターフェースのSDAを4、SCLを5番のピンにつないでラズパイを起動します。i2cdetect -y 327が出力されればモジュールが認識されています。

pi@raspberrypi:/usr/local/bin $ i2cdetect -y 3
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- 27 -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

この27はラズパイにつないでいるデバイスのI2Cアドレスのため、もし私と違うデバイスを使っていれば異なるアドレスになる可能性があります。

このアドレスは後述のLCDに文字列を表示するプログラム中で利用します。

とりあえずLCDに文字を出力する

LCDへの文字出力はPythonを使います。

https://osoyoo.com/そのまま動くサンプルが公開されているのでこれを実行してみます。

注意点としてサンプルではI2Cのバス1を使っているので、私の場合はバス3に書き換える必要があります。

i2clcda.py
#bus = smbus.SMBus(1) # Rev 2 Pi uses 1
bus = smbus.SMBus(3) 

また、i2cdetectで確認したI2Cアドレスが0x27以外の場合は下記の部分も書き換える必要があります。

# Define some device parameters
I2C_ADDR  = 0x27 # I2C device address, if any error, change this address to 0x3f

スクリプトを実行してLCDに文字が表示されればOKです。

python3 icslcda.py

IMG_20211217_005831.jpg

温湿度モジュールを接続する

温湿度モジュールは過去にこちらの記事で紹介しています。
ラズパイ×Amazon TimeStreamで部屋の温湿度を可視化

  

温湿度モジュールはAmazonで購入できるこちらの商品を使います。

VCC,GND,DATをラズパイにつないでPythonのAdafruit_CircuitPython_DHTライブラリを使えば、簡単に温度と湿度が取得できます。

IMG_20211217_000214.jpg

pip3 install adafruit-circuitpython-dht
import adafruit_dht

# D26はDATをつないでいるGPIOピン番号
dht_Device = adafruit_dht.DHT22(board.D26)

print("temp: {}'C".format(dht_Device.temperature))
print("humidity: {} %".format(dht_Device.humidity,temp))

動体検知カメラの設定

こちらも過去の記事で紹介しています。
ラズパイで見守りシステム開発その2:動体検知と通知機能の実装

カメラの接続や設定は上の記事を参照してください。

動体検知にはmotionを使います。

$ sudo apt install motion

/etc/motion/motion.confの以下の部分を修正します。

/etc/motion/motion.conf
# 動体検知してから次の検知を始めるまでの待機時間(秒)
event_gap 60

# 動体検知で保存される動画の最大時間
max_movie_time 60

# 動体検知した時に実行するコマンドを設定
on_event_start bash -c "touch /tmp/motion_detect"

motionコマンドでサービスが起動します。

$ motion

プログラムの実装

いよいよ最終工程です。定期的に温湿度表示を更新しつつ、motionの動体検知に連動してLCDのバックライトが点灯するようにpythonスクリプトを作成します。

といっても仕組みはめちゃくちゃシンプルで

  1. 定期的に温湿度を表示するメインスレッド
  2. 早い間隔でmotionのon_event_startで作られる空ファイル/tmp/motion_detectを監視するスレッド

を実装します。

2.のスレッドが空ファイルを検知すればバックライトを点灯させ、/tmp/motion_detectを削除します。その後一定間隔以上、/tmp/motion_detectが作成されなければバックライトを消す、という流れです。

  

こんな感じのプログラムに仕上げました。i2clcda.pyはバックライトのON/OFFを指定できるように少し改修しています。

ソースコード(GitHub)

thermo-hygrometer.py
import i2clcda
import time
import adafruit_dht
import subprocess
import os
import threading
import traceback
import math

# 現在のバックライトの状態(スレッド間で共有するグローバルな値)
BACKLIGHT = i2clcda.LCD_BACKLIGHT_ON

BACKLIGHT_TOGGLE_INTERVAL_SECONDS=0.1
MOTION_DETECT_EVENT_GAP_SECONDS=60
# 動体検知されない間もLCDバックライトONにする閾値
THRESHOLD_BACKLIGHT_OFF=math.floor(MOTION_DETECT_EVENT_GAP_SECONDS/BACKLIGHT_TOGGLE_INTERVAL_SECONDS)

dht_Device = adafruit_dht.DHT22(board.D26)
lock = threading.Lock()

# i2clcda.pyを使ったLCD更新処理
def display_info():
  global BACKLIGHT
  try:
    result=subprocess.run('vcgencmd measure_temp', shell=True, encoding='utf-8', stdout=subprocess.PIPE).stdout.split('=')
    temp=result[1].replace("\n","")

    i2clcda.lcd_string("{}'C | CPU".format(dht_Device.temperature),i2clcda.LCD_LINE_1,BACKLIGHT)
    i2clcda.lcd_string("{} % | {}".format(dht_Device.humidity,temp),i2clcda.LCD_LINE_2,BACKLIGHT)
  except RuntimeError:
    print (traceback.format_exc())

# バックライト切替スレッド
# 0.1秒間隔で/tmp/motion_detectの存在チェックを行う
def toggle_backlight():
  global BACKLIGHT
  file_not_found_count = 0
  while True:
    if os.path.exists('/tmp/motion_detect'):
      # 空ファイルがあればバックライトを点けてファイルは即座に削除
      with lock:
        file_not_found_count=0
        BACKLIGHT = i2clcda.LCD_BACKLIGHT_ON
        os.remove('/tmp/motion_detect')
        display_info()

    else:
      file_not_found_count += 1
      if file_not_found_count == THRESHOLD_BACKLIGHT_OFF:
        # 空ファイルが無い状態が60秒続いたらバックライトを消す
        with lock:
          BACKLIGHT = i2clcda.LCD_BACKLIGHT_OFF
          display_info()
    time.sleep(BACKLIGHT_TOGGLE_INTERVAL_SECONDS)

# メインスレッド
# 20秒間隔で温湿度(とラズパイのCPU温度)を表示する
def main():
  print('Start main')
  while True:
    with lock:
      display_info()
    time.sleep(20)

if __name__ == '__main__':
  i2clcda.lcd_init()


  thread_main = threading.Thread(target=main)
  thread_toggle_backlight = threading.Thread(target=toggle_backlight)

  thread_main.start()
  thread_toggle_backlight.start()

  thread_main.join()
  thread_toggle_backlight.join()

こんな感じで動きます!
ダウンロード.gif

以上です。皆さんもよきラズパイ生活をお送りください!!

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?