今回はRaspberry Pi Zeroと赤外線人感センサーを使って睡眠時間のロギングシステムを構築したので紹介。
といっても全然大したものではなくて、単純にベッドに人感センサーを向けて定期的に検出を行い、検出されたらログに追記するという仕組み。
モノ
試作1号。。ひどい見た目だけど検証用途としては要はデータ取れたらなんでも良いのでマスキングテープが活躍。
ラズパイのGPIOピン18番に人感センサーのデータピンを接続している。
センサーはAmazonでHC-SR501を検索すると適当なメーカーのものがいくつもヒットする。
私はHiletGo社のものを買ったけど今は在庫切れのようだ。まぁどれでも同じだと思う。
プログラム
ラズパイで実行させる検出プログラム
以下は10秒ごとに人体検出を試み、検出されたらファイルに記録して次の検出まで60秒間検出停止する。
まだ検証段階なので特にデーモン化等は考えておらず、SSHで繋いで実行させたらSSHセッションそのまま保持させている。
from datetime import datetime import time import RPi.GPIO as GPIO INTERVAL = 10 SLEEPTIME = 60 GPIO_PIN = 18 GPIO.setmode(GPIO.BCM) GPIO.setup(GPIO_PIN, GPIO.IN) if __name__ == '__main__': try: print ("To Cancel:CTRL+C") cnt = 1 while True: if(GPIO.input(GPIO_PIN) == GPIO.HIGH): with open('/home/thom/data.csv', 'a') as f: print(datetime.now().strftime('%Y-%m-%d %H:%M:%S') + ', 1', file=f) print(datetime.now().strftime('%Y-%m-%d %H:%M:%S') + ', 1') cnt = cnt + 1 time.sleep(SLEEPTIME) else: print(datetime.now().strftime('%Y-%m-%d %H:%M:%S')) time.sleep(INTERVAL) except KeyboardInterrupt: print("Closing") finally: GPIO.cleanup() print("GPIO cleaned")
PCでデータ加工用に作成中のプログラム
出力データはそのままでは非常に見づらいのでpandasを使って1時間単位の検出回数を集計する。
import pandas as pd df = pd.read_csv('./sleepdata.csv', header=None, parse_dates=[0]) df = df.resample('60T', on=0).sum() df = df.loc[df[1] > 0] with pd.option_context('display.max_rows', None, 'display.max_columns', None): print(df)
1週間記録してみたデータ
プログラムで加工しただけでも一応分かるものの、入眠と起床が分かりにくいので空行で区切ってコメントを付けてみた。
見返すと酷い生活リズム。。最近色々テクノロジー系にハマってたのでその弊害かなと思う。
# 仮眠 2022-04-01 17:00:00 55 2022-04-01 18:00:00 29 # 睡眠 2022-04-02 01:00:00 10 2022-04-02 02:00:00 12 2022-04-02 03:00:00 40 2022-04-02 04:00:00 28 2022-04-02 05:00:00 37 2022-04-02 06:00:00 20 2022-04-02 07:00:00 30 2022-04-02 08:00:00 60 2022-04-02 09:00:00 45 2022-04-03 06:00:00 32 2022-04-03 07:00:00 35 2022-04-03 08:00:00 42 2022-04-03 09:00:00 53 2022-04-03 10:00:00 36 # 仮眠→爆睡 2022-04-03 17:00:00 13 2022-04-03 18:00:00 36 2022-04-03 19:00:00 50 2022-04-03 20:00:00 35 2022-04-03 21:00:00 52 2022-04-03 22:00:00 14 # 睡眠 2022-04-04 02:00:00 34 2022-04-04 03:00:00 13 2022-04-04 04:00:00 40 2022-04-04 05:00:00 39 2022-04-04 06:00:00 43 2022-04-04 07:00:00 59 2022-04-04 08:00:00 25 2022-04-05 03:00:00 20 2022-04-05 04:00:00 47 2022-04-05 05:00:00 52 2022-04-05 06:00:00 35 2022-04-05 07:00:00 53 2022-04-05 08:00:00 51 2022-04-05 09:00:00 5 # 仮眠 2022-04-05 17:00:00 18 2022-04-05 18:00:00 58 2022-04-05 19:00:00 60 2022-04-05 20:00:00 48 # 睡眠 2022-04-06 02:00:00 14 2022-04-06 03:00:00 37 2022-04-06 04:00:00 50 2022-04-06 05:00:00 22 2022-04-06 06:00:00 48 2022-04-06 07:00:00 45 2022-04-06 08:00:00 52 # 睡眠 2022-04-06 23:00:00 28 2022-04-07 00:00:00 31 2022-04-07 01:00:00 55 2022-04-07 02:00:00 49 2022-04-07 03:00:00 52 2022-04-07 04:00:00 44 2022-04-07 05:00:00 60 2022-04-07 06:00:00 60 2022-04-07 07:00:00 51 2022-04-07 08:00:00 46 2022-04-07 09:00:00 9 # 仮眠 2022-04-07 17:00:00 10 2022-04-07 20:00:00 10 # 睡眠 2022-04-07 22:00:00 14 2022-04-07 23:00:00 52 2022-04-08 00:00:00 55 2022-04-08 01:00:00 44 2022-04-08 02:00:00 51 2022-04-08 03:00:00 60 2022-04-08 04:00:00 60 2022-04-08 05:00:00 17 2022-04-08 06:00:00 8
ちなみに平日の9時台に数件検出されてるのはサボりとか遅刻ではなくて、センサーの検出時間を最大にしてるのでベッドを離れても数分検出が続くためだ。ここ2年くらいは在宅勤務なので8時55分くらいまで寝てることがある。。
難点と改良
最初はセンサーの感度をMAXにしてたけど、部屋の前を横切っただけでベッド上にいる判定になってしまうので、検出感度を下げてみた。ところが感度が低いと検出精度が悪かったので取り付け方向を変えて段ボールフードで覆うことで枕を狙い撃ちすることにした。これまたひどいビジュアルだけど。。
あとそもそも人感センサーは動きを検出するので静止してると検出しない。
普通の人間は寝てる間もモゾモゾするので検出しないわけではないものの、周期的に静止状態になるので深い眠りに落ちている間の検出ができなかったりする。本当は15分単位でデータ集約したかったんだけど、それだと起きてる判定になる時間が多かったので精度を落として1時間単位の集約とした。
まぁそもそもベッドに居る=寝てるとは限らないので、Kindle読んでたりスマホいじってたりする時間を除くと最近十分な睡眠がとれているかどうかは怪しいのだが。
今後の展望としてはデータ加工まではラズパイ側で対応して、メイン機に転送してグラフ表示をしたい。
3Dプリンターでちゃんとしたラズパイケースとかセンサー用のフードを作るのはそこまでできた後で良いかな。。ダサイけど。
以上