ラズパイその他工作

ラズパイとセンサで作る「快適空間自動生成装置」第3回

こんにちは、ヨシケンです!
自宅を快適に、在宅仕事を効率的にするデバイス作りの第3回です。
前回はローム・センサメダルをBLEでつないでさまざまな数値を計測しました。今回は人感センサなどもつないで、座りっぱなしや仕事のし過ぎもチェックできるようにしたいと思います!

raspberrypi-comfortable-space-device-03-1

 

今回の記事で必要な物一覧

Raspberry Pi 3 B+ または Raspberry Pi 4 Model B

3

Raspberry Pi 3 B+

4

Raspberry Pi 4 Model B

 

ローム・センサメダル(SensorMedal-EVK-002)

5

 

焦電型赤外線(人感)センサ (SB412A)

raspberrypi-comfortable-space-device-03-5

 

ラズパイ用LCDディスプレイ

raspberrypi-comfortable-space-device-03-6

 

今回の記事の流れ

  1. ラズパイに人感センサを接続
  2. LCDディスプレイを追加
  3. まとめ

 

1. ラズパイに人感センサを接続

前回はローム・センサメダルから明るさを計測し、その数値に応じてUSBライトをコントロールしました。それに加えて温湿度もチェックし、室温が高くなっていたら扇風機を回すなども同様のやり方で作ることができます。

ただ、それだけですと効率的ではないかもしれません。このラズパイ・デバイスを設置するデスク周りに、人がいる時だけ動作させるようにしたいでしょう。

また、第1回で挙げたように、リモートワーク中、ついつい座りっぱなしになって疲れてしまうのを防げるようにもしたいです。

番号 計測機能 計測後にあったらいい機能
5 椅子に座っている時間をチェック 人が居続ける(座りっぱなし)だったら、席を立って動くように促す

ということで、第1回で挙げた「このような機能があったらいいな」の中から、上記の計測機能を実装していきたいと思います。具体的には、ラズパイに人がいるかどうかを測るセンサを追加し、デスク周りの活動状況をチェックできるようにします。そのために以下のような、集電型赤外線人感センサをラズパイに設置します。

raspberrypi-comfortable-space-device-03-7

センサ側(写真左から) ラズパイ側
+(黄色) 5V
OUT(赤) GPIO13
ー(黒) GND

 

ラズパイとの接続は表の通りです。実際の設置した写真はこのようになっています。

raspberrypi-comfortable-space-device-03-8

 

ここで人感センサとして動いているか、簡単なプログラムhuman.pyを作ります。これを流して、周りに人がいる場合1と表示され、それ以外だと0となります。

[human.py]

import RPi.GPIO as GPIO
from time import sleep

human_pin = 13
GPIO.setmode(GPIO.BCM)
GPIO.setup(human_pin, GPIO.IN)

try:
    while True:
        human = GPIO.input(human_pin)
        print(human)
        sleep(1)

except KeyboardInterrupt:
    pass

GPIO.cleanup()

 

human.pyを実行してみます。ラズパイを置いた前に座ったり、手を近くに置いた時だけ1が表示されています。

raspberrypi-comfortable-space-device-03-10

raspberrypi-comfortable-space-device-03-9

 

2. LCDディスプレイを追加

それでは、これまで追加したセンサメダルや人感センサの値を表示するようなLCDディスプレイをラズパイに付けましょう。

いろいろな種類のLCDディスプレイが市販されていますが、ラズパイのGPIO端子に差し込むだけで使えるディスプレイ・ハットを使います。人感センサを接続するためのGPIOにピンも挿しておきます。

raspberrypi-comfortable-space-device-03-6

 

写真のように、ラズパイのGPIOにディスプレイを差し込みます。

raspberrypi-comfortable-space-device-03-11

このディスプレイのライブラリがAdafruitから出ているので、そのGithubページを見てみます。
https://github.com/pimoroni/displayotron

そこに書いてあるインストール・スクリプトを流します。これでHome下にpimoroniというディレクトリが作られ、その中の以下の場所にサンプルプログラムが格納されます。

似たような機能でDot3000と、DotHatがありますが、今回使ったのはDotHatの方なのでそのライブラリを使います。いくつかサンプルプログラムがあるので、流して試してみてください。

$ curl -sS get.pimoroni.com/displayotron | bash
$ cd /home/pi/Pimoroni/displayotron/dothat
$ python3 basic/hello_world.py
$ python3 basic/backlight.py 

 

それでは、前回使ったセンサメダルとラズパイを接続するプログラムを改造して、このLCDに計測した数値を表示するようにします。以下、4行目、22〜27行目、45〜50行目、91〜115行目が前回のbleプログラムへの追加部分です。

[ble_lcd.py]

#!/usr/bin/env python3
# coding: utf-8

import dothat.lcd as lcd

from datetime import datetime
from bluepy import btle
from sys import argv
import getpass
from time import sleep

def payval(num, bytes=1, sign=False):
    global val
    a = 0
    for i in range(0, bytes):
        a += (256 ** i) * int(val[(num - 2 + i) * 2 : (num - 1 + i) * 2],16)
    if sign:
        if a >= 2 ** (bytes * 8 - 1):
            a -= 2 ** (bytes * 8)
    return a

