Arduino 4×4薄膜鍵盤模組實驗(一):按鍵掃描程式原理說明

下圖左是一款常見的薄膜按鍵模組(hex keypad),有4×4或3×4(少了最右邊一行的A, B, C, D鍵),它的內部如同下圖右邊的電路所示,是由16個按鍵(開關)交織而成。有些按鍵模組直接使用按鍵(微觸)開關組裝,連接電路與程式都和本文相同。

薄膜按鍵模組(hex keypad)

4×4按鍵模組有8個接腳,分成列、行兩組,可以接在Arduino的任意8個接腳,筆者將它接在數位6~13腳:

4x4按鍵模組連接Arduino

為了簡化接線,可以使用「長腳型」排針,將其中兩個腳用尖嘴鉗稍微折彎,即可插入Arduino的排母:

「長腳型」排針

排針上頭的黑色塑膠,可以用蠻力讓它移到中間的位置,以便銜接兩邊的排母:

使用排針銜接Arduino和薄膜按鍵模組

4×4薄膜鍵盤的Arduino按鍵偵測程式

撰寫Arduino按鍵偵測程式,最簡單也是最好的方式,就是採用既有的程式庫。本單元將示範使用Keypad程式庫,把偵測到的按鍵字元顯示在序列埠監控視窗。請按此下載Keypad程式庫(原始出處在這篇keypad介紹文),解壓縮之後,置入Arduino的libraries路徑:

Keypad程式庫

底下的程式,修改自Keypad程式庫的“HelloKeypad”範例,使用此程式庫,我們的程式碼需要定義按鍵模組的行(col)、列(row)數、連接Arduino的腳位以及按鍵所代表的字元

#include <Keypad.h>    // 引用Keypad程式庫

#define KEY_ROWS 4 // 按鍵模組的列數
#define KEY_COLS 4 // 按鍵模組的行數

// 依照行、列排列的按鍵字元(二維陣列)
char keymap[KEY_ROWS][KEY_COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

byte colPins[KEY_COLS] = {9, 8, 7, 6};	   // 按鍵模組,行1~4接腳。
byte rowPins[KEY_ROWS] = {13, 12, 11, 10}; // 按鍵模組,列1~4接腳。 

// 初始化Keypad物件
// 語法:Keypad(makeKeymap(按鍵字元的二維陣列), 模組列接腳, 模組行接腳, 模組列數, 模組行數)
Keypad myKeypad = Keypad(makeKeymap(keymap), rowPins, colPins, KEY_ROWS, KEY_COLS);

void setup(){
  Serial.begin(9600);
}
  
void loop(){
  // 透過Keypad物件的getKey()方法讀取按鍵的字元
  char key = myKeypad.getKey();
  
  if (key){  // 若有按鍵被按下…
    Serial.println(key);  // 顯示按鍵的字元
  }
}

編譯並上傳程式碼,再開啟「序列監控視窗」,按下薄膜鍵盤的任何按鍵,該字元將顯示在序列埠監控視窗。

按鍵偵測與掃描原理

為了方便解說,筆者把4×4按鍵簡化成3×1,像下圖這樣串連三個開關,連接到同一個微控制器的輸入腳。此外,因為要簡化開關電路,所以要啟用微控器內部的上拉電阻(請參閱《超圖解Arduino互動設計入門》第四章「啟用微控器內部的上拉電阻」一節,4-13頁):

掃描按鍵的原理

假設開關的「行1」~「行3」輸入端全都輸入高電位,無論開關是否被按下,Arduino將接收到高電位(1)。為了檢測到其中按鍵被按下,程式必須依序將「行1」~「行3」腳位設定成低電位。

掃描按鍵的原理

輪到「行2」腳輸入低電位,此時,微控器的輸入腳也將接收到低電位(0),由此可知連接「行2」的「開關B」被按下了

掃描按鍵的原理

輪到「行3」腳輸入低電位,由於「開關C」未被按下,因此微控器的輸入腳接收到高電位(1)。

掃描按鍵的原理

到此,偵測按鍵的程式必須再次回到「行1」,輸入低電位…如此反覆循環掃描,才能持續偵測到某個按鍵是否被按下。實際的程式需要運用雙重迴圈,才能分批掃描每一列:

掃描按鍵的雙重迴圈

雙重迴圈的練習,請參閱《超圖解Arduino互動設計入門》第8章「LED矩陣動畫與多維陣列程式設計」一節,8-28頁。

自行撰寫掃描按鍵的程式

根據以上說明,自行撰寫掃描按鍵的程式碼:

const byte colPins[4] = {9, 8, 7, 6};     // 設定「行」腳位
const byte rowPins[4] = {13, 12, 11, 10}; // 設定「列」腳位
const char keymap[4][4] = {     // 設定按鍵的「行、列」代表值
    {'1','2','3','A'}, 
    {'4','5','6','B'}, 
    {'7','8','9','C'},
    {'*','0','#','D'}
};

byte i, j;      // 暫存迴圈的索引數字
byte scanVal;   // 暫存掃描到的按鍵值

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

  for (i = 0; i < = 3; i++) {
    pinMode(rowPins[i], INPUT);
    pinMode(colPins[i], OUTPUT);
    digitalWrite(colPins[i], HIGH);
    digitalWrite(rowPins[i], HIGH);
  }
}

