siroitori0413のアイコン画像

Raspberry Pi Zeroで作るカメラ付きIoTポスト

siroitori0413 2021年08月28日に作成  (2021年08月28日に更新)

Raspberry Pi Zeroで作るカメラ付きIoTポスト

カメラ付きIoTポスト

郵便を通知してくれるIoTポストを初めて作ってみました。
カメラをつけてポストの中の画像を見られるようにしました。

マンションのポストで自宅Wi-Fiは届かないため、SORACOMのIoT通信プラットフォームを使用しています。

材料

郵便が来たかどうかの判定では、最初チルトセンサー(チルトスイッチ)を使って実現しようとしましたが、うちの郵便受けにはマッチせず、今回は距離センサ―を使用しました。

ネットにIoTポストの情報はわりとありますが、センサーや形態はさまざまです。
実際に自分の家・モノに合うかどうか試してみるの大事ですね。

構成

キャプションを入力できます
これを100均のケースに収納しました。
カメラは角度と高さを固定したかったのでカメラの固定部分だけ3Dプリンターで自作しました。

キャプションを入力できます
距離センサーは郵便受けの底に固定させて郵便物との距離を測定することにしました。

配線図
LEDは抵抗入りのものを使っているので抵抗を挟まず直接続しています。

ポストの中の設置の様子
(画像ではカメラの固定部分が3Dプリントする前の段ボールで作ったものになっています)

プログラム

iot_post_distance.py

# coding: utf-8 # Your code here! import RPi.GPIO as GPIO import time import math import subprocess import os import datetime import requests from picamera import PiCamera #GPIO Mode (BOARD / BCM) GPIO.setmode(GPIO.BCM) #set GPIO Pins GPIO_TRIGGER = 17 GPIO_ECHO = 27 Led_pin = 18 #変数"Led_pin"に18を格納 #set GPIO direction (IN / OUT) GPIO.setup(GPIO_TRIGGER, GPIO.OUT) GPIO.setup(GPIO_ECHO, GPIO.IN) GPIO.setup(Led_pin, GPIO.OUT) #GPIO18を出力モードに設定 #Camera Module camera = PiCamera() camera.resolution = (1024, 768) #----------------------------------- #US-015 距離計測 #----------------------------------- def distance(): # set Trigger to HIGH GPIO.output(GPIO_TRIGGER, True) # set Trigger after 0.01ms to LOW time.sleep(0.00001) GPIO.output(GPIO_TRIGGER, False) StartTime = time.time() StopTime = time.time() # save StartTime while GPIO.input(GPIO_ECHO) == 0: StartTime = time.time() # save time of arrival while GPIO.input(GPIO_ECHO) == 1: StopTime = time.time() # time difference between start and arrival TimeElapsed = StopTime - StartTime # multiply with the sonic speed (34300 cm/s) # and divide by 2, because there and back distance = (TimeElapsed * 34300) / 2 return distance #----------------------------------- #ログ出力関数 #----------------------------------- def logPrint(str): dt_now = datetime.datetime.now() dt_str = dt_now.strftime('%Y年%m月%d日 %H:%M:%S') print(dt_str + " " + str) return try: logPrint("iot_post_distance.py [start]") isPosting = False while True: isPostAndWait = False waitCounter = 0 while (isPostAndWait==False): cm = distance() #距離を測定する # print("TEST distance=", int(cm), "cm") if ( cm >= 0 and cm < 400 ) or (cm > 1000): #距離が0~400cm または1000より大の場合 #print("distance=", int(cm), "cm") #距離をint型で表示 if (cm < 5 or cm > 1000): logPrint("[POSTING]distance=" + str(int(cm)) + "cm") #距離をint型で表示 if isPosting: waitCounter+=1 #ポスティング判定CountUp else: waitCounter=1 logPrint("waitCounter = " + str(waitCounter)) isPosting = True else: isPosting = False else: print("[incorrect value at Posting]distance=" + str(int(cm)) + "cm") #incorrect value if waitCounter >= 10: #10秒待つ isPostAndWait = True else: time.sleep(1) #1秒間待つ # LED ON GPIO.output(Led_pin, GPIO.HIGH) #GPIO18の出力をHigh(3.3V)にする # take Photo camera.start_preview() time.sleep(2) #warm up camera.capture("test.jpg") camera.stop_preview() logPrint("[Take Photo Done]") # SORACOM Harvestに送信 data = None with open('./test.jpg', 'rb') as f: data = f.read() requests.post('http://harvest-files.soracom.io', data=data, headers={'Content-Type': 'image/jpeg'}) logPrint("[SORACOM Harvestに送信 Done]") # LED OFF GPIO.output(Led_pin, GPIO.LOW) #GPIO18の出力をLow(0V)にする waitCounter = 0 isNoPost = False while isPosting: cm = distance() #距離を測定する if ( cm >= 0 and cm < 400 ) or cm > 1000: #距離が0~400cmまたは1000より大の場合 #print("distance=", int(cm), "cm") #距離をint型で表示 if ( cm >= 5 and cm < 400 ): logPrint("[NOPOSTING]distance=" + str(int(cm)) + "cm") #距離をint型で表示 if isNoPost: waitCounter+=1 else: waitCounter=1 logPrint("np waitCounter = " + str(waitCounter)) isNoPost = True #ポストから物が取り除かれた else: print("[incorrect value at no Posting]distance=" + str(int(cm)) + "cm") #incorrect value if waitCounter >= 10: #10秒待つ isPosting = False else: time.sleep(1) #1秒間待つ except KeyboardInterrupt: #GPIOをクリーンアップ GPIO.cleanup() pass

