Raspberry Pi Zeroで作るカメラ付きIoTポスト
カメラ付きIoTポスト
郵便を通知してくれるIoTポストを初めて作ってみました。
カメラをつけてポストの中の画像を見られるようにしました。
マンションのポストで自宅Wi-Fiは届かないため、SORACOMのIoT通信プラットフォームを使用しています。
材料
- Raspberry Pi Zero WH
- ラズパイカメラモジュール
- US-015超音波距離測定モジュールセンサー
- 抵抗入りLED
- SORACOM スターターキット(3G USBドングル AK-020)
- SORACOM USBドングル接続用USBケーブル(Bオス-Aメス)…100均で購入
- モバイルバッテリー・ケーブル
- ジャンパワイヤ
郵便が来たかどうかの判定では、最初チルトセンサー(チルトスイッチ)を使って実現しようとしましたが、うちの郵便受けにはマッチせず、今回は距離センサ―を使用しました。
ネットに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で可視化しました。
右側に撮影履歴、左側に最新の画像が表示されます。
1枚目は文字が読めるほどきれいに撮影できましたがこういうことはあまりなく、何が写っているのかよくわからないことがほとんどですが…何かあるのはわかるのでこれで良しとします。
リアルタイムで通知させる仕組みは自分使いするのにあまりメリットを感じられなかったので今回省略しました。(近頃何かと通知が多いので全部無視してしまう傾向にあり意味が無いので。)
そろそろ郵便来てるかな?と思ったときにSORACOM Lagoonで確認するという感じにしました。
実行動画
まとめ
IoTのシステムは実際に作ってみて実際に動かしてみないとうまく動作できるものであるかわからないので、案外試行錯誤しました。
うまく実行できることを確認しましたが、以下懸念点があり今後の課題です。
-
長時間稼働
まだ長い時間稼働させていないので途中で止まってしまわないか気になるところです。
バッテリーもどれくらい持つか気になります。毎日1回は郵便物をポストから出すと考えて1日1回のバッテリー交換でいけると良いなと思います。 -
ログの改良
長時間稼働に伴いログはファイルが大きくなりすぎる可能性があるので、ログを一定時間単位でわけるなど考える必要があります。(ログ出力を無くしてもよいかもしれませんが) -
カメラの調整
郵便物の状態によってはカメラにうつらないですが、これはどうやってもうつらないときはうつらないですし郵便物がカメラに覆いかぶさったら真っ暗ですね。
きちんと撮れても何かよくわからないことが多いです。 -
LEDが光ると怪しい
カメラ撮影・SORACOM送信時に光らせるようにしたLEDですが、外から見ているとちょっと(かなり)怪しく住人に通報されないか心配です。
「郵便物通知システム稼働中のため光ることがあります」のような注意書きをつけておいたほうが良いかもしれません。
投稿者の人気記事
-
siroitori0413
さんが
2021/08/28
に
編集
をしました。
(メッセージ: 初版)
-
siroitori0413
さんが
2021/12/20
に
編集
をしました。
ログインしてコメントを投稿する