2021/12/15 よりサイトリニューアルしました

Raspberry Pi 4Bでエルチカ「タクトスイッチでトグル点灯」【Pythonの関数呼び出し】について

トグル動作Lチカ

前回のタクトスイッチによるLチカ(押した時のみ点灯)に続き、今回はスイッチを押すごとに点灯、消灯が入れ替わる「トグル」のLチカを作成します。

※前回のLチカはこちら↓

回路構成は前回と変わりないので、Pythonのプログラムだけ変更します。

念のため、回路構成などを乗っけておきます。

回路構成

回路図

タクトスイッチLチカ回路

プルダウンの回路のタクトスイッチでGPIO17に3.3Vを印可させると、GPIO4がHIGHになってLEDが点灯します。

17がインプット、4がアウトプットになります。

配線図

タクトLチカ配線図
GPIO

Pythonのプログラム

※2020/11/13 記述に誤りがありご指摘を頂きましたので修正いたしました。また、当記事のコメント欄にてよりスマートな記述を投稿して頂きましたので、是非そちらもご覧になってください。

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変換などをやろうかと思います。

7 COMMENTS

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のピン番号は変えちゃったけど、これでちゃんと動きましたわ

返信する
ketunorobio

どうもすみません!掲載しているコードで動かないみたいですね。。
後ほど修正させていただきます。ご指摘ありがとうございました!

返信する

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)

とりあえずこれで動きました

返信する
ketunorobio

ご丁寧に対応いただきありがとうございます!
非常に参考になります。
勝手ながらこちらのコードも、本記事内にて紹介させていただきます。

返信する

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です