import RPi.GPIO as GPIO
human_pin = 13
GPIO.setmode(GPIO.BCM)
GPIO.setup(human_pin, GPIO.IN)
human_count = 0
human_check = 3

interval = 10 # 動作間隔
scanner = btle.Scanner()

while True:
  
    now = datetime.now()
    d = '{0:0>4d}/{1:0>2d}/{2:0>2d}({3})'.format(now.year, now.month, now.day, now.strftime('%a'))
    t = '{0:0>2d}:{1:0>2d}:{2:0>2d}'.format(now.hour, now.minute, now.second)
    lcd.clear()
    lcd.set_cursor_position(0, 0)
    lcd.write('PiRemote')
    lcd.set_cursor_position(0, 1)
    lcd.write('{}'.format(d))
    lcd.set_cursor_position(2, 2)
    lcd.write('{}'.format(t))

    human = GPIO.input(human_pin)
    print(human)
    if human == 1:
      human_count+=1
    else:
      human_count=0
    
    try:
        devices = scanner.scan(interval)
    except Exception as e:
        print("ERROR",e)
        if getpass.getuser() != 'root':
            print('使用方法: sudo', argv[0])
            exit()
        sleep(interval)
        continue

    for dev in devices:
        print("\nDevice %s (%s), RSSI=%d dB" % (dev.addr, dev.addrType, dev.rssi))
        isRohmMedal = False
        sensors = dict()
        for (adtype, desc, val) in dev.getScanData():
            print("  %s = %s" % (desc, val))
            if desc == 'Short Local Name' and val[0:10] == 'ROHMMedal2':
                isRohmMedal = True
            if isRohmMedal and desc == 'Manufacturer':

                sensors['ID'] = hex(payval(2,2))
                sensors['Temperature'] = -45 + 175 * payval(4,2) / 65536
                sensors['Humidity'] = 100 * payval(6,2) / 65536
                sensors['Illuminance'] = payval(25,2) / 1.2
                sensors['Battery Level'] = payval(30)
                sensors['RSSI'] = dev.rssi

                print('    ID            =',sensors['ID'])
                print('    Temperature   =',round(sensors['Temperature'],2),'℃')
                print('    Humidity      =',round(sensors['Humidity'],2),'%')
                print('    Illuminance   =',round(sensors['Illuminance'],1),'lx')
                print('    Battery Level =',sensors['Battery Level'],'%')
                print('    RSSI          =',sensors['RSSI'],'dB')

                '''
                for key, value in sorted(sensors.items(), key=lambda x:x[0]):
                    print('    ',key,'=',value)
                '''

                temp  = sensors['Temperature']
                humid = sensors['Humidity']
                if temp > 26 or humid > 60:
                    temp_msg = "Hot!"
                else:
                    temp_msg = "Not bad"

                illum = sensors['Illuminance']
                if illum < 200:
                    illum_msg = "Dark!"
                else:
                    illum_msg = "Bright"

                if human_count > human_check:
                    human_msg = "Take Rest"
                else:
                    human_msg = "Work Hard!"

                lcd.clear()
                lcd.set_cursor_position(0, 0)
                lcd.write('Temp: {0:1.0f}C {1:1.0f}% {2}'.format(temp, humid, temp_msg))
                lcd.set_cursor_position(0, 1)
                lcd.write('Illum: {0:1.0f}Lx {1}'.format(illum,illum_msg))
                lcd.set_cursor_position(0, 2)
                lcd.write('{0:1.0f} Cnt {1}'.format(human_count, human_msg))

                sleep(interval)

 

このプログラムをsudo python3 ble_lcd.pyのように流すと、まず現在の日付、時間などを取得し表示します。

raspberrypi-comfortable-space-device-03-12

 

しばらくするとBLE経由でセンサメダルからの計測値が取得できます。すると温度や湿度、明るさなどを表示します。人感センサから何秒間そこに人がいるのかも見えます。

raspberrypi-comfortable-space-device-03-13

もし、室温が26℃以上か湿度が60%以上だと警告を発してくれます。また、明るさが200ルクス以下でもメッセージが変わります。

そして人感センサで一定以上検知し続けると(この時はテストのため30秒程度にしています)、「休みを取って!」と表示を変えています。

各センサでの閾値は、部屋の状況や仕事の状況に応じて変えてみてください。作業効率がいいとされるポモドーロ・タイム(25分働いて5分の休みを取る)などに合わせて、数値をセットするのもいいかもしれませんね。

 

3. まとめ

今回はセンサメダルに加え、人感センサもプラスして、デスク周りに人がいるかどうかをチェックできるようにしました。座りっぱなしのリモートワークでもそれに気を使ってくれるデバイスがあるといいですよね。

また、センサから取得した値を表示するLCDディスプレイも付けました。ハット型になっているものは、ライブラリなどを使うと簡単にデータを表示できます。もちろんLCDを自分で接続して使ってみても構いません。

次回は仕上げとして、インターネットから情報を取得したり、各種数値により行動を促すような仕組みをプラスして、快適デバイスを完成させます。

お楽しみに!

電子工作マニュアル Vol.3
ヨシケン(吉田 顕一)

普通の会社に勤めるサラリーマンですが、モノ作りが好きな週末メイカーで、電子書籍MESHBOOKを出したり、ブログを書いたりしています!

http://blog.ktrips.net