- 第3回 IoT電子工作入門講座 RaspberryPi Pico 2Wでボタン入力・LED制御動画はこちら
- この記事でわかること
- RaspberryPi Pico 2W で Thonny を使う方法(コードを実行するまで)
- RaspberryPi Pico 2W のサンプルコードをGitHubから取得する
- RaspberryPi Pico 2W ピンアウト図の読み方(GPIO番号と物理番号の違い)
- RaspberryPi Pico 2W のボタン入力の仕組み(デジタル入力とは)
- プルアップ・プルダウン抵抗の役割
- RaspberryPi Pico 2W の配線手順(Grove拡張基板で簡単接続)
- RaspberryPi Pico 2W 基本プログラム①:ボタンを押している間LEDが点灯する
- チャタリングとは?(原因と仕組み)
- チャタリング対策①:単純遅延方式(ソフトウェア)
- チャタリング対策②:割り込み(irq)を使う方法
- チャタリング対策③:ハードウェア(CR積分回路)
- エッジ検出で「押した瞬間」をとらえる
- RaspberryPi Pico 2W 応用プログラム:ボタンでLEDをトグル動作させる(MicroPython)
- RaspberryPiPico2Wがうまく動かない時のトラブルシューティング
- まとめ・次回予告
第3回 IoT電子工作入門講座 RaspberryPi Pico 2Wでボタン入力・LED制御動画はこちら
この記事はこんな方におすすめ
- Pico 2Wの第2回(Lチカ)を終えて、次にボタン操作へ進みたい方
- MicroPythonでスイッチ入力を初めて試す方
- チャタリングという言葉は知っているけど、対策のやり方は知らない方
前回の第2回では環境構築から始まり、LEDを光らせる「Lチカ」を体験しました。
前回の解説記事はこちら。
LEDを点けたり消したりするのは、マイコンから外へ信号を出す「出力」の世界でした。
今回はその逆、外から信号を受け取る「入力」に挑戦します。具体的にはGrove Buttonを押すとLEDが光る、という双方向のやり取りを作ります。
入力ができるようになると、IoTの幅が一気に広がります。
センサーの値を読む、スイッチで動作を切り替える、そうした「外の世界の状態を読み取る」処理はすべて入力が土台だからです。
この記事ではデジタル入力の仕組みから、プルアップ・プルダウン抵抗、そして初心者がほぼ必ずハマるチャタリングの除去まで、実際に動くMicroPythonコードで順番に解説します。
まだ環境構築が済んでいない方は、第1回・第2回の記事を先に読んでおくとスムーズです。
第1回の準備編はこちら。
第2回の環境構築・Lチカ編はこちら。
この記事でわかること
この記事を読むと、以下のことが分かります。
この記事で分かること
- デジタル入力とデジタル出力の違い
- プルアップ・プルダウン抵抗の役割と仕組み
- Grove Button の特殊仕様(押すとHIGHになる理由)
- Thonny でコードを実行するまでの手順
- GitHub からサンプルコードを取得する方法
- MicroPython の
machine.Pinクラスの詳細 - チャタリングの原因と3種類の対策方法
- 動かない時のトラブルシューティング手順
RaspberryPi Pico 2W で Thonny を使う方法(コードを実行するまで)
Pico 2W のプログラムを書いて実行するには、Thonny という IDE(統合開発環境)を使います。
まだインストールしていない方は第1回や第2回を参照してください。
Thonny の画面構成
Thonny を起動すると、画面がに分かれています。

右上が「①エディタエリア」でコードを書く場所です。
右下側が「②シェル」でコードの実行結果が表示される場所です。
右下に「Raspberry Pi Pico」と表示されていれば、Pico 2W が認識されています。
表示されていない場合は USB ケーブルを抜き差しして、トラブルシューティングを確認してください。
左側には「④ファイルブラウザ」が表示されています。
コードを貼り付けて保存する
右上のエディタエリアにコードを貼り付けます。
「ファイル → 名前をつけて保存」を選ぶと、保存先として「このコンピューター」と「Raspberry Pi Pico」の2択が出ます。
「Raspberry Pi Pico」を選んでファイル名(例:button_led_basic.py)を入力して保存します。

