前回のタクトスイッチによるLチカ(押した時のみ点灯)に続き、今回はスイッチを押すごとに点灯、消灯が入れ替わる「トグル」のLチカを作成します。
※前回のLチカはこちら↓
回路構成は前回と変わりないので、Pythonのプログラムだけ変更します。
念のため、回路構成などを乗っけておきます。
回路構成
回路図
プルダウンの回路のタクトスイッチでGPIO17に3.3Vを印可させると、GPIO4がHIGHになってLEDが点灯します。
17がインプット、4がアウトプットになります。
配線図
Pythonのプログラム
※2020/11/13 記述に誤りがありご指摘を頂きましたので修正いたしました。また、当記事のコメント欄にてよりスマートな記述を投稿して頂きましたので、是非そちらもご覧になってください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
import RPi.GPIO as GPIO from time import sleep def toguru(channel): global led if channel==17: led=not led if led==GPIO.HIGH: GPIO.output(4,GPIO.HIGH) else: GPIO.output(4,GPIO.LOW) GPIO.setmode(GPIO.BCM) GPIO.setup(4,GPIO.OUT,initial=GPIO.LOW) GPIO.setup(17,GPIO.IN) GPIO.add_event_detect(17,GPIO.RISING,callback=toguru,bouncetime=200) led=GPIO.LOW try: while True: sleep(0.01) except KeybordInterrupt: pass GPIO.cleanup() |
4~11行目が「関数」のブロックになります。この部分は、「必要に応じて読み込まれる」プログラムですので、上段にあるからといって先に実行されるわけではありません。
下段にある「callback」の変数が読み込まれた時点で、動作する仕組みになっています。
初期化のブロックには、14行目に「initial=GPIO.LOW」を加えていますが、これはプログラム開始時に、GPIO4がLOW(LED消灯)で始まるように宣言しています。
16行目の記述は、イベント処理の内容になります。「RISING」は、信号がLOWからHIGHへ上がる瞬間の事を指しています。これを「ポジティブエッジ」と呼び、それの検出になります。今回の場合だとタクトスイッチが押された事を検出するといった内容になります。
その後に続く「callback=toguru」は、RISINGを検出した際に実行する関数の指定先を表しています。callbackの変数にtoguruを入れているので、関数の読み込み先は4行目の「toguru」になっています。
その後の「bouncetime=200」は、RISING検出後に200ミリ秒は検出しないようにする記述です。これは、下図のようにLOWからHIGHになる瞬間にノイズが入る事があり、誤検出を招く恐れがあることから検出のタイミングを少しずらしてノイズを回避させています。
気になる本文ですが、while文が「sleep(0.01)」だけとなっています。これはとりあえずプログラムを動かし続ける為だけの記述です。ここに関数を入れた方が個人的にはしっくりくるのですが、どうも設計上できないっぽいですね。(多分。。)
それでは、今回のプログラムの一連の流れをまとめたいと思います。字で書くのめんどいので、下図にまとめます。
18行目の変数「led」を、7行目のnotでHIGH,LOWを反転させてトグルを再現させています。
なお、5行目の「global led」は、変数ledにglobalを付けることによって関数内でも使用できるようにしているみたいです。結構重要ですね。
実際の動作はこんな感じになります。
次回はAD変換などをやろうかと思います。
inprt→import
GPIO.→GPIO,
import RPi.GPIO as GPIO
from time import sleep
def toguru(channel):
global led
if channel==17:
led=not led
if led==GPIO.HIGH:
GPIO.output(18,GPIO.HIGH)
else:
GPIO.output(18,GPIO.LOW)
GPIO.setmode(GPIO.BCM)
GPIO.setup(18,GPIO.OUT,initial=GPIO.LOW)
GPIO.setup(17,GPIO.IN,pull_up_down=GPIO.PUD_UP)
GPIO.add_event_detect(17,GPIO.RISING,callback=toguru,bouncetime=200)
led=GPIO.LOW
while True:
sleep(0.01)
#GPIOのピン番号は変えちゃったけど、これでちゃんと動きましたわ
どうもすみません!掲載しているコードで動かないみたいですね。。
後ほど修正させていただきます。ご指摘ありがとうございました!
if channel==17:
これは必ずTrueになるにで省けるみたいです
led=not led
これでledの内容を反転していますが、GPIOの反転はその後の
if led==GPIO.HIGH:
GPIO.output(4,GPIO.HIGH)
else:
GPIO.output(4,GPIO.LOW)
でできるので、反転したものをまた反転する無駄な処理になっています。
ですから、
global led
と
led=not led
と
led=GPIO.LOW
を削除して、
if led==GPIO.HIGH:
を
if GPIO.input(4) == GPIO.HIGH:
にすればいいと思います。
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
GPIO_IN = 17
GPIO_OUT = 18
def i(GPIO_IN):
if GPIO.input(GPIO_OUT) == GPIO.HIGH:
GPIO.output(GPIO_OUT,GPIO.LOW)
else:
GPIO.output(GPIO_OUT,GPIO.HIGH)
GPIO.setup(GPIO_OUT,GPIO.OUT,initial=GPIO.LOW)
GPIO.setup(GPIO_IN,GPIO.IN,pull_up_down=GPIO.PUD_DOWN)
GPIO.add_event_detect(GPIO_IN,GPIO.FALLING,callback=i,bouncetime=200)
while True:
time.sleep(0.01)
とりあえずこれで動きました
ご丁寧に対応いただきありがとうございます!
非常に参考になります。
勝手ながらこちらのコードも、本記事内にて紹介させていただきます。