2022年01月20日 更新
どうも、クラゲです。
ラズパイにタクトスイッチを付けて基本的なプログラミングを行います。主に、GPIOを常時チェックして処理する方法とGPIOに変化があったときのみ処理する方法の2通りあります。
この動画はLチカとの組合せで、スイッチを押したら5回だけ点滅しています。こちらのコードも最後に紹介します。
[TOC]
今回はRaspberry Pi 4 B を使用しました。別のラズパイでも問題ありません。
ラズパイ以外に必要な部品は以下3点です。
色や大きさなどは好みで構いません。
以下のように接続してください。
タクトスイッチは縦置きか横置きかで向きがありますが、図のように挿さる向きであればOKです。
ラズパイ側は上から3番目のピンと6番目のピンです。上側がGround
で下側がGPIO18
という端子です。
import time
#GPIOの初期設定
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
#GPIO18を入力端子設定
GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP)
while True:
#スイッチ状態取得
sw_status = GPIO.input(18)
#画面出力
if sw_status == 0:
print('スイッチON!')
else:
print('')
#少し待つ
time.sleep(0.3)
実行結果は以下のようになります。
動画ではディスプレイの代わりにスマホにVNCを導入していますが、皆さんはPCで問題ありません。
スイッチのオン/オフに関わらずPythonの表示は0.3秒毎に流れます。スイッチオンのときにスイッチON!
と表示されています。短押し、長押しによって表示数も異なります。
GPIO入力のポイントだけ説明します。
GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP)
今回接続しているGPIO18
をGPIO.IN
、つまり入力として設定しています。
pull_up_down=GPIO.PUD_UP
という引数で「プルアップ」という設定を行っています。
今回の回路ではスイッチが押されていないときのGPIOの入力値は1
で、スイッチが押されたときの値は0
を期待しています。
実際のところ、スイッチが押されていない状態のとき、GPIO端子は不定な状態となり、何かのノイズで1
がたまに入力されてしまう場合があります。そこで入力端子に置いては「プルアップ」もしくは「プルダウン」という処理が必要です。
今回のようにスイッチを押すことでGPIO端子がGround
と導通する回路の場合は「プルアップ」を設定します。
sw_status = GPIO.input(18)
変数sw_status
にGPIO18
の値を入力しています。
スイッチが押されていないときのGPIOの入力値は1
で、スイッチが押されたときの値は0
です。
time.sleep(0.3)
表示後にちょっとだけ一時停止しないと表示が速く流れ過ぎてしまうため、0.3秒だけスリープさせています。
import time
#GPIOの初期設定
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
#GPIO18を入力端子設定
GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP)
while True:
#スイッチ押下待ち
GPIO.wait_for_edge(18, GPIO.FALLING)
#画面出力
print('スイッチON!')
#チャタリング対策
time.sleep(0.3)
実行結果は以下のようになります。
先程と異なり、スイッチを押したときのみ表示されます。短押しも長押しも関係なく処理されています。
先程からの変化点のみ解説します。
GPIO.wait_for_edge(18, GPIO.FALLING)
この記述で、GPIO18
の値に変化が起きるまでここで待つことになります。
変化にも種類があります。主に立ち上がりエッジGPIO.RISING
なのか立ち下がりエッジGPIO.FALLING
なのかを指定します。
これはスイッチを押したときか、スイッチ押しを離したときのどちらかを検知したいかで変わってきます。今回はスイッチを押したときを検知させています。
スイッチを押していないときが1
で、スイッチを押している間が0
ですので、1 → 0
の変化、つまりGPIO.FALLING
を指定するということになります。
time.sleep(0.3)
先程と違って今回はずっと待つのでスリープは不要です。しかし、このスリープを外して実験してみると分かりますが、1回押しているだけなのに数回押されたかのような結果になる場合があります。このような現象を「チャタリング」と呼んでいます。タクトスイッチによる機械的な弾性振動が原因です。
いくつか対策がありますが、最も簡単なのはプログラミングでスリープを入れることです。今回は0.3秒を設定してます。スリープ時間を長くすればする程、チャタリングをより確実に防げる一方、連続押しの応答がどんどん悪くなるという事態になりますので注意が必要です。
冒頭の動画のコードです。
Raspberry Pi で Lチカのときと同じようにLEDと抵抗も必要になります。
import time
#GPIOの初期設定
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
#GPIO17を出力端子設定
GPIO.setup(17, GPIO.OUT)
#GPIO18を入力端子設定
GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP)
while True:
#消灯
GPIO.output(17, 0)
#スイッチ押下待ち
GPIO.wait_for_edge(18, GPIO.FALLING)
counter = 1
while True:
#点灯
GPIO.output(17, 1)
#0.2秒スリープ
time.sleep(0.2)
#消灯
GPIO.output(17, 0)
#0.2秒スリープ(チャタリング対策も兼ねる)
time.sleep(0.2)
if counter >= 5:
break
counter = counter + 1
今回のプログラムでは点滅してる間はスイッチ入力は受け付けていません。何かのタスクを行っている最中もスイッチ入力を行いたい場合は「割り込み」という処理が必要になりますので調べてみて下さい。
以上、Raspberry Piでスイッチ入力でした!