Arduinoでタクトスイッチを読む|プルアップ抵抗とINPUT_PULLUPのしくみ、チャタリング対策まで
INPUT_PULLUPで配線を減らす
ボードの中のプルアップ抵抗を使う
Arduino Unoなどのマイコンには、入力端子ごとにプルアップ抵抗が内蔵されていて、スケッチから有効にできます。pinMode で端子を INPUT_PULLUP に設定すると、外付けの抵抗なしでプルアップの回路ができあがります。内蔵の抵抗は数十kΩ程度で、値は機種によって違いますが、ボタンを読む用途には十分です。
配線は、ボタンの片側をデジタル端子(ここでは2番)に、もう片側をGNDにつなぐだけです。部品が減り、5Vの配線も不要になるので、ブレッドボードの上がすっきりします。入門では、まずこの方法から始めるのがおすすめです。
配線の手順
- USBケーブルを抜き、ボードに電源が入っていない状態にする。
- タクトスイッチをブレッドボードの中央の溝をまたぐように挿す。
- スイッチの対角の足の一方に、ボードのデジタル2番からジャンパー線をつなぐ。
- もう一方の足から、ボードのGNDへジャンパー線をつなぐ。
- 配線を指でたどり、5VとGNDが直接つながっていないことを確かめてからUSBをつなぐ。

押されたら基板のLEDを点けるスケッチ
ボタンの状態を読み、押されている間だけ基板上のLEDを点けるスケッチは、次のようになります。
const int buttonPin = 2;
void setup() {
pinMode(buttonPin, INPUT_PULLUP);
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(9600);
}
void loop() {
int state = digitalRead(buttonPin);
if (state == LOW) { // 押されているとLOW
digitalWrite(LED_BUILTIN, HIGH);
} else {
digitalWrite(LED_BUILTIN, LOW);
}
Serial.println(state);
delay(10);
}
ポイントは、押されているときに LOW になることです。プルアップでは値が「逆」になるので、条件を state == LOW と書きます。慣れないうちは混乱しやすいので、bool pressed = (digitalRead(buttonPin) == LOW); のように「押されているか」を表す変数を作ってから使うと、後のスケッチが読みやすくなります。
シリアルモニタを開くと、押していないときは1、押すと0が流れていくはずです。値が勝手に揺れる場合は、INPUT_PULLUP の書き間違いや、別の端子番号に配線していないかを確かめます。
外付けの抵抗で組む場合
内部プルアップがあるのに外付けの抵抗を学ぶ意味は、他のマイコンや部品を使うときに同じ考え方が出てくるからです。外付けのプルダウンで組むなら、ボタンの片側を5Vに、もう片側をデジタル2番につなぎ、同じ2番の列から10kΩの抵抗を通してGNDへつなぎます。スケッチでは pinMode(buttonPin, INPUT); とし、押されているときが HIGH になります。
外付けと内部のプルアップを同時に使う必要はありません。外付けのプルダウン抵抗を付けたまま INPUT_PULLUP にすると、内部の抵抗と外付けの抵抗が引っ張り合い、押していないときの電圧が中途半端になることがあります。回路とスケッチの設定は、どちらか一方にそろえます。
押した瞬間を検出する
「押されている」と「押された」は違う
上のスケッチは、押している間ずっと反応します。しかし実際の作品では、「1回押すごとにLEDの点灯と消灯を切り替える」「押した回数を数える」など、押した瞬間だけを捉えたい場面がよくあります。loop は1秒間に何千回も回るので、押している間の状態をそのまま使うと、1回の押下で何百回も数えてしまいます。
前回の状態と比べる
押した瞬間を捉えるには、前回 loop を回ったときの状態を覚えておき、今回と比べます。前回がHIGH(押していない)で、今回がLOW(押している)なら、ちょうど押された瞬間です。このように状態が切り替わる境目を「エッジ」と呼びます。
const int buttonPin = 2;
int lastState = HIGH;
bool ledOn = false;
void setup() {
pinMode(buttonPin, INPUT_PULLUP);
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
int state = digitalRead(buttonPin);
if (lastState == HIGH && state == LOW) { // 押された瞬間
ledOn = !ledOn;
digitalWrite(LED_BUILTIN, ledOn ? HIGH : LOW);
}
lastState = state;
}
逆に、前回がLOWで今回がHIGHなら、ボタンが離された瞬間です。押した瞬間で処理を始め、離した瞬間で終える、という組み合わせもよく使います。押した回数を数えたいときは、押された瞬間の条件の中で変数に1を足し、シリアルモニタへ表示すると、数え方が正しいかを目で確かめられます。
動きを確かめるコツ
エッジの検出がうまく動いているかは、LEDだけでは分かりにくいことがあります。押された瞬間に Serial.println("pressed"); のような文字を出すようにしておくと、1回押したときに何回表示されるかで、スケッチの動きを確かめられます。1回押して1回だけ表示されれば正しく、2回、3回と表示されるなら、何かが余分に反応しています。
これで1回押すごとに点灯と消灯が切り替わる……はずですが、実際に試すと、うまく切り替わらないことがあります。押したのに点いたり消えたりを素早く繰り返して、元の状態に戻ってしまうのです。シリアルモニタで確かめると、1回の押下で表示が何回も出ることがあります。原因は次に説明するチャタリングです。










