要約
LEDとタクトスイッチだけで、入力→処理→出力という組み込みの基本思考を最短で体得する。配線、コード、デバッグ、拡張までを一気通貫で解説。
想定読者
- Arduino未経験〜初心者
- ハード寄りの思考を最短で掴みたい人
この記事で得られること
- 入力(ボタン)と出力(LED)の因果設計
- チャタリング対策と状態遷移の基礎
- バグの切り分け手順と拡張の勘所
目次
- 必要なもの
- 配線図と回路の考えかた
- 最小コード(まずは点灯)
- チャタリング対策(時間で整える)
- 状態遷移で“押すたびにトグル”
- 典型トラブルと切り分け
- 学びを拡張する3ステップ
- まとめ
- 付録:コピペ用スケッチ一式
- SEOメモ(キーワード/メタ/FAQ構造化)
1. 必要なもの
- Arduino Uno互換(他でも可)
- ブレッドボード
- タクトスイッチ 1個
- LED 1個
- 抵抗 220Ω ×1(LED用)
- ジャンパワイヤ数本
以降は内部プルアップを使うためボタン用の抵抗は不要。
2. 配線図と回路の考えかた
- LED:Arduino D13 に直列220Ωを挟んでLEDアノード、カソードはGND。
- ボタン:片側をD2、もう片側をGND。D2はINPUT_PULLUPで論理1に保たれ、押すと0になる。
設計ポイント
- 入力はノイズを含む。機械接点はチャタリングで数ms揺れる。
- 出力は人間に見える変化を与える。ここではLEDのON/OFF。
- 真ん中の処理は状態遷移で表現すると破綻しにくい。
3. 最小コード(まずは点灯)
const int LED_PIN = 13;
void setup() {
pinMode(LED_PIN, OUTPUT);
}
void loop() {
digitalWrite(LED_PIN, HIGH);
}
電気が通ると光る。出力の“基準”を先に確認。
4. チャタリング対策(時間で整える)
狙い:押した瞬間の短いガタつきを無視。**“一定時間同じ状態なら採用”**が基本。
const int BTN_PIN = 2;
const int LED_PIN = 13;
unsigned long lastChange = 0;
const unsigned long DEBOUNCE_MS = 20;
int stableState = HIGH; // PULLUPなので非押下=HIGH
int lastRaw = HIGH;
void setup() {
pinMode(LED_PIN, OUTPUT);
pinMode(BTN_PIN, INPUT_PULLUP);
}
void loop() {
int raw = digitalRead(BTN_PIN);
if (raw != lastRaw) {
lastChange = millis();
lastRaw = raw;
}
if (millis() - lastChange > DEBOUNCE_MS) {
stableState = raw; // 安定してから採用
}
digitalWrite(LED_PIN, stableState == LOW ? HIGH : LOW);
}
ここでは“押している間だけ点灯”。時間で入力を整えるのが組み込み思考の最小単位。
5. 状態遷移で“押すたびにトグル”
狙い:エッジ(立ち下がり)を1回検出→LEDの状態を反転。押下の瞬間だけを使う。
const int BTN_PIN = 2;
const int LED_PIN = 13;
unsigned long lastChange = 0;
const unsigned long DEBOUNCE_MS = 20;
int lastRaw = HIGH;
int debounced = HIGH;
int prevDebounced = HIGH;
bool ledOn = false;
void setup() {
pinMode(LED_PIN, OUTPUT);
pinMode(BTN_PIN, INPUT_PULLUP);
digitalWrite(LED_PIN, LOW);
}
void loop() {
// 1) デバウンス
int raw = digitalRead(BTN_PIN);
if (raw != lastRaw) {
lastChange = millis();
lastRaw = raw;
}
if (millis() - lastChange > DEBOUNCE_MS) {
debounced = raw;
}
// 2) 立ち下がりエッジ検出: HIGH -> LOW
if (prevDebounced == HIGH && debounced == LOW) {
ledOn = !ledOn; // 状態遷移
digitalWrite(LED_PIN, ledOn ? HIGH : LOW);
}
prevDebounced = debounced;
}
状態機械の見取り図
LED=OFF
–(押下エッジ)→LED=ON
LED=ON
–(押下エッジ)→LED=OFF
“入力イベント”をエッジに限定すると、多重反応が消える。
6. 典型トラブルと切り分け
症状 | 原因の仮説 | テスト |
---|---|---|
LEDが点かない | 極性逆、抵抗未接続、ピン番号違い | D13へ直接digitalWrite(HIGH) で確認 |
反応が鈍い | DEBOUNCEが長すぎ | 10–20ms で調整 |
勝手に切り替わる | 浮遊入力 | INPUT_PULLUP か外部プルダウンで必ず固定 |
長押しで連続トグル | エッジ検出漏れ | prev とcurrent で遷移条件を厳密化 |
切り分け順
- 出力単体確認 → 2. 入力の安定化 → 3. 事件(エッジ)定義 → 4. 状態遷移
7. 学びを拡張する3ステップ
- 長押し機能:500ms以上の押下で別動作。
pressStart
と長さ比較。 - 点滅パターン:非ブロッキングな
millis()
タイマで複数周期。 - マルチボタン:同じデバウンス関数を配列化して再利用。
8. まとめ
- 入力→処理→出力をLEDとボタンで固めると他デバイスへ展開しやすい。
- 時間と状態を明示するのが組み込み思考。
- バグは切り分け順序で最短到達。
9. 付録:コピペ用スケッチ一式(最終版)
// Arduino超入門:押すたびにLEDトグル(デバウンス+立ち下がり検出)
const int BTN_PIN = 2;
const int LED_PIN = 13;
unsigned long lastChange = 0;
const unsigned long DEBOUNCE_MS = 20;
int lastRaw = HIGH;
int debounced = HIGH;
int prevDebounced = HIGH;
bool ledOn = false;
void setup() {
pinMode(LED_PIN, OUTPUT);
pinMode(BTN_PIN, INPUT_PULLUP);
digitalWrite(LED_PIN, LOW);
}
void loop() {
int raw = digitalRead(BTN_PIN);
if (raw != lastRaw) { lastChange = millis(); lastRaw = raw; }
if (millis() - lastChange > DEBOUNCE_MS) { debounced = raw; }
if (prevDebounced == HIGH && debounced == LOW) {
ledOn = !ledOn;
digitalWrite(LED_PIN, ledOn ? HIGH : LOW);
}
prevDebounced = debounced;
}
10. SEOメモ
推奨タイトル(クリック狙い)
- Arduino超入門:LEDとボタンだけで“組み込み思考”を最速で身につける
- 初心者向けArduinoチュートリアル|ボタン入力とLEDで学ぶデバウンスと状態遷移
スラッグ
arduino-beginner-led-button-debounce-state-machine
メタディスクリプション(140–160文字)
Arduino超入門。LEDとボタンだけで入力・処理・出力の基礎を体得。配線、デバウンス、エッジ検出、状態遷移、トラブル対処まで最短で解説。
見出し構成(Hタグ)
- H1:Arduino超入門:LEDとボタンだけで“組み込み思考”を身につける
- H2:必要なもの / 配線と回路 / 最小コード / デバウンス / 状態遷移 / トラブル / 拡張 / まとめ
- H3:症状別チェック、3ステップ拡張など
主要キーワード
- Arduino 初心者
- LED ボタン 配線
- デバウンス
- INPUT_PULLUP
- 状態遷移 立ち下がり検出
- 組み込み 思考 入門
内部リンク案
- “millis()でノンブロッキング点滅”解説記事
- “センサ入力で状態機械を組む”実装例
FAQ構造化マークアップ(JSON-LD)
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [{
"@type": "Question",
"name": "ボタンに抵抗は必要ですか?",
"acceptedAnswer": {
"@type": "Answer",
"text": "INPUT_PULLUPを使う場合は不要です。ピンをGNDに落とす配線にします。"
}
},{
"@type": "Question",
"name": "チャタリングは何msで対策すべき?",
"acceptedAnswer": {
"@type": "Answer",
"text": "一般的に10–20msで良好です。部品や配線で最適値は変わるため調整してください。"
}
},{
"@type": "Question",
"name": "長押しと短押しを分けるには?",
"acceptedAnswer": {
"@type": "Answer",
"text": "押下開始時刻を記録し、押している間の経過時間で閾値判定します。"
}
}]
}
</script>