Pico 2W 本体にコードが保存されます。
コードを実行する
ツールバーの緑の三角ボタン(実行ボタン)をクリックします。

シェルに「スイッチ入力プログラム開始」と表示されれば、プログラムが動いています。
プログラムを止めるときは、赤い四角ボタン(停止ボタン)をクリックします。

RaspberryPi Pico 2W のサンプルコードをGitHubから取得する
この講座のサンプルコードは GitHub で公開しています。
手打ちしなくてもコードをそのまま取得できます。
リポジトリ URL:https://github.com/Python-Electronics-Thunderblog/raspberrypi-pico2w-iot-course
ファイルの場所
リポジトリ(ファイルの保管庫)ページを開いたら、lesson03_switch フォルダをクリックします。

今回使うファイルが入っています。
01_button_led_basic.py:基本プログラム(押している間だけ点灯)02_button_led_advance.py:応用プログラム(チャタリング除去+トグル動作)
ファイルの取得方法
取得したいファイル名をクリックすると、コードが表示されます。
右上の「Raw」ボタンをクリックすると、コードのみの画面になります。
Ctrl+A で全選択 → Ctrl+C でコピーして、Thonny のスクリプトエディタに貼り付けてください。
「Download raw file」ボタン(下矢印のアイコン)を使うと、ファイルをそのままダウンロードすることもできます。

RaspberryPi Pico 2W ピンアウト図の読み方(GPIO番号と物理番号の違い)
Pico 2W には 40 本のピンがあります。
コードでピン番号を指定するときに混乱しやすいポイントがあるので、最初に整理しておきます。
GPIO 番号と物理ピン番号の違い
ピンの番号には2種類あります。「物理ピン番号」はボードの端から数えた番号で、1から40まであります。
「GPIO 番号」は、マイコンの信号線に付けられた番号です。
MicroPython のコードで指定するのは GPIO 番号です。
Pin(16, Pin.OUT) と書いたら「GPIO 16番のピン」を意味します。物理ピン番号の16番とは違うので注意してください。
今回使うピン
今回の配線では、以下の GPIO を使います。
- LED:GPIO 16(物理ピン21 / Grove Base HatではD16コネクタ)
- ボタン:GPIO 18(物理ピン24 / Grove Base HatではD18コネクタ)

Grove Base Hat を使えば「D16」「D18」とシルク印刷されたコネクタに挿すだけなので、物理ピン番号を意識する必要はありません。
ピンアウト図を確認したい場合は「Raspberry Pi Pico 2W pinout」で検索すると、公式の PDF が入手できます。
RaspberryPi Pico 2W のボタン入力の仕組み(デジタル入力とは)

まず「デジタル入力」とは何かを押さえましょう。
デジタル入力とは、マイコンが外部からの信号を「HIGH(高い電圧)」か「LOW(低い電圧)」の2つの状態として読み取る仕組みのことです。
RaspberryPi Pico 2W(以下、Pico 2Wと略します。)の場合、HIGHはおよそ3.3V、LOWはほぼ0Vを意味します。
マイコンはこのHighかLowの2段階を見ています。
デジタルの世界では、中間の電圧はあいまいで嫌うので、回路側で「きっちりHIGHかLOW」を作ってあげる必要があります。
(ちなみに、アナログは中間電圧を扱います。第4回ではアナログである照度センサーを使います。)
これが後で出てくる抵抗の話につながります。
ボタンを押すという行為は、この電圧を切り替える操作です。
マイコンはGPIO(汎用入出力ピン)でその電圧変化を監視し、「いま押されている」「いま離れている」を判断します。
私はハードウェアの開発を本業にしていますが、入力回路は「マイコンに何を読ませたいか」を電圧で表現する設計だと考えると、一気に理解が進みます。
デジタル出力とデジタル入力の違い
前回のLチカは「デジタル出力」でした。
マイコンがピンに電圧を出して、LEDを光らせる。
主導権はマイコン側にあります。
今回の「デジタル入力」は完全に逆です。
電圧を決めるのは外側(ボタン)で、マイコンはそれを読み取るだけ。
主導権は外の世界にあります。
コードの上でもこの違いははっきり出ます。
出力は Pin.OUT で設定して led.value(1) のように値を書き込みます。
入力は Pin.IN で設定して switch.value() のように値を読み出します。
書くのか読むのか、ここが出力と入力の決定的な差です。
最初のうちは「OUTは命令、INは観測」と覚えておくと混乱しません。
次のステップでは、ボタンを押したとき電圧が実際にどう動くのかを見ていきます。
ボタンを押すと電圧はどう変わる?
ボタンの中身は、ただの金属接点です。
押すと2つの端子がつながり、離すと切れる。電気的にはスイッチのON/OFFそのものです。
問題は「ボタンがつながったときに、マイコンのピンへどんな電圧が届くか」です。
これは配線のしかた次第で変わります。
同じボタンでも、つなぎ方によって「押すとHIGH」にも「押すとLOW」にもなるのです。
ここがデジタル入力で最初につまずくポイントです。
ボタンを押した=1(HIGH)になる、とは限りません。
むしろ一般的な電子工作の入門記事では「押すとLOW(0)になる」配線が主流です。
なぜそうなるのか、そしてGrove Buttonはどちら側なのか。その答えがプルアップ・プルダウン抵抗の話です。
プルアップ・プルダウン抵抗の役割

