#はじめに
Raspberry Pi(Raspbian)で写真を撮るプログラムの紹介です。
カメラモジュールの準備方法は下記を参照して下さい。
#必要なもの
- RaspbianがインストールされているRaspberry Pi
- Raspberry Pi用のカメラモジュール
- ブレッドボード
- タクトスイッチ
- ジャンパー線(オス/メス)x2
#配線
GPIOとGNDならどこでも可ですが、今後の拡張性などを考えるとGPIOのみのピン(3, 5, 8, 10, 19, 21, 23, 24, 25以外)を使う方が無難だと思います。
この投稿では37(GPIO26), 39(GND)ピンを使用しています。
#プログラム
#Import Files
import RPi.GPIO as GPIO
import picamera
import time
#GPIO Settings
GPIO.setmode(GPIO.BCM)
GPIO.setup(26, GPIO.IN, pull_up_down=GPIO.PUD_UP)
#Camera Settings
CAM_DIR = "/home/pi/python/_photo/"
camera = picamera.PiCamera()
#Main
try:
while True:
if GPIO.input(26) == 0:
filename = time.strftime("%Y%m%d%H%M%S") + ".jpeg"
save_dir_filename = CAM_DIR + filename
camera.capture(save_dir_filename)
except KeyboardInterrupt:
GPIO.cleanup()
#解説
- スイッチの制御に使用する
RPi.GPIO
ライブラリをインポートする - Raspberry Piのカメラモジュールの制御に使用する
picamera
ライブラリをインポートする - 時間を取得するために使用する
time
ライブラリをインポートする - GPIOのモードをBCMに設定する(物理的なピン番号ではなく、GPIO**を使用する)
- GPIO26を入力端子に設定し、状態をプルアップ(Hi)にする(Hi=OFF, Low=ON)
-
CAM_DIR
に保存先のディレクトリを設定する - PiCameraクラスのインスタンスを生成する
- スイッチが入力されるのを待つ必要があるので
while True:
で無限ループさせる - スイッチが押されたら(GPIO26がLowになったら)写真を撮る処理を行う
-
time.strftime
でスイッチが押された時の日時を取得する -
time.strftime
で取得した日時+拡張子(.jpeg)をファイル名にする -
CAM_DIR
で指定したディレクトリとファイル名を連結させる -
camera.capture
で写真を撮る -
CAM_DIR
で指定したディレクトリに写真を保存する - 解説9に遷移 or プログラムが終了するのを待つ
- Control+Cが押されたらGPIOを解放してプログラムを終了する
#プログラムを実行してみる
- プログラムを実行する
- スイッチを押す
-
CAM_DIR
で指定したディレクトリに写真が保存される - スイッチを押したら写真を撮るプログラム完成
- ファイル名が固定ではないので何回写真を撮ってもデータが上書きされない
#写真が何枚も撮れてしまう問題の対処法(1)
#Main
try:
while True:
time.sleep(0.1)
if GPIO.input(26) == 0:
filename = time.strftime("%Y%m%d%H%M%S") + ".jpeg"
save_dir_filename = CAM_DIR + filename
cam.capture(save_dir_filename)
except KeyboardInterrupt:
GPIO.cleanup()
チャタリング対策のため、time.sleep(待ち時間)
の処理を追加する。
time.sleep(0.01)
で10ms、time.sleep(0.1)
で100ms、time.sleep(1)
で1s待つ。
待ち時間を長くするとスイッチを押しているのに反応しないように感じるため、100〜200ms程度が無難。
この方法だとスイッチを長押しした場合に何枚も写真が撮れてしまう問題が発生する。
短押しで1枚、長押しで連写とするのであれば問題ないが、長押しでも1枚としたい場合は別の対策が必要になる。
#写真が何枚も撮れてしまう問題の対処法(2)
#Main
try:
while True:
if GPIO.input(26) == 0:
filename = time.strftime("%Y%m%d%H%M%S") + ".jpeg"
save_dir_filename = CAM_DIR + filename
cam.capture(save_dir_filename)
time.sleep(1)
except KeyboardInterrupt:
GPIO.cleanup()
time.sleep(待ち時間)
の処理を追加し、写真を撮る処理を行ってから一定時間は写真を撮る処理を行わないようにする。
この方法でも写真が何枚も撮れてしまう問題の対処法(1)
同様、スイッチを長押しした場合に何枚も写真が撮れてしまう問題が発生する。
#写真が何枚も撮れてしまう問題の対処法(3)
#Import Files
import RPi.GPIO as GPIO
import picamera
import time
#GPIO Settings
GPIO.setmode(GPIO.BCM)
GPIO.setup(26, GPIO.IN, pull_up_down=GPIO.PUD_UP)
#Camera Settings
CAM_DIR = "/home/pi/python/_photo/"
camera = picamera.PiCamera()
#Camera Function
def camera_func(x):
if GPIO.input(26) == 0:
filename = time.strftime("%Y%m%d%H%M%S") + ".jpeg"
save_dir_filename = CAM_DIR + filename
camera.capture(save_dir_filename)
#Interrupt
GPIO.add_event_detect(26, GPIO.FALLING, callback=camera_func)
#Main
try:
while True:
pass
except KeyboardInterrupt:
GPIO.cleanup()
-
#Main
内にあった写真を撮る処理
をcamera_func(x)
に分離 - スイッチを押したら
camera_func(x)
を実行するようGPIO.add_event_detect
を追加 -
while True:
内の処理が無くなったのでpass
を追加
上記の対策を行うことでスイッチ押下時のみ写真を撮るようになる。
#参考
-
GPIO.FALLING
はスイッチ押下時に処理を行う -
GPIO.RISING
はスイッチを離した時に処理を行う