RaspberryPi 3 Model B+と長距離透過形フォト・マイクロセンサで通過数をカウントする
Contents
長距離透過形フォト・マイクロセンサ
RaspberryPi 3 Model B+とオムロンの長距離透過型フォト・マイクロセンサ(EE-SPW311)を使って物体の通過検知のプログラムを作成した時の備忘録。
向かって左側の赤色のLEDが付いている方が受光器、右側が投光器になる。
以下の条件で動作するセンサーを探していた所、オムロンの EE-SPW311 がヒットしたので試してみることにした。
- 通過検知が可能なセンサー
- 距離は1m弱
- RaspberryPi で使いたい
アマゾンで4,688円(2019年当時)で購入した。
この手のセンサーとしては正直ちょっと高目だとは思ったが過去記事の赤外線センサー(TSSP77038)だと人が近くを通った時に誤検知をしてしまう事がまれにあるので2点間での通過検知の方がより精密なのではないかと思い、IoT の勉強も兼ねて購入してみた。
IoT の勉強とは言っても RaspberryPi に接続はするが今回のプログラムではインターネットに接続はしないので厳密に言うとIoT(Internet of Things)では無い事はお断りしておく。
やりたいこと
やりたいことのイメージ図は以下の通り。
通過検知センサーを使って物体が通過した件数を RaspberryPi でカウントしたい。
スペック
EE-SPW311 の主なスペックは以下の通り。
データシートはこちらを参照のこと。
電源電圧 | DC5(-5%)~24V(+10%) 5Vで動作するので RaspberryPi から電源をとることにした。 |
検出距離 | 1m |
検出物体 | 直径5mm以上 |
光源 | GaAs赤外発光ダイオード |
動作モード | 遮光時にON 尚、入光時にONになる EE-SPW411 もある |
端子配列
投光器
1 | DC5~24V |
2 | -(未使用) |
3 | GND(0V) |
受光器
1 | DC5~24V |
2 | OUTPUT RaspberryPiのGPIO5に接続するのだが、半固定抵抗を入れて3V付近まで電圧を落とした方が良い。 尚、電圧の計算方法は「ラズパイで半固定抵抗とADコンバーターから電圧を表示するプログラム」の抵抗の分圧計算式の章を参照して欲しい。 |
3 | GND(0V) |
RaspberryPiとの接続
RaspberryPi と EE-SPW311 との接続は以下の通り。
Output は 半固定抵抗を経由してGPIO5 に接続して半固定抵抗の目盛りを中央付近にするとおよそ out の半分程の電圧になる(抵抗の分圧計算より)。
事前準備
Python のデフォルトが Python 2.x になっている場合は事前に Python 3.x に変更することをオススメする。
過去記事の「RaspberryPiでPythonのデフォルトをPython2.7からPython3に変更する」を参照して欲しい。
プログラム
物体検出&カウントアップ用の Python の簡易プログラムは以下の通り。
もう少しスマートな書き方はあるの思うのでソースの公開はちょっと恥ずかしいのだけれども同じようなことをやりたい人達に少しでも役に立つのであればと思い公開する。
# -*- coding utf-8 -*-
"""
Created on 2019-08-04
EE-SPW311 Test Program
"""
from time import sleep
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM) # ピンをGPIOの番号で指定
SPW311 = 5 # ピンの名前を変数として定義
GPIO.setup(SPW311, GPIO.IN, pull_up_down=GPIO.PUD_UP) # GPIOセットアップ
#main
try:
if __name__ == '__main__':
find_flg = 0 # モノを見つけたフラグの初期化
counter = 0 # カウンターを初期化
while True:
if GPIO.input(SPW311) == GPIO.HIGH: # LOWからHIGHになる時にカウントアップ
if find_flg == 1: # 前回検知している
counter += 1
print("found",counter)
find_flg =0
else:
find_flg =1 # find(検知)
sleep(0.01)
except KeyboardInterrupt:
pass
GPIO.cleanup()
今であれば上記の様なフラグを使ったカウント方法は行わず、
GPIO.add_event_detect(SPW311, GPIO.RISING, callback=callback_func, bouncetime=200)
で callback_func の関数内で電圧の上昇を検知するロジックにすると思う。
add_event_detectについては以前の記事のソースコードを参照して欲しい。
カウントアップの考え方
- 物体検出:GPIO5=Low
- 物体未検出:GPIO5=High
となっているがGPIO5がHIGHになった時にカウントアップしている。
これは物体がセンサーの前を通り過ぎた後のタイミングでカウントしたいのでこの仕様にしている。
0.01秒間隔でGPIOを監視しているのでHigh、High・・・High、Low、Low・・・、Low、High、Highの様に検出される。
基本的な考え方は以前のこちらの記事のGPIOの推移(イメージ図)を参照して欲しい。
プログラムの実行結果
プログラムの実行結果は以下の通り。
センサーの前を物体が横切るたびにカウントアップされる。
以上で今回の記事を終了とする。
この記事が何処かで誰かの役に立つことを願っている。
尚、当記事中の商品へのリンクはAmazonアソシエイトへのリンクが含まれています。Amazonのアソシエイトとして、当メディアは適格販売により収入を得ていますのでご了承ください。
本ページを参考にさせて頂き、物体検知センサーを制作しようと試みているですが、
信号検知ができない状態でして、センサーはPTB-802 透過形光電センサというものを使用しています。
こちらで取り上げているセンサーとは配線方法異なるのか、ご教示いただけないでしょうか?
KKさん
コメントありがとうございます。
カタログを見る限りいけそうではありますね。
1)PTB-802ですが5Vと12Vがあるようです。5Vの方ですか
2)受光センサーのライトは光りますか(PTB-802-5DとPTB-802-5D1で動きが違うようです)
→まずはセンサーが正しく動作しているかの確認です
3)プルアップ抵抗ですがプルダウンを指定したらどうなりますか
GPIO.setup(SPW311, GPIO.IN, pull_up_down=GPIO.PUD_UP)
↓
GPIO.setup(SPW311, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
気がつくのはこれぐらいでしょうか。
souichirouさん
掲載プログラムそのまま使用したところ動作できました。
(プログラムは別に書いたものを使っていまして、早とちりな質問をしてしまいすみません。)
pull_up_down=の指定が必要なのですね。pull_up_down=GPIO.PUD_UPのままで動作しました。
DOWNに変えるとカウントしませんでした。
受光器は5v遮光時ONのPTB-802-5D1を使用していますが、この場合センサー内部スイッチのon/offと
GPIOへのhigh/lowは逆になるんですね。
それと投光器側はモバイルバッテリーから電源供給していましたが、
接続して何秒かで電源供給が遮断されることも改めてセンサーの動作確認でわかりました。
初歩的な質問ながらご丁寧に返答下さりありがとうございました。
KKさん
無事に動作したようで良かったですね。
pull_up_down指定は取得する電圧を安定化させる為の抵抗の指定です。
ほとんどのセンサーはPUD_UP指定で動作しますが、まれにPUD_DOWN指定が必要なセンサーがあるのでもしかしたらと思ったのですがUPで大丈夫だった様ですね。
後、遮光時ONとOFFではLOW、HIGHが逆になりますね。
はじめして
一点お聞きしたいのですが
ブログではセンサーとacアダプタを直接つないでおりますが
おすすめのACアダプタとかありますでしょうか?
コメントありがとうございます。
自分は秋月電子さんで以下のアダプターを購入しています。
またオン・オフをしたかったのでスイッチも一緒に購入しています。
・超小型スイッチングACアダプター12V0.5A AD-B120P50
・2.1mm標準DCジャック(2.5A) ON・OFFスイッチ付 基板取付用 MJ-R02
・DCジャック付ケーブル1.8m (2.1mm) MC-2376
特にこの構成でないと駄目という事はありません。
また電源タップ側にオン・オフスイッチがあるのならば、スイッチは不要になります。
ご丁寧に返信をしてくださいましてありがとうございます。
参考にさせていただきます。
souichirou様
はじめまして
上にある、てぃんか様の質問内容の通りにセンサーにACアダプタを実際に取り付けました。
実際にこのブログの内容の通りプログラムを書き、動作はしているものの
必ず途中でラズパイが落ち、黒い画面が表示されkarnel panicとメッセージが表示されてしまいます。
これは過電圧が原因で落ちてしまっているのでしょうか?
もし対策があればご教授いただけないでしょうか?
一応現在の環境も表記します。
————————————–
使用機器:
Raspberry Pi 4 Computer Model B
OS情報:
Distributor ID: Raspbian
Description: Raspbian GNU/Linux 10 (buster)
Release: 10
Codename: buster
————————————–
もりあ さん
こんにちは。
もしかしたら過電圧が原因かも知れませんね。
その場合は抵抗で電圧を落としてみてください。
受光器のOUTーーー2.2Kの抵抗ーーー+ーーーGIPO5
|
3.3Kの抵抗
|
GND
とすればGPIOへの電圧が下がります。
詳しくはこちらの記事の「抵抗の分圧計算式」の章をご参照ください。
元の電圧の3.3/(2.2+3.3)=3.3/5.5になる計算です。
また上記記事中にある半固定抵抗でも同じことが出来ます。
本文記事も後で修正をしておきます。
はじめまして。
センサーをEE-SPW411(入光時on)に変更した場合のプログラムについての質問です。
遮光時onと入光時onでは論理を逆転すればよい、というサイトを見ました。
このコードにおいて、SPW311をSPW411に置換し、さらに
19行目
if GPIO.input(SPW311) == GPIO.HIGH:
の部分を
if GPIO.input(SPW411) == GPIO.LOW:
にすれば、EE-SPW311を使った場合と同様に動作するのでしょうか?
kabi さん コメントありがとうございます。
そうですね。
その修正でHIGHからLOWに変わる瞬間をカウントすれば良いと思います。
上記の修正で動作するとは思いますが、ブログ中で2021年6月8日に追記してる通り、フラグを使うよりも、
GPIO.add_event_detect を使った方がよりスマートだと思います。
使い方はこちらの記事を参考にして下さい。
上記のGPIO.RISINGの部分をGPIO.FALLINGとすればHIGHからLOWに変わる瞬間を捉えることができます。
ご返信ありがとうございます。試させていただきます。