プルアップ抵抗・プルダウン抵抗とは、ボタンが押されていないときのピンの電圧を「あらかじめ決めておく」ための抵抗です。
プルアップは電源側(3.3V)へ、プルダウンはグラウンド側(0V)へ、ピンを軽く引っ張っておきます。
「軽く引っ張る」と書いたのは、抵抗を通して弱くつないでいるからです。
ボタンが押されたときは、もっと強い経路で電圧が決まるので、抵抗の力は負けてくれます。
この関係がプルアップ・プルダウンの肝です。
抵抗がないと何が起きる?──フローティング
抵抗を入れず、ボタンとピンだけをつないだ状態を考えてみます。
ボタンを離している間、ピンはどこにもつながっていない「宙ぶらりん」の状態になります。
これをフローティング(浮いた状態)と呼びます。
フローティングのピンは、まわりのノイズを拾ってHIGHになったりLOWになったりフラフラします。
マイコンから見ると「押してないのに押された判定が出る」「値が暴れる」といった不安定な動きになります。
これを防ぐのがプルアップ・プルダウン抵抗です。
ボタンを離している間も、抵抗がピンの電圧をHIGHかLOWのどちらかへ確実に固定してくれます。
だから入力回路には必ずどちらかの抵抗が必要になるわけです。
自分で抵抗を付けるのは少し面倒ですが、安心してください。
今回使うGrove Buttonには、この抵抗が最初から基板に載っています。
次の項目でその「載っている向き」が重要になります。
Grove Buttonはスイッチを押すとHIGHが出る
ここが今回いちばん大事なポイントです。

Grove Buttonはボタンを離している間はLOW(0V)に固定され、押すとHIGH(3.3V)に切り替わります。
一般的なスイッチ接続とは逆の動作です。一般的な使い方は、ボタンを離しているときがHIGH、スイッチを押すとGNDに接続されてLOWとすることが多いです。
このように多くのマイコン入門記事は「プルアップ接続(押すとLOW=0)」を前提にしています。
その感覚のままGrove Buttonのコードを書くと、「押してないのに反応する」「押しても無反応に見える」と混乱します。
私も最初これで首をかしげました。
整理すると、こうなります。
Grove Buttonは後者です。
だから今回のコードでは「switch.value() が 1 なら押された」と判定します。
ネット上の多くのサンプルとは判定が逆になる、ここを必ず覚えておいてください。
なお今回のコードはピンを Pin.IN だけで設定します。
Grove Buttonの基板にプルダウン抵抗がすでに載っているため、マイコン内蔵のプル抵抗を使う必要がないからです。
意図をコード上ではっきりさせたい場合は Pin(SWITCH_PIN, Pin.IN, Pin.PULL_DOWN) と書いて内蔵プルダウンを併用しても問題ありません。
RaspberryPi Pico 2W の配線手順(Grove拡張基板で簡単接続)
配線はGroveケーブルを使うので、とても簡単です。

