ヘルニアクソ野郎エンジニアblog

~ヘルニアでHell near~

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

calendar

reload

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

前回のタクトスイッチによる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変換などをやろうかと思います。

この記事をシェアする

コメント

  • inprt→import
    GPIO.→GPIO,

    by あ 2020年11月13日 3:27 PM

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

    by あ 2020年11月13日 3:53 PM

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

      by ketunorobio 2020年11月13日 4:05 PM

  • if channel==17:
    これは必ずTrueになるにで省けるみたいです

    by あ 2020年11月13日 6:01 PM

  • 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:
    にすればいいと思います。

    by あ 2020年11月13日 6:24 PM

  • 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)

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

    by あ 2020年11月13日 6:28 PM

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

    by ketunorobio 2020年11月13日 10:16 PM

down コメントを残す