iT邦幫忙

2026 iThome 鐵人賽

DAY 6
0

現在號誌燈的狀態已經有了統一的管理方式,但真正的控制箱不能每次都靠修改程式來操作,今天要加上一顆實體按鈕,讓現場人員只要動手一按,就能直接向 MCU 下達指令。

將按鈕接到 D9

本篇在原有 D2 LED 之外加入一顆按鈕,按鈕一端接 D9,另一端接 GND,程式使用 UNO Q D9腳位內建的上拉電阻功能,因此不需要另外加入一顆電阻。
https://ithelp.ithome.com.tw/upload/images/20260806/20058745euDZwri4SH.png
四腳按鈕的同側兩腳通常彼此相通,接線時要讓 D9 與 GND 位於開關兩側,按下後兩端才會導通,若程式執行後輸入一直沒有變化,應先檢查按鈕方向與麵包板位置。

程式開頭新增 BTN_PIN,將現場操作鍵固定對應到 D9。

const int LED_PIN = 2;
const int BTN_PIN = 9;

使用名稱表示腳位後,LED_PIN 負責輸出,BTN_PIN 負責輸入,程式不必在不同位置反覆出現數字 2 與 9,也能直接看出兩個腳位的用途。

使用內部上拉輸入

setup() 中加入 pinMode(BTN_PIN, INPUT_PULLUP);,將 D9 設為數位輸入,並啟用 MCU 內部的上拉電阻。

pinMode(BTN_PIN, INPUT_PULLUP);

注意:啟用 INPUT_PULLUP 後,內部上拉讓輸入腳位在按鈕放開時維持明確的 HIGH,避免腳位懸空而出現不穩定讀值,按鈕放開時 D9 會讀到 HIGH,按下後 D9 與 GND 導通,讀值會變成 LOW,程式判斷按下狀態時要使用 LOW,不能沿用「按下等於 HIGH」的直覺。

數位輸入只能分辨 HIGH 與 LOW,無法直接知道按鈕名稱或使用者意圖,程式必須先依接線方式解讀讀值,本篇將 LOW 定義為現場人員正在按下操作鍵,HIGH 則代表按鈕已放開,後續條件判斷都沿用這個規則。

在迴圈讀取按鈕

loop() 會持續執行,程式每次先用 digitalRead(BTN_PIN) 讀取 D9,再將結果存入布林變數 btn

bool btn = digitalRead(BTN_PIN);

if (btn == LOW) {
  toggle_led();
}

btn 等於 LOW,代表按鈕目前處於按下狀態,程式便呼叫前一天完成的 toggle_led(),由同一個函式反轉 ledState 並更新 D2 LED。

按鈕程式沒有直接寫 HIGH 或 LOW 到 LED,也沒有另外建立第二套切換流程,現場操作只負責提出切換要求,真正的狀態管理仍由 toggle_led() 完成。

完整 MCU 程式

sketch/sketch.ino 更新為以下內容,其他檔案保持 Day 5 的版本。

const int LED_PIN = 2;
const int BTN_PIN = 9;

bool ledState = false;

void toggle_led() {
  ledState = !ledState;
  digitalWrite(LED_PIN, ledState ? HIGH : LOW);
}

void setup() {
  pinMode(LED_PIN, OUTPUT);
  pinMode(BTN_PIN, INPUT_PULLUP);
  digitalWrite(LED_PIN, LOW);
}

void loop() {
  bool btn = digitalRead(BTN_PIN);

  // 只要按住按鈕就持續切換,下一天再修正。
  if (btn == LOW) {
    toggle_led();
  }
}

啟動時 LED 維持關閉,按下後 btn 變成 LOW,程式開始呼叫切換函式。

執行與驗證

按下 App Lab 的 Run 並等待部署完成,此時 LED 應保持原狀,短按按鈕時可看到 LED 改變,這代表 D9 輸入已進入 MCU 的號誌控制流程。

測試時可先上電不碰按鈕,確認 LED 維持關閉,再快速按下並放開,觀察 LED 是否出現變化,最後按住按鈕一秒,確認 LED 會快速切換,三個結果分別驗證放開讀到 HIGH、按下讀到 LOW,以及條件在按住期間會持續成立。

按住按鈕不放時,loop() 會在極短時間內重複讀到 LOW,每次都呼叫 toggle_led(),LED 因此快速切換,這是因為程式目前只知道「按鈕正在被按住」,還無法辨認「剛剛按下的那一刻」,後面我們會比較前一次與目前讀值,讓一次按下只切換一次。

若按下後完全沒有反應,依序檢查 D9 與 GND 接線、按鈕方向、INPUT_PULLUP 是否正確,以及條件是否寫成 btn == LOW

本篇完成內容

  • 將 D9 設為現場按鈕輸入。
  • 使用 INPUT_PULLUP 穩定按鈕讀值。
  • 使用 digitalRead() 取得 HIGH 與 LOW。
  • 讓按鈕呼叫既有的 toggle_led()

現在按鈕已能切換號誌燈,但是若一直按住則燈號就會持續切換跳動,下一步要讓程式只在按下瞬間反應一次。

下一篇|按一下才切換,別讓燈一直跳


上一篇
Day 5|如何管理號誌燈
系列文
一塊板子,兩個腦袋:Arduino UNO Q 30 天實戰6
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言