Raspberry Piと人感センサーで人の検知


授業でIoTを使ったシステムを作成したのでメモ．

# センサー
今回用いた人感センサーはRaspberry Pi スターター学習キットに入っている人感センサーを用いた．
[Amazon | Raspberry Pi スターターキット](https://www.amazon.co.jp/初心者演習用パーツセット-回路配線図とサンプルスケッチ有り-スターター学習キット-リレーモジュール制御-赤外線リモコン等IoTを実践する電子部品セット/dp/B01M6ZFNSS/ref=sr_1_3?ie=UTF8&qid=1506848597&sr=8-3&keywords=raspberry+pi+starter+kit)

![humansensor.jpg](https://qiita-image-store.s3.amazonaws.com/0/152224/abedf22f-3a7a-7b1a-5bc8-8734a56154e6.jpeg "humansensor.jpg")

人感センサーを2つ下図のように取り付けることで，外のセンサー -> 内のセンサーの順で反応すると人が入って来た判定をし，逆の順番だと外に出たと判定する仕組みを作成する．

![sensor_position.jpg](https://qiita-image-store.s3.amazonaws.com/0/152224/2d18cd61-3114-19a6-f787-0dd00b2c5488.jpeg "sensor_position.jpg")


# プログラム
このRasperry Pi スタータキットのサンプルコードが公式に上がっているので，以下を参照してコードを記述した．
[Raspberry Pi Starter Kit Lesson 16: Raspberry Pi and PIR Motion Sensor | osoyoo](http://osoyoo.com/ja/2017/07/04/raspi-pir-motion-sensor/)

## ライブラリ
以下のライブラリをインポートする．後で，センサーが反応した後に処理を実行する際に違うプロセスで実行するためにmultiprocessingを入れている．

```py3
import RPi.GPIO as GPIO
import time
import os
import pexpect # to automatically input password for scp
import getpass
from multiprocessing import Pool
```

## GPIOの番号設定

人感センサーの値は，GPIOの16，17番に繋いでいるので，

```py3
PIRPinIn = 17
PIRPinOut = 16
```
とピンの番号を取得する．

## main関数
main関数の動作としては，
* 初期化 
* センサーの値取得
* Ctrl + C の時のKeyBoard Interrupt処理
の3つで構成されている．

```py3
if __name__ == '__main__':
    setup() # 色々初期化
    try:
            main()
    #when 'Ctrl+C' is pressed,child program destroy() will be executed.
    except KeyboardInterrupt:
        destroy()
        pass
```

## setup関数
``GPIO.setwarning(False)``でWarningを表示しないようにし，``GPIO.setmode(GPIO.BCM)``でRaspberry Piで指定されたGPIOの番号でピンの指定を行うようになっている．``GPIO.setup([1],[2])の[1]で先ほど定義したピンの番号を格納した変数を指定．[2]でINなら入力モード，OUTなら出力モードになる．

```py3
def setup():
    GPIO.setwarnings(False)
    #set the gpio modes to BCM numbering
    GPIO.setmode(GPIO.BCM)
    #set BuzzerPin's mode to output,and initial level to HIGH(3.3V)
    #GPIO.setup(BuzzerPin,GPIO.OUT,initial=GPIO.HIGH)
    GPIO.setup(PIRPinIn,GPIO.IN)
    GPIO.setup(PIRPinOut,GPIO.IN)
```

```py3
def main():

    while True:
        #read Sw520dPin's level
        if(GPIO.input(PIRPinIn)!=0):
            starttime=time.time()
            runtime = 0
            print ('********************')
            print ('*     In Sensor!     *')
            print ('********************')
            print ('\n')
            while(runtime < 3):
                runtime = time.time() - starttime
                if(GPIO.input(PIRPinOut)!=0):
                    print("=============")
                    print("    Out    ")
                    print("=============")
                    time.sleep(5)
                    setup()
                    break
            time.sleep(1)

        elif(GPIO.input(PIRPinOut)!=0):
            starttime=time.time()
            runtime = 0
            print ('*******************')
            print ('*    Out Sensor    *')
            print ('*******************')
            print('\n')
            while(runtime < 3):
                runtime = time.time() - starttime
                if(GPIO.input(PIRPinIn)!=0):
                    print("===============")
                    print("     In      ")
                    print("===============")
                    time.sleep(5)
                    break
            time.sleep(1)
        else:
            #print ('====================')
            print ('=     Not alarm...  =')
            #print ('====================')
            print ('\n')
        time.sleep(1)
```

プログラムのフローは下図である． 
片方のセンサーが反応してから，3秒間もう片方のセンサーが反応をするのを待ち，反応したら，入室/退室判定を行う．


![flow.jpg](https://qiita-image-store.s3.amazonaws.com/0/152224/eb2889ee-3085-5515-63ed-97a6a6cdeadc.jpeg "flow.jpg")

# 実行結果
画像が小さいが，入り口を出ると，"In Sensor" -> "Out Sensor"の順に反応して，Out判定を行う． 

![demo.gif](https://qiita-image-store.s3.amazonaws.com/0/152224/46f4bd03-9c07-9a18-a9a7-917e3381f0a2.gif "demo.gif")


# まとめ
今回は，Raspberry Piで人感センサーで人の入退出の検出を行なった．今回は，デバイス等のリソースに制限があったので，こんな構築になりましたが，実際は，カメラ2台やRaspberry Pi2台のほうが，高精度の検出が可能な感じがします．