ポイント

  • ポスティング判定
    距離センサ―測定値が5センチ未満または1000センチ以上のときに郵便物がある判定としました。1000以上というのは、郵便物が距離センサーのどちらの目もぴったりふさいでしまったときに大きな値が出てしまうのでそれを測定するためです。
    距離計測に異常値が出ることがあるので、10回以上続けて郵便物あり判定の時にポスティング判定とすることにしました。
    10秒待つことで、急に光って郵便配達の人を驚かせないようにするという意図もあります。

  • 写真撮影・SORACOM送信
    ポスティング判定のときに写真撮影とその画像をSORACOM Harvestへ送信します。

  • ポスティングが取り除かれた判定
    そのままループさせると郵便物が取り除かれるまでいつまでも郵便物の画像が送信され続けてしまうので、写真撮影・SORACOM送信が終わったら郵便物がポストから無くなるのを待ちます。これも、10回郵便物が無い判定のときにポスティングが取り除かれた判定とすることにしました。

  • ログの出力
    標準出力にprintするように作りました。
    テスト時はそのままpythonで実行すればコマンドラインから確認出来て良いですし、本番環境で実行させるときは下記のように実行させることでログに書き出すようにしました。

python3 iot_post_distance.py >& iot_post_log.log
  • LEDの点灯
    写真撮影・SORACOM送信の間LEDを点灯させることにしました。
    カメラ撮影時に少しでも明るくしたいということと、外から見てポスティング判定されたというのがわかるようにという意図です。

SORACOM Lagoon

SORACOM Hervesst へ送ったデータを SORACOM Lagoonで可視化しました。

SORACOM Lagoon
ダッシュボードでの表示1
ダッシュボードでの表示2
右側に撮影履歴、左側に最新の画像が表示されます。
1枚目は文字が読めるほどきれいに撮影できましたがこういうことはあまりなく、何が写っているのかよくわからないことがほとんどですが…何かあるのはわかるのでこれで良しとします。

リアルタイムで通知させる仕組みは自分使いするのにあまりメリットを感じられなかったので今回省略しました。(近頃何かと通知が多いので全部無視してしまう傾向にあり意味が無いので。)
そろそろ郵便来てるかな?と思ったときにSORACOM Lagoonで確認するという感じにしました。

実行動画

ここに動画が表示されます

まとめ

IoTのシステムは実際に作ってみて実際に動かしてみないとうまく動作できるものであるかわからないので、案外試行錯誤しました。

うまく実行できることを確認しましたが、以下懸念点があり今後の課題です。

  • 長時間稼働
    まだ長い時間稼働させていないので途中で止まってしまわないか気になるところです。
    バッテリーもどれくらい持つか気になります。毎日1回は郵便物をポストから出すと考えて1日1回のバッテリー交換でいけると良いなと思います。

  • ログの改良
    長時間稼働に伴いログはファイルが大きくなりすぎる可能性があるので、ログを一定時間単位でわけるなど考える必要があります。(ログ出力を無くしてもよいかもしれませんが)

  • カメラの調整
    郵便物の状態によってはカメラにうつらないですが、これはどうやってもうつらないときはうつらないですし郵便物がカメラに覆いかぶさったら真っ暗ですね。
    きちんと撮れても何かよくわからないことが多いです。

  • LEDが光ると怪しい
    カメラ撮影・SORACOM送信時に光らせるようにしたLEDですが、外から見ているとちょっと(かなり)怪しく住人に通報されないか心配です。
    「郵便物通知システム稼働中のため光ることがあります」のような注意書きをつけておいたほうが良いかもしれません。

怪しく光るポスト

siroitori0413のアイコン画像
https://siroitori.hatenablog.com/
ログインしてコメントを投稿する