前回、LINE Notifyを使って簡単に画像を送ることができました。次は、定期的にLINEに画像を送る下準備として、定期的に動作させる方法を考えてみたいと思います。

pythonでプログラムを書いていきます(^o^)

構想だけ(というか実装できる気がしない)

こちらの記事を参考にして、10分ごとに写真を撮り、前回写真と差分があればLINEする というのも考えました

送る画像を減らせてAPIの節約になることと、猫の動きがわかるメリットがありますが、日暮れで暗くなった場合にしきい値が変わるので誤って撮ってしまいそうでした

ですので、実装やめました(てかできない)

なので、変化ありなしに関わらず、10分ごとに写真を撮ってLINEすることにします

time.sleep()はイマイチ

イマイチというのは、今回の用途には合わないということです

真っ先に思いつくsleepは例えば10分止める場合は以下のように書けます

import time

time.sleep(600) # 600秒(=10分)スリープ

イマイチなところは、処理を止めてしまうのでその間に他のことができなくなってしまうことです

お安いWEBカメラ

10分スリープして、直後に撮影をすると画像が真っ暗になりました

お安いWEBカメラにはシャッター時間を長くとって明るさを確保しないと画像が暗いということがよくあるようですが、私の数年前のWEBカメラも漏れずそんな感じみたいです

撮影する少し前に起動して、明るくなったら撮影する必要があります

というわけでsleepは却下〜

起動処理は以下記事内にあるこの文↓

ret, frame = capture.read()

タイマー割り込み? → 無い😇

別の方法としてタイマー割り込みを考えてみます

割り込みであればメインループでカメラを起動しておき、時間が来たら割り込みの処理を実行する(撮影する)ため明るさの問題は回避できそうです

10分毎に割り込み処理が入るようにすれば、10分毎の動作が可能です

し・か・し

どうやらラズパイにはタイマー割り込みがない模様・・・(pythonで書く場合)

こちら↓の方が質問をされています

残念〜

python以外(Cとか?)で制御するならできなくは無さそうですが、敷居はとっても高そうです

割り込みはありますが、外部入力でGPIOに変化があったことをトリガーにする動作なのでタイマー割り込みではありません

メインループ内で時間を測る

割り込みが使えないので、正確な時間は測れ無さそうです

ですが、10分毎に動作のように分オーダーの時間であれば数秒程度の誤差なら全く問題にならなそうです

というわけで、メインループ内で時間を測ることにしました

import time

old = time.time() # 現在時刻取得(sec)

while(True): # main loop
  time0 = time.time() # 現在時刻取得
  delta = time0 - old # 差分

  if delta > 600: # 差が600sec(=10分)以上だったら
    print(delta) # 確認
    old = time0 # 古い値を保持

はじめにoldに現在時刻を取得して格納します

その後、メインループに入り都度時間を取得し、oldとの差分をdeltaに格納します

そしてその差分deltaが10分以上となった時に処理を実行します

問題点

問題点はメインループの速度に依存してしまうことです

メインループに時間がかかる処理があれば、その分遅れも大きくなるため、誤差が大きくなります

上のプログラムなら、600秒”以上”という条件でifとしているので、遅い処理があれば600.1秒にも600.2秒にもなる可能性があります

ただもう一度になりますが、今回のように分オーダー毎の処理なら気にならない誤差だと思いますので許容しています

おわり(^o^)