ハンダ付けもブレッドボードも不要で、ケーブルを挿すだけで完成します。
これで配線は完了です。
ボタンモジュールがD18、LEDモジュールがD16です。
この対応はあとでコードのピン番号と一致させるので、ここで覚えておいてください。
ちなみに今回のGrove LEDモジュールは、基板側に電流制限抵抗が組み込まれているので追加の抵抗は不要です。
もしLEDを単体(生のLED)で使う場合は、電流制限抵抗(LEDに流れる電流を抑えるために直列に入れる抵抗)を必ず入れてください。
抵抗値の求め方の計算ツールを作りました。抵抗値を計算してくれるので便利です。
RaspberryPi Pico 2W 基本プログラム①:ボタンを押している間LEDが点灯する
配線ができたら、いよいよプログラムです。
まずは「ボタンを押している間だけLEDが光る」という、いちばんシンプルな基本プログラムを作ります。
このコードは、ボタンの状態を一定間隔で読み取り、押されていればLED点灯・離されていればLED消灯する、という単純な仕組みです。
入力と出力をつなぐ最小の形なので、ここをしっかり理解すると応用が一気に楽になります。
サンプルコード全文
このコードは、スイッチの状態を10ミリ秒ごとに確認して、その結果をそのままLEDに反映するためのものです。
switch.value() が 1(押された)かどうかを見ているのがポイントです。
Grove Buttonはプルダウン接続なので、押されたときが 1 になります。
from machine import Pin
import time
# ピン番号の定義
LED_PIN = 16 # LEDをつなぐピン(GP16 = D16コネクタ)
SWITCH_PIN = 18 # スイッチをつなぐピン(GP18 = D18コネクタ)
# 待機時間の定義
SLEEP_TIME = 0.01 # 10ms ごとにスイッチを確認する
# スイッチ状態の定義
SWITCH_PRESSED = 1 # スイッチが押されている状態
SWITCH_RELEASED = 0 # スイッチが離されている状態
# LED状態の定義
LED_ON = 1 # LED点灯
LED_OFF = 0 # LED消灯
# ピン設定
led = Pin(LED_PIN, Pin.OUT)
switch = Pin(SWITCH_PIN, Pin.IN) # Grove Button基板内蔵のプルダウンを使用
print("スイッチ入力プログラム開始")
# メインループ
while True:
switch_state = switch.value()
if switch_state == SWITCH_PRESSED:
led.value(LED_ON)
else:
led.value(LED_OFF)
time.sleep(SLEEP_TIME)
Code language: Python (python)
実行すると、コンソールに「スイッチ入力プログラム開始」と表示され、あとはボタンを押している間だけLEDが点灯します。
押せば光り、離せば消えます。
もし「押しても消えたまま」「押してないのに光る」という場合は、配線のコネクタ(D18・D16)と、ピン番号の対応を見直してください。
なお、このサンプルプログラムおよび後半の応用プログラムは下記のGitHubで公開しています。
今後公開するプログラムも追加していく予定ですので、是非参考にしてください。
コードの解説
最初の from machine import Pin と import time は、ピン操作と待機処理に必要なモジュールの読み込みです。
MicroPythonでハードを触るときの定番なので、毎回書くものと思ってください。
次に各種の番号や状態を定数として名前付きで定義しています。
SWITCH_PRESSED = 1 のように名前を付けておくと、あとでコードを読んだとき「1って何だっけ?」と悩まずに済みます。
とくに SWITCH_PRESSED = 1 の「1」は、Grove Buttonがプルダウン接続で押すとHIGHになるからこの値です。
ここに意味を込めておくのが大事です。
led = Pin(LED_PIN, Pin.OUT) でLEDのピンを出力に、switch = Pin(SWITCH_PIN, Pin.IN) でスイッチのピンを入力に設定しています。
出力は書き込む、入力は読み取る、という役割の違いがそのまま設定に出ています。
while True: の無限ループの中で、switch.value() でいまのスイッチ状態を読み取り、押されていれば点灯・そうでなければ消灯しています。
最後の time.sleep(SLEEP_TIME) は10ミリ秒の待機で、マイコンに少し休みを与えてループが暴走しないようにしています。
machine.Pin クラスの詳細
from machine import Pin は、MicroPython に標準で入っている machine モジュールから Pin クラスを取り込む命令です。
GPIO ピンを操作するために必要です。
Pin(LED_PIN, Pin.OUT) はピン番号 16 を出力として設定します。
Pin.OUT を指定すると、コードからこのピンに電圧を出力できるようになります。
Pin(SWITCH_PIN, Pin.IN) はピン番号 18 を入力として設定します。
Pin.IN を指定すると、このピンにかかっている電圧を読み取れるようになります。
switch.value() は、入力ピンの現在の状態を読み取ります。
Grove Button が押されていれば 1、離されていれば 0 が返ります。
led.value(LED_ON) は、出力ピンに値を書き込みます。
1 を書き込むと 3.3V が出力されて LED が点灯し、0 を書き込むと 0V になって消灯します。
定数で名前をつける意味
コードの冒頭で LED_PIN = 16 や SWITCH_PRESSED = 1 のように定数を定義しています。
if switch_state == 1: と書くより if switch_state == SWITCH_PRESSED: と書いた方が、何を判定しているか一目で分かります。
ピン番号を変更する必要が生じたときも、定数部分を1か所直すだけで済みます。
ポーリングとは
while True: の中で switch.value() を繰り返し呼び、ボタンの状態を確認し続ける方法を「ポーリング」と言います。
time.sleep(0.01) で 10ms ごとに確認しています。
シンプルで分かりやすい方法ですが、CPU がひたすらボタンを見張り続けるため、消費電力が気になる用途には後述の割り込み方式が向いています。
これで「押している間だけ光る」は完成です。ただ実際に試すと、たまに反応が変だと感じることがあります。
その正体が次に説明する「チャタリング」です。
チャタリングとは?(原因と仕組み)
基本プログラムは「押している間だけ光る」でした。次は一段進んで「押すたびにON/OFFが切り替わる(トグル)」を作ります。
トグル動作を正しく作るには、まずチャタリングという現象を理解する必要があります。
金属の接点が物理的にバウンドするために起こります。
人間には一瞬の「カチッ」でも、マイコンの目から見ると、その一瞬の間に何度もON/OFFが起きているように見えます。
理想(人が押した感覚):
離す ──────┐ ┌──────
└────────┘
1回押した
実際(チャタリング):
離す ──────┐ ┌┐ ┌─┐ ┌──────
└─┘└─┘ └──┘
押した瞬間に細かく振動 → マイコンは複数回と誤認
結果として、1回しか押していないのに「2回押された」「3回押された」と誤カウントしてしまいます。
トグル動作でこれが起きると最悪です。
1回押したつもりが偶数回カウントされ、ONにしたはずなのにOFFに戻ってしまう、といった「効いたり効かなかったり」する挙動になります。
だからトグルを作るならチャタリング対策は必須です。
チャタリング対策①:単純遅延方式(ソフトウェア)
単純遅延方式とは、ボタンが押されたと検出したあと、一定時間(今回は20ミリ秒)はそれ以降の入力を無視する、という考え方です。
チャタリングはほんの一瞬で収まるので、その間だけ目をつぶってしまえば誤カウントを防げます。
実装では「最後に押された時刻」を記録しておき、新しい押下を検出したときに「前回からどれだけ時間が経ったか」を見ます。
経過時間が20ミリ秒以下なら、それはチャタリングと判断して無視します。
時間の計測には time.ticks_ms() と time.ticks_diff() を使います。
time.ticks_ms() は現在のミリ秒カウントを返す関数、time.ticks_diff() は2つの時刻の差を安全に計算する関数です。単純な引き算ではなく ticks_diff() を使うのには理由があります。
カウンタが一周(オーバーフロー)しても、正しく差を求められるからです。
この20ミリ秒という値(DEBOUNCE_MS)は、短すぎるとチャタリングを取りこぼし、長すぎると素早い連打を拾えなくなります。
20〜50ミリ秒あたりが実用的な目安です。
単純遅延方式のメリットはシンプルで理解しやすいことです。デメリットは、常にポーリングしているのでCPUリソースを使い続ける点です。バッテリー駆動など消費電力を気にする場合は、次に紹介する割り込み方式が向いています。
チャタリング対策②:割り込み(irq)を使う方法
「割り込み(irq:Interrupt Request)」を使う方法もあります。
割り込みとは?
ポーリングは while True: でひたすらボタンの状態を確認し続ける方法でした。
割り込みは「ボタンが押された瞬間にマイコンが自動で気づく」仕組みです。
ボタンが押されたとき(LOW → HIGH に変化したとき)に、あらかじめ登録しておいた関数(ハンドラ)が自動で呼び出されます。
メインのループは何もしていなくてOKです。
CPU が常にボタンを見張らなくていいので、消費電力を抑えられます。
チャタリング対策③:ハードウェア(CR積分回路)
ソフトウェアではなく、回路側でチャタリングを解決する方法もあります。「CR積分回路」と呼ばれる手法です。
CR積分回路の仕組み
スイッチとグランドの間にコンデンサを入れ、スイッチと電源の間に抵抗を入れる回路です。
コンデンサは電荷を蓄える性質があるため、スイッチが細かく ON/OFF しても電圧がなめらかに変化します。
チャタリングによる急激な電圧変動が平滑化されるので、マイコンからは1回の押下に見えます。
ソフトウェア対策との比較
ハードウェア対策のメリットはコードがシンプルになることです。
デメリットは回路に部品を追加する必要があり、設計の手間がかかることです。
今回使う Grove Button はモジュール上にすでにプルダウン抵抗が内蔵されているため、コンデンサを追加するには Grove ケーブルの途中に割り込む改造が必要です。
ソフトウェア対策の方が手軽なので、初めはソフトウェア対策で十分です。
エッジ検出で「押した瞬間」をとらえる
エッジ検出とは、「押している間ずっと」ではなく「押した瞬間だけ」を捉える技術のことです。
もしエッジ検出をせずに「押されている=1」のたびにトグルしたらどうなるでしょう。
ボタンを1秒押し続けるだけで、状態が何十回も反転してしまいます。これでは使い物になりません。
狙いは「1回の押下=1回の反転」です。
そこで、前回のスイッチ状態と今回のスイッチ状態を比較します。
previous_switch_state が RELEASED(離れていた)で、current_switch_state が PRESSED(押された)になった瞬間、つまり「離れている → 押された」へ変化したその一回だけを処理します。
この変化の瞬間を「立ち上がりエッジ」と呼びます。
RaspberryPi Pico 2W 応用プログラム:ボタンでLEDをトグル動作させる(MicroPython)
このコードは、チャタリング除去(単純遅延方式)とエッジ検出を組み合わせて、ボタンを押すたびにLEDがON/OFFと切り替わるトグル動作を実現するためのものです。
previous_switch_state と current_switch_state を比較している部分がエッジ検出、time.ticks_diff() で時間差を見ている部分がチャタリング除去にあたります。
from machine import Pin
import time
# ── ピン番号の定義 ─────────────────────────────────────────────
LED_PIN = 16
SWITCH_PIN = 18
# ── 状態の定義(Grove Button はプルダウン接続) ────────────────
SWITCH_PRESSED = 1
SWITCH_RELEASED = 0
LED_ON = 1
LED_OFF = 0
# ── チャタリング除去の待機時間 ─────────────────────────────────
DEBOUNCE_MS = 20 # 20ms 以内の再入力はチャタとして無視
# ── ピン設定 ──────────────────────────────────────────────────
led = Pin(LED_PIN, Pin.OUT)
switch = Pin(SWITCH_PIN, Pin.IN)
# ── 状態変数 ──────────────────────────────────────────────────
led_state = LED_OFF
previous_switch_state = SWITCH_RELEASED
last_press_time = time.ticks_ms()
count = 0
led.value(led_state)
print("応用プログラム 開始")
# ── メインループ ───────────────────────────────────────────────
while True:
current_switch_state = switch.value()
if previous_switch_state == SWITCH_RELEASED and \
current_switch_state == SWITCH_PRESSED:
now = time.ticks_ms()
if time.ticks_diff(now, last_press_time) > DEBOUNCE_MS:
count += 1
if led_state == LED_OFF:
led_state = LED_ON
else:
led_state = LED_OFF
led.value(led_state)
print("押された回数:", count)
last_press_time = now
previous_switch_state = current_switch_state
Code language: Python (python)
実行すると、コンソールに「応用プログラム 開始」と表示され、ボタンを押すたびにLEDがON→OFF→ON…と切り替わります。
同時に「押された回数: 1」「押された回数: 2」とカウントが増えていきます。
もしチャタリングが残って数字が一度に2ずつ増えるようなら、DEBOUNCE_MS の値を30〜50に上げてみてください。
コードの流れを追うと、まずループの先頭でいまの状態を読み取り、「離れている → 押された」へ変化したかを確認します。
変化していたら、前回の押下から20ミリ秒以上経っているかをチェックし、条件を満たしたときだけLEDの状態を反転させて書き込みます。
最後に previous_switch_state = current_switch_state で今回の状態を次回用に保存します。
この保存を忘れるとエッジ検出が成立しないので、ここも重要なポイントです。
RaspberryPiPico2Wがうまく動かない時のトラブルシューティング
うまく動かないときは、以下を順番に確認してください。
LED が光らない
症状:ボタンを押してもLEDが変化しない。
原因として多いのは、LED モジュールの接続先コネクタの間違いです。D16 コネクタに刺さっているか確認してください。コードの LED_PIN = 16 がコネクタと一致しているかも確認します。
また、LED モジュール自体が壊れていないか、別のコネクタに挿してテストするのも有効です。
ボタンが反応しない
症状:ボタンを押しても何も起きない。
D18 コネクタに Grove Button モジュールが刺さっているか確認してください。Thonny のシェルで以下を入力すると、ボタンの状態をリアルタイムに確認できます。
from machine import Pin
switch = Pin(18, Pin.IN)
print(switch.value()) # 押していないとき: 0, 押しているとき: 1
Code language: Python (python)
動作が逆になる(離すと光る、押すと消える)
症状:ボタンを押すと消灯し、離すと点灯する。
Pin.PULL_UP を誤って指定しているケースが多いです。
Grove Button 側にプルダウン抵抗が内蔵されているので、Pico 2W 側は Pin.IN だけで設定してください。
Pin.PULL_UP を指定すると、動作が逆になります。
Thonny で「No port」「接続できない」エラーが出る
症状:USB を接続しても Thonny が Pico 2W を認識しない。
充電専用の USB ケーブルを使っているケースがよくあります。データ転送に対応した USB ケーブルに替えてください。
外観では区別が難しいので、できれば別のケーブルを試してみることをおすすめします。
Pico 2W のドライバが正しくインストールされているかも確認してください。第1回の環境構築手順を参照してください。
チャタリングが収まらない(複数回反応する)
症状:1回押しているのに LED が複数回反応する。
DEBOUNCE_MS = 20 の値を 50 に増やしてみてください。スイッチの個体差によってチャタリングの長さが異なります。
値を大きくしすぎると押したと認識されるまでの遅延が増えるので、20〜100 の範囲で調整してください。
まとめ・次回予告
今回はGrove Buttonを使って、デジタル入力の基礎からチャタリング除去・トグル動作までを実際のコードで体験しました。
入力ができるようになったことで、マイコンと外の世界が双方向でやり取りできるようになりました。
とくにGrove Buttonの「押すとHIGH」という挙動は、一般的なプルアップ接続と逆なので、つまずきやすい最重要ポイントです。
ここを押さえておけば、今後どんなスイッチを扱うときも判定で迷わなくなります。
今回の講座で学んだこと
- デジタル入力はHIGH/LOWの2つの状態を読み取る仕組みだと理解した
- プルアップ・プルダウン抵抗がフローティングを防ぐ役割を理解した
- Grove Buttonはプルダウン接続で「押すとHIGH(value=1)」になると分かった
- チャタリングの正体と、単純遅延方式での除去方法を理解した
- エッジ検出を使って、押すたびに切り替わるトグル動作を実装できた
次回(第4回)は照度センサーを使って、明るさを数値として読み取るアナログ入力に挑戦します。
今回のデジタル入力(0か1か)に対して、次回は連続した値を扱う世界です。
入力の世界がさらに広がるので、ぜひ続けて挑戦してみてください。
今回の記事を動画でも解説しています。あわせてご覧ください。