void loop() {
  for (i = 0; i <= 3; i++) {
    for (j = 0; j <= 3; j++) {
      digitalWrite(colPins[j], LOW);
      scanVal = digitalRead(rowPins[i]);

      if (scanVal == LOW) {    // 如果輸入值是「低電位」…
        Serial.println(keymap[i][j]);  // 輸出按鍵代表的字元
        delay(200);  // 掃描按鍵的間隔時間
        digitalWrite(colPins[j], HIGH);
        break;       // 跳出迴圈
      }
      digitalWrite(colPins[j], HIGH);
    }
  }
}

Keypad程式庫的運作方式大致上面的程式相同,主要是多了消除彈跳(debounce)的程式(相關說明請參閱第四章「解決開關訊號的彈跳問題」一節,4-15頁),而且按鍵掃描的間隔時間是透過比對時間差,而非使用delay。上面的程式用於幫助理解掃描按鍵的原理,在實際專案製作上,請使用Keypad程式庫。

未完,待續…

延伸閱讀

Posts created 467

8 thoughts on “Arduino 4×4薄膜鍵盤模組實驗(一):按鍵掃描程式原理說明

  1. 請問一下
    1.
    Keypad() 這函式是只能接受 Keypad( char , byte , byte , int , int ) 這樣的型態嗎?
    byte colPins[KEY_COLS] = {9, 8, 7, 6};
    byte rowPins[KEY_ROWS] = {13, 12, 11, 10};
    這兩行腳位宣告,我把型態變成int後就在Keypad()出現 no matching function

    2.
    #define KEY_ROWS 4 // 按鍵模組的列數
    #define KEY_COLS 4 // 按鍵模組的行數
    如果把這兩行定義變成
    int KEY_ROWS = 4;
    int KEY_COLS = 4;
    後面只要跟這兩變數有關的都會錯誤,說沒有宣告…
    這是為什麼呢?

    1. hi vivian:

      因為Arduino的C程式,不允許使用變數定義陣列的範圍,請改用常數,例如:

      const byte KEY_ROWS = 4; // 按鍵模組的列數
      const byte KEY_COLS = 4; // 按鍵模組的行數

      thanks,
      jeffrey

    1. 有收錄在《超圖解Arduino互動設計入門》第三版,第四版因為新增其他內容所以沒有收錄。

      thanks,
      jeffrey

    2. 呃…第5版應該也不會收錄,《超圖解ESP32深度實作》新書的低功耗藍牙(BLE)人機介面單元,也有用到這個鍵盤模組,但部份內文同樣是參照到這系列貼文,沒有全部收錄。

      thanks,
      jeffrey

    1. 可以,要搭配具備USB介面或者藍牙介面的微控器。我用過ESP32製作藍牙鍵盤滑鼠。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

Related Posts

Begin typing your search term above and press enter to search. Press ESC to cancel.

Back To Top