- 8×8、16ビットLEDディスプレイ
- 慣性測定ユニット(加速度、ジャイロ、磁力)
- 気圧センサ
- 温度センサ
- 湿度センサ
- 4 + 1ジョイスティック(上下左右 + 押し込み)
今回はこのSense HATを使い、ドアの開閉検知を行うプログラムを作ってみます。
Sense HATの注意点
Sense HATはとても高機能なHATで、高精度な加速度センサーが組み込まれています。このセンサーは、ただ置いておくだけでも常に値が揺れてしまいます。そのため、今回は小数点以下2桁までを対象としています。
acceleration = sense.get_accelerometer_raw() x = acceleration['x'] # 他に acceleration['y']、acceleration['z']があります x = round(x, 2)
ただし、2桁にしても値が 0.01と0.02を揺れてしまうので、ある程度の範囲(±0.01)の範囲は誤差として開閉検出しないようにしています。
# 開閉していないかチェックする関数 # 開閉を開始している場合(moving = True)はさらに誤差が大きくなるので ±0.08 としています def acceleration_range(old, num, moving): if moving: r = 0.08 else: r = 0.01 if num == old: return True if num >= old + r: return True if num <= old - r: return True return False
この辺りは実際に動かしながら試してみるのが良いでしょう。
窓(引き戸)の場合
まず試したのが窓です。左右方向に動くだけの動きを検出するパターンになります。単純にデータをグラフ化すると次のようになります。これは最初閉まっていて、窓を開けた後、戻した場合です。
このグラフを見て分かる通り、閉めるときに最後強い衝撃が加わっています。開けるときにはあまり大きな数字の動きにはなっていません。
では実際のコードです。まずSense HATを用意します。これはRaspberry OSに標準で組み込まれています。
#!/usr/bin/env python from sense_hat import SenseHat import time sense = SenseHat()
次に変数を準備します。old_x
は1つ前のX座標の値を保存しています。 moving
は開閉が開始されたら True にします。 is_open
は True だったら開ける動作、 False だったら閉める動作を意味しています。
try: old_x = 0 moving = False is_open = False while True: # この中に処理を書いていきます # 古い値を保存 old_x = x except KeyboardInterrupt: # Ctrl + Cで終了した場合 sense.clear()
Sense HATからのデータ取得は先ほども書きましたが sense.get_accelerometer_raw()
で行います。これで x/y/z軸それぞれの値が返ってきます。今回はX軸のみ扱います。
acceleration = sense.get_accelerometer_raw() x = acceleration['x'] x = round(x, 2) # 小数点以下2桁まで対象
そして先ほど紹介した値のブレを吸収するための acceleration_range
関数が False 、つまり窓の開閉動作を検知したら moving
を True にします。また、ここからは実行時間を0.04秒遅らせています。これは実際に試してみたのですが、あまり頻繁に加速度を検知すると、開いている最中でも動作が止まったと判断されてしまうためです。この辺りも皆さんの環境ごとに試しながら確認してください。
if acceleration_range(old_x, x, moving) == False: moving = True time.sleep(0.4) else: # この後説明
開閉しきった際には上記のelseに処理が移ります。 moving
がTrueだったならば、開閉フラグ is_open
の状態によって窓を開いたか閉じたかを出力しています。
if moving: moving = False is_open = not is_open if is_open: print("Open") else: print("Close")
今回は標準出力しているだけですが、クラウドの保存したり、メールやSlack通知すると言った動作につなげるのは簡単でしょう。
ドアの場合
続いてドアの場合です。こちらもデータをグラフ化してみました。
これを見て分かるのは、飛び抜けて高い(または低い)値(+0.04以上または-0.01以下)を検知した時が閉める、または開ける動作と言えそうです。先ほどのコードを参考に、同じように実装したのが次のコードになります。
from sense_hat import SenseHat sense = SenseHat() def acceleration_range(old, num, moving): if moving: r = 0.08 else: r = 0.01 if num == old: return True if num >= old + r: return True if num <= old - r: return True return False try: old_x = 0 moving = False is_open = False while True: acceleration = sense.get_accelerometer_raw() x = acceleration['x'] x = round(x, 2) if x >= 0.04: # 開ける動作 is_open = True moving = True elif x <= -0.01: # 閉める動作 is_open = False moving = True elif acceleration_range(old_x, x, moving) == False: # 停止状態の判定 # 開閉中であれば、メッセージを出す if moving: moving = False if is_open: print("Open") else: print("Close") is_open = not is_open old_x = x except KeyboardInterrupt: sense.clear()
これでドアを開けた時、閉めた時を検知できるようになります。
まとめ
Sense HATの値が常に動き続けるので、どこを閾値にするかは試してみないと分かりません。恐らくドアの種類や開閉方向などによって異なるはずです。一度データをグラフ化してみて、閾値を判定するといいでしょう。
入退室の検知や会議室の利用状態、自宅の防犯など開閉検知が使える場面は多そうです。ぜひSense HATを活用してください。
]]>