第4回:ボタンを押すごとにLEDのON/OFFの切替え

つぶやき

トグル動作とは何か?

「トグル動作」とは、ボタンを押すごとに状態が切り替わる挙動のことを指します(例えば ON → OFF → ON → …)。
これは、ボタンを 押している間だけ ON、という「押下中維持」型とは異なり、押した瞬間に切り替わり、あとは次に押されるまでその状態を保持する方式です。

この動きはユーザーインターフェース(UI)や機械制御のスイッチ類で頻繁に使われます。たとえばテレビの電源ボタン、階段照明の切り替えスイッチなどです。

本稿では、マイコン(例えば Raspberry Pi Pico W など)を使ったボタン入力から LED 出力までのトグル実装を題材に、動作原理・注意点・応用へと展開します。


ボタン入力の基本と「押された瞬間」検出の考え方

ボタンの物理挙動・スイッチ構造

ボタンは物理的には接点が開閉する機構を持ち、押下や離下によって接点(メタル接触片)が互いに接触・分離します。
この構造ゆえに、“押された瞬間”を正確に検出するためには、押されている間ずっと ON にするのではなく、押された瞬間をトリガーとして処理を行うという設計が重要です。

「押された瞬間」だけ反応させる理由

単純に button.value() が 1 になっている間ずっと LED を ON にしてしまうと「押しっぱなし」中にも不要な切り替えや誤反応が起きやすくなります。
トグル動作を実現するためには、「ボタンが“未押下”から“押下”に変化した瞬間(立ち上がりエッジ)」を検出する必要があります。
つまり、前回の状態を保持し、今回の状態と比較して変化があったときだけ反応させる手法です。

この考え方が、サンプルコードでも使われています:

if current == 1 and prev_button == 0:
    …切り替え処理…

サンプルコードと解説

サンプルコード

from machine import Pin
import utime

button = Pin(16, Pin.IN, Pin.PULL_DOWN)  # ボタン入力
led = Pin('LED', Pin.OUT)                # LED出力

led_state = 0     # 現在のLED状態(0=OFF, 1=ON)
prev_button = 0   # 前回のボタン状態

while True:
    current = button.value()  # 今のボタン状態を取得

    # ボタンが「押されていない→押された」に変化した瞬間を検出
    if current == 1 and prev_button == 0:
        led_state = not led_state   # 状態を反転
        led.value(led_state)        # LEDに反映

    prev_button = current  # 状態を保存
    utime.sleep(0.02)      # チャタリング防止のため待機

各行のポイント

  • Pin(16, Pin.IN, Pin.PULL_DOWN)
     ボタンを入力ピン GPIO16 に割り当て、内部プルダウン抵抗により未押下時は 0 を維持。
  • led = Pin('LED', Pin.OUT)
     オンボードLED出力用のピン設定。
  • led_state = 0
     LEDの状態を管理する変数。
  • if current == 1 and prev_button == 0:
     この条件において「前回押されていない → 今回押された」という遷移を検出。
  • led_state = not led_state
     Python ではビット反転ではなく真偽反転(0⇄1)がこの書き方で可能。
  • utime.sleep(0.02)
     20 ms 程度の待機を入れることで、チャタリング(スイッチバウンス) の影響を減らす(後述)。

チャタリング(スイッチバウンス)問題とその対策

チャタリングとは?

スイッチのメカニカル接点は、押した/離した際に接触と分離を数回高速に繰り返すことがあります。
この現象を “バウンス(bounce)” と呼び、マイコンが高速に状態変化を検知すると「押されたはずが複数回検出された」ような誤動作を起こします。
このため、デジタル回路では「バウンスを除去(デバウンス)」する処理が必須です。

ソフトウェアによるチャタリング防止

代表的な手法としては、以下のようなものがあります:

  • ボタン状態が変化したら一定時間 (10~50 ms) 待ってから再確認する。
  • 状態が一定時間安定していることを確認してから反応させる。
  • 割り込み+タイマーを併用して、変化後一定時間無視する。

本サンプルでは utime.sleep(0.02)、すなわち 20 ms の固定待機を使っていますが、実際にはスイッチの特性・使用環境によって 20〜50 ms 程度が目安とされます。

ハードウェアによるデバウンス

抵抗+コンデンサ(RCフィルタ)やスイッチングICを使って入力信号を平滑化する方法もあります。
ただし、マイコン+ソフトウェアで処理可能ならハード構成を簡素化できます。


状態反転(トグル)処理の設計ポイント

簡潔に実装できる反転処理

Python では led_state = not led_state によって、0⇄1 の反転を簡単に行えます。
多くの言語でも論理反転や XOR 演算(例:led_state ^= 1)で同様の処理が可能です。

状態遷移モデルを整理する

「ボタンが押された瞬間に反転 → 次に押されるまで状態維持」というモデルを意識すると、

  • 状態管理変数(例:led_state
  • 前回ボタン状態(例:prev_button
    を設けることで、誤検出を防ぎやすくなります。

まとめ

「ボタンを押すごとに LED の ON/OFF を切り替えるトグル動作」をテーマに、実装例・技術解説・チャタリング対策を説明しました。
トグル制御というシンプルな課題であっても、実運用を考えると「押された瞬間を正確に検出」「チャタリング除去」「状態管理」「拡張設計」など多くの設計要素が出てきます。

参考URL

Switch Debounce in Digital Circuits - GeeksforGeeks
Your All-in-One Learning Portal: GeeksforGeeks is a comprehensive educational platform that empowers learners across dom...
How to Implement a Software-Based Debounce Algorithm for Button Inputs on a Microcontroller
Explore how to eliminate false button presses due to mechanical switch bounce using an Arduino software debounce algorit...

コメント