[Arduino線上教程] 第三篇: 開關控制

更新於 發佈於 閱讀時間約 13 分鐘

前導

在電路中開關的種類很多,主要的功能是接通和斷開,開關打開時為接通,此時電流會流通,我們稱之為(ON),開關斷開時會開路,此時電流不會流通,我們稱之為(OFF)。開關的種類有很多,例如:機械開關、指撥開關、按鍵開關,可以上網查詢各個開關的模樣與電路圖的表示方法,蠻好分辨的。

一般微控制器數位輸入腳位的接法分別為上拉電阻(Pull-Up)與下拉電阻(Pull-Down)。

第一張圖:下拉電阻(Pull-Down)接法

   +5V

[按鈕]

Pin7 ← 連接到數位輸入腳(如 sw=7)

[10K] ← 電阻(例如 10KΩ)

GND

工作原理:

  • 按鈕未按下時:電路中只有電阻與 GND 形成回路,所以 Pin7 讀到的是 LOW (0)
  • 按鈕按下時:+5V 直接透過按鈕在電阻產生電壓,所以 Pin7 讀到的是 HIGH (1)
  • 按下按鈕就是 HIGH。
  • 預設狀態為 LOW

第二張圖:上拉電阻(Pull-Up)接法

   +5V

[10K] ← 電阻(例如 10KΩ)

Pin7 ← 連接到數位輸入腳(如 sw=7)

[按鈕]

GND

工作原理:

  • 按鈕未按下時:因為有上拉電阻連到 +5V,Pin7 預設為 HIGH (1)
  • 按鈕按下時:Pin7 直接接到 GND,讀到的是 LOW (0)
  • 更常見

好,現在幫我將接線用成下圖(下拉電阻(Pull-Down)接法):

raw-image

範例1:

const int sw = 7;
const int led = 12;

void setup()
{
pinMode(sw, INPUT);
pinMode(led, OUTPUT);
}

void loop()
{
if(digitalRead(sw) == HIGH){
delay(20);
digitalWrite(led, HIGH);
}
else{
digitalWrite(led, LOW);
}
}
  • 一般按鈕在按下後會有機械彈跳時間,這段時間會造成電路的不穩定。
  • 在上面的程式碼中,雖然我們在偵測到按鈕為 HIGH 之後,插入了一個 delay(20),但它並不是真正意義上的「去彈跳」(debounce);更準確地說,這只能算是插入一段延時,並沒有在延時之後再次檢查按鈕是否仍維持在同一狀態

所以真正的軟體去彈跳流程為何?

  1. 偵測到狀態改變(例如 LOW → HIGH)。
  2. 等待一小段時間(通常 5~20ms)。
  3. 再次讀取按鈕狀態,確認是否仍為 HIGH(或 LOW)。
  • 若狀態仍維持不變,才算是「真的按下(或放開)」。

改進的程式碼如下所示:

範例2:

const int sw = 7;
const int led = 12;
const int deBounceDelay = 20;

void setup() {
pinMode(sw, INPUT);
pinMode(led, OUTPUT);
}

void loop() {
// 偵測按鈕是否被按下
if (digitalRead(sw) == HIGH) {
// 按下後先等待 debounce 延時
delay(deBounceDelay);
// 再次確認按鈕是否仍然處於按下狀態
if (digitalRead(sw) == HIGH) {
// 如果確定按下,則點亮 LED
digitalWrite(led, HIGH);

// 進入等待狀態,直到按鈕鬆開
while (digitalRead(sw) == HIGH)
;

// 等待按鈕釋放(鬆開)後,再做一次 debounce
delay(deBounceDelay);
if (digitalRead(sw) == LOW) {
// 確認鬆開後,熄滅 LED
digitalWrite(led, LOW);
}
}
}
}

這段程式碼:

while(digitalRead(sw) == HIGH)
;

的意思是:只要 digitalRead(sw) 回傳 HIGH,程式就會一直在這個迴圈中「忙等待」(busy-wait),直到按鈕狀態改變,不再是 HIGH。這種寫法可以讓程式暫停在這裡,不執行後面的程式碼,直到按鈕被放開。


如若今天我想要利用按鈕來控制的行為是: 按鈕按下後放開,切換狀態的話,我們可以這樣實現:

範例3:

const int sw = 7;
const int led = 12;
const int deBounceDelay = 20;
int lesStatus = LOW;

void setup()
{
pinMode(sw, INPUT);
pinMode(led, OUTPUT);
}

void loop()
{
if(digitalRead(sw) == HIGH){
delay(deBounceDelay);
while(digitalRead(sw) == HIGH)
;
lesStatus = !lesStatus;
digitalWrite(led, lesStatus);
}
}
  • 這段程式碼的主要功能是利用一個按鈕來切換 LED 狀態,也就是每當你按下並放開按鈕時,就會將 LED 的狀態反轉(如果原來亮則變暗,反之亦然)

好,在Arduino中,其內部有上拉電阻,「上拉電阻」的概念是用來穩定數位輸入腳的電平,避免在開關(如按鈕)未接通時輸入腳懸空,從而受到干擾產生不穩定的讀數。

上拉電阻的接法如下:

   +5V

[10K] ← 上拉電阻(例如 10KΩ)

Pin7 ← 連接到數位輸入腳(如 sw=7)

[按鈕]

GND
  • 當按鈕沒有按下時,由於上拉電阻連接於 +5V 和 Pin7 之間,所以 Pin7 的電位會被「拉」到 HIGH。
  • 當按下按鈕時,按鈕將 Pin7 直接接到 GND,使其讀值變成 LOW。

想要使用Arduino 的內建上拉電阻,只需將腳位設為

pinMode(sw, INPUT_PULLUP);

好,現在我們來改寫本章節的範例3:

首先改變接線關係:

raw-image

再來修改程式碼:

const int sw = 7;
const int led = 12;
const int deBounceDelay = 20;
int ledStatus = LOW;

void setup() {
pinMode(sw, INPUT_PULLUP); // 使用內建上拉電阻
pinMode(led, OUTPUT);
}

void loop() {
// 當按鈕被按下時,digitalRead(sw) 會讀取到 LOW
if (digitalRead(sw) == LOW) {
delay(deBounceDelay); // 延時以消除彈跳
// 等待按鈕釋放,即讀值變成 HIGH
while (digitalRead(sw) == LOW)
;
ledStatus = !ledStatus; // 切換 LED 狀態
digitalWrite(led, ledStatus); // 更新 LED 輸出
}
}

電話鍵盤控制開關

電話鍵盤通常採用矩陣式排列,例如 3×4 的鍵盤

  • 鍵盤接線通常需要依照其資料手冊接線,常見會有 7 個或 8 個接腳(視矩陣大小而定)。例如,3×4 鍵盤通常需要 8 根線(4 列 + 4 行 )。

在tinkercad中,已經幫你標記好接線的關係了,如下圖:

raw-image

好,這邊簡單示範如何掃描指定按鈕的讀值,策略是使用兩個迴圈,外層迴圈負責掃描列,內層迴圈負責掃描行(檢查哪一按鈕被壓下)。

好,首先請跟我把麵包版接好,如下圖:

raw-image

再來,程式碼如下所示:

const byte ROWS = 4; // 四列
const byte COLS = 4; // 四行
const int buzzPin = 3; // 蜂鳴器接腳

// 鍵盤行與列的 Arduino 腳位設定
byte rowPins[ROWS] = {4, 5, 6, 7}; // 連接鍵盤的列腳位
byte colPins[COLS] = {8, 9, 10, 11}; // 連接鍵盤的行腳位

// 鍵盤上各按鍵對應的字元
char keys[ROWS][COLS] = {
{'1','2','3', 'A'},
{'4','5','6', 'B'},
{'7','8','9', 'C'},
{'*','0','#', 'D'}
};

const int deBounceDelay = 20; // 去彈跳延時(毫秒)

void setup(){
Serial.begin(9600);

// 設定所有 rowPins 為輸出,預設拉 HIGH
for (int i = 0; i < ROWS; i++){
pinMode(rowPins[i], OUTPUT);
digitalWrite(rowPins[i], HIGH);
}

// 設定所有 colPins 為輸入,啟用內建上拉
for (int i = 0; i < COLS; i++){
pinMode(colPins[i], INPUT_PULLUP);
}

// 設定蜂鳴器腳位為輸出
pinMode(buzzPin, OUTPUT);
}

// getKey() 函式:掃描矩陣鍵盤,若有按下則回傳該鍵字元,否則回傳 '\0'
char getKey() {
for (int r = 0; r < ROWS; r++) {
// 將當前列拉低
digitalWrite(rowPins[r], LOW);

// 掃描所有行
for (int c = 0; c < COLS; c++){
// 因為使用內建上拉電阻,按下時該行會變成 LOW
if (digitalRead(colPins[c]) == LOW) {
delay(deBounceDelay); // debounce 延時
if (digitalRead(colPins[c]) == LOW) { // 再次確認仍然按下
// 等待按鍵釋放
while (digitalRead(colPins[c]) == LOW) {
;
}
// 將該列恢復 HIGH 後,回傳對應字元
digitalWrite(rowPins[r], HIGH);
return keys[r][c];
}
}
}
// 恢復該列為 HIGH
digitalWrite(rowPins[r], HIGH);
}
return '\0'; // 沒有按鍵按下時回傳空字元
}

void loop(){
char key = getKey(); // getKey() 掃描鍵盤
if (key != '\0') { // 若有鍵按下
Serial.print("Press: ");
Serial.println(key);

// 控制蜂鳴器嗶一聲:蜂鳴 100 毫秒
digitalWrite(buzzPin, HIGH);
delay(100);
digitalWrite(buzzPin, LOW);
}
}

getKey() 函式

  • 掃描每一列:將某一列拉 LOW,然後檢查各個行之接腳是否讀取到 LOW。
  • 若檢測到 LOW,進行 debounce 延時,再次確認。
  • 等待按鍵釋放後,回傳對應的字元,並且嗶一聲;否則回傳空字元 '\0'

本頻道持續更新中(內容涵蓋前端程式設計入門、大學必備程式設計入門、電子系專業課程入門、數學微積分題解)如果身旁有相關科系的學生,不妨推薦一下喔~

相信這裡會是家教或線上課程之外,高中、大學生系統性綜合學習的好選擇。

最後感謝您的觀看!

在當今數位時代,電資領域人才需求爆發式成長,不論是前端網頁設計、嵌入式開發、人工智慧、物聯網還是軟硬體整合,這些技術都在改變世界。而掌握 C/C++、Python、數位邏輯、電路學與嵌入式開發等大學電資領域的課程,正是進入這個高薪、高需求產業的關鍵!
留言
avatar-img
留言分享你的想法!
本章節主要著重在程式碼上。讓讀者練習一些邏輯的推演,也藉此更了解Arduino的語法。
本章節會帶領讀者使用虛擬的模擬平台撰寫你的第一支Arduino程式。Arduino 因其易用性和開源生態成為許多創客和工程師的首選。它是很多人第一次接觸的微控制器,說明其為物聯網和嵌入式系統相關科目的入門學習首選。
本章節主要著重在程式碼上。讓讀者練習一些邏輯的推演,也藉此更了解Arduino的語法。
本章節會帶領讀者使用虛擬的模擬平台撰寫你的第一支Arduino程式。Arduino 因其易用性和開源生態成為許多創客和工程師的首選。它是很多人第一次接觸的微控制器,說明其為物聯網和嵌入式系統相關科目的入門學習首選。
你可能也想看
Google News 追蹤
Thumbnail
靈感用盡、鍵盤不再響,盯著喜歡、分享、留言的數字,心跳跟著小鈴鐺七上八下⋯⋯vocus 2025 年 4 月限定新商品,要為創作者打氣! 🚨「創作者打氣包」 最懂創作者的vocus,為創作者打造 ✨ 打氣包,包什麼?!四件道具挺創作者 一、【打氣復活卷】 專屬你的打氣小語,成功登記免費
Thumbnail
全新 vocus 挑戰活動「方格人氣王」來啦~四大挑戰任你選,留言 / 愛心 / 瀏覽數大 PK,還有新手專屬挑戰!無論你是 vocus 上活躍創作者或剛加入的新手,都有機會被更多人看見,獲得站上版位曝光&豐富獎勵!🏆
Thumbnail
這篇內容,將會講解什麼是「switch」,以及與「switch」相關的知識。包括switch的簡介、switch、break。
Thumbnail
這篇內容,將會講解什麼是函式,以及與函式相關的知識。包括函式的簡介、Runtime Function、自訂函式、Script Function 腳本函式、Method 方法。
Thumbnail
實際上為了製作斷路開關(老外叫做Adapter Kill Switch Door)以及腳踢線(Kick harness),中間找工具/端子&針腳針腳規格/線徑大小...花了一段時間,因為我從來就沒有接觸過此類手工技術的經驗,當初傻傻地拿著框體上的端子跑去光華商場的電子街想要照規格買沒
Thumbnail
在設計表單的時候有幾種不同的元件,可以用來加快填寫表單的速度。而在這些元件中比較常見的 Checkbox 與 Toggle Switch 常常會讓我覺得有點像又有點不像,在製作表單的時候會有點不太確定在什麼情境下分別使用這兩種元件。在搜集資料後發現,真的有人將這兩個元件做了一些詳細的說明,所以決定整
※ switch用法: ​switch是 JavaScript 中的一個控制結構,是一種更結構化的方法來替代多個 if...else 語句,特別是當需要根據同一變數的多個值進行不同操作時非常有用。 ※ switch語法: switch 語句首先評估括號內的表達式 (expression)。
本課程學習如何在 Kotlin 程式碼檔案中,設定 Button 按鈕元件點擊事件。
Thumbnail
靈感用盡、鍵盤不再響,盯著喜歡、分享、留言的數字,心跳跟著小鈴鐺七上八下⋯⋯vocus 2025 年 4 月限定新商品,要為創作者打氣! 🚨「創作者打氣包」 最懂創作者的vocus,為創作者打造 ✨ 打氣包,包什麼?!四件道具挺創作者 一、【打氣復活卷】 專屬你的打氣小語,成功登記免費
Thumbnail
全新 vocus 挑戰活動「方格人氣王」來啦~四大挑戰任你選,留言 / 愛心 / 瀏覽數大 PK,還有新手專屬挑戰!無論你是 vocus 上活躍創作者或剛加入的新手,都有機會被更多人看見,獲得站上版位曝光&豐富獎勵!🏆
Thumbnail
這篇內容,將會講解什麼是「switch」,以及與「switch」相關的知識。包括switch的簡介、switch、break。
Thumbnail
這篇內容,將會講解什麼是函式,以及與函式相關的知識。包括函式的簡介、Runtime Function、自訂函式、Script Function 腳本函式、Method 方法。
Thumbnail
實際上為了製作斷路開關(老外叫做Adapter Kill Switch Door)以及腳踢線(Kick harness),中間找工具/端子&針腳針腳規格/線徑大小...花了一段時間,因為我從來就沒有接觸過此類手工技術的經驗,當初傻傻地拿著框體上的端子跑去光華商場的電子街想要照規格買沒
Thumbnail
在設計表單的時候有幾種不同的元件,可以用來加快填寫表單的速度。而在這些元件中比較常見的 Checkbox 與 Toggle Switch 常常會讓我覺得有點像又有點不像,在製作表單的時候會有點不太確定在什麼情境下分別使用這兩種元件。在搜集資料後發現,真的有人將這兩個元件做了一些詳細的說明,所以決定整
※ switch用法: ​switch是 JavaScript 中的一個控制結構,是一種更結構化的方法來替代多個 if...else 語句,特別是當需要根據同一變數的多個值進行不同操作時非常有用。 ※ switch語法: switch 語句首先評估括號內的表達式 (expression)。
本課程學習如何在 Kotlin 程式碼檔案中,設定 Button 按鈕元件點擊事件。