Learn to code

Arduino Home

Lessons 1
Arduino - Getting Started
Lessons 2
Arduino - Basics
Lessons 3
Arduino - Serial Communication
Lessons 4
Arduino - Digital / Analog
Lessons 5
Arduino - Visual Output
Lessons 6
Arduino - Motor Control
Lessons 7
Arduino -LCD Displays
Lessons 8
Arduino -LCD Displays

Reading a 4 x 4 keypad with Arduino

in Arduino Digital / Analog

In this tutorial, we will read the values of a keypad without using libraries. This tutorial is for those who want to understand how the keypad works. Firstly, we will learn how the keypad works. In other words, how a keypad detects key presses. An easy example is given by printing the key on the Serial Monitor. We are going to use a 3x4 matrix membrane keypad. 

Parts you will need

Arduino Uno Rev3 Arduino Uno Rev3 × 1
Keypad Keypad × 1
Dupont Wires Dupont Wires × 7

Arduinoplatform is a participant in several affiliate programs. This means that I will earn a commision if you buy a product from the affiliated websites through clicking on the links provided above.

How does the keypad work?

The buttons of each keypad are arranged in rows and columns. The keypad that we are using has 4 rows and 3 columns. Beneath each key is a switch. Each switch is connected with the other switches in the row.  Each row and column should be connected to the Arduino Board. In total, we have 7 pins that we are going to connect.

Arduino detects which button is pressed on the keypad by detecting the row and columns pin that is detected to the button.

  1. If no buttons are pressed, all of the column pins are HIGH, and all of the rows are LOW.
  2. When a button is pressed, the column pin of the button is pulled LOW.
  3. The Arduino knows which column the button is in; however, it still needs to know the row. It does this by switching all the rows to HIGH, and at the same time, reading the column pins to detect which column is HIGH.
  4. When the column pin is HIGH, the Arduino has found the row that is connected to the button.

BreadBoard Layout

This sketch will only work correctly if the wiring agrees with the code. Check carefully, as incorrect wiring can short out the pins, and that could damage your controller chip.

  1. Place the keypad next to the Arduino
  2. Look closely to the diagram, the wires should be connected according to the schematic. Otherwise, the keypad will not work
  3. Connect the Arduino Board with your computer.
  4. Open the Arduino IDE.
  5. Open a new sketch and copy-paste the code sketch code below
  6. Click the Verify button on the top left side of the screen to be sure that there are no problems
  7. Click the Upload button (next to the Verify button).
  8. Open the serial monitor window, you should see the number that you press on the Serial Monitor.

The Code

/*
  Keypad sketch
  prints the key pressed on a keypad to the serial port
*/
// number of rows in the keypad
const int numRows = 4; 
// number of columns
const int numCols = 3; 
// number of milliseconds for switch to be stable
const int debounceTime = 20; 

// keymap defines the character returned when the 
// corresponding key is pressed
const char keymap[numRows][numCols] = {
  { '1', '2', '3' } ,
  { '4', '5', '6' } ,
  { '7', '8', '9' } ,
  { '*', '0', '#' }
};

// this array determines the pins used for rows and columns
// Rows 0 through 3
const int rowPins[numRows] = { 7, 2, 3, 6 }; 
// Columns 0 through 2
const int colPins[numCols] = { 5, 8, 4 }; 

void setup()
{
  Serial.begin(9600);
  
  for (int row = 0; row < numRows; row++)
  { 
    // Set row pins as input
    pinMode(rowPins[row], INPUT); 
    // turn on Pull-ups
    digitalWrite(rowPins[row], HIGH); 
  }
  for (int column = 0; column < numCols; column++)
  {
    // Set column pins as outputs for writing
    pinMode(colPins[column], OUTPUT); 
    // Make all columns inactive
    digitalWrite(colPins[column], HIGH); 
  }
}

void loop()
{
  char key = getKey();
  // if the character is not 0 then it's a valid key press
  if ( key != 0) { 
    Serial.print("Got key ");
    Serial.println(key);
  }
}


// returns with the key pressed, or 0 if no key is pressed
char getKey()
{
  // 0 indicates no key pressed
  char key = 0; 
  for (int column = 0; column < numCols; column++)
  {
    // Activate the current column.
    digitalWrite(colPins[column], LOW); 
    // Scan all rows for a key press.
    for (int row = 0; row < numRows; row++) 
    {
      // Is a key pressed?
      if (digitalRead(rowPins[row]) == LOW) 
      {
        delay(debounceTime); // debounce
        // wait for key to be released
        while (digitalRead(rowPins[row]) == LOW); 
         // Remember which key was pressed.
        key = keymap[row][column];
      }
    }
     // De-activate the current column.
    digitalWrite(colPins[column], HIGH);
  }
  // returns the key pressed or 0 if none
  return key; 
}

Code Explanation

This code is a bit complicated if you are not familiar with Arduino. Each of the four rows on the keypad is connected to an input pin and each column is connected to an output pin. Since we will use the rows and columns of the keypad a lot we are declaring them as a constant variable at the beginning of the sketch. Furthermore, we declare a constant variable for debounce to detect if the switch activated by the button is stable.

// number of rows in the keypad
const int numRows = 4;
// number of columns
const int numCols = 3;
// number of milliseconds for switch to be stable
const int debounceTime = 20;

After the the number of columns and rows are defined, corresponding characters of those rows and columns are defined in the char keymap. This is a multi-dimensional array that contains 4 rows and three columns.

// keymap defines the character returned when the 
// corresponding key is pressed
const char keymap[numRows][numCols] = {
  { '1', '2', '3' } ,
  { '4', '5', '6' } ,
  { '7', '8', '9' } ,
  { '*', '0', '#' }
};

The below code sets the corresponding pins from your Arduino Board to the columns and rows of the keypad.

// this array determines the pins used for rows and columns
// Rows 0 through 3
const int rowPins[numRows] = { 7, 2, 3, 6 }; 
// Columns 0 through 2
const int colPins[numCols] = { 5, 8, 4 }; 

We are starting serial communication between the Arduino and the computer.

  Serial.begin(9600);

 

There are two loops in the setup() part of the sketch.

The first for loop() sets the pins connected to the rows of the keypad as input. Since we configure the pin as an input pin connected to the keypad, the least you want is that the signal is disturbed. Therefore we activate the internal pull-up resistors that prevent the pin from floating by forcing the signal to VCC when it is not actively driven.

  for (int row = 0; row < numRows; row++)
  { 
    // Set row pins as input
    pinMode(rowPins[row], INPUT); 
    // turn on Pull-ups
    digitalWrite(rowPins[row], HIGH); 
  }
  for (int column = 0; column < numCols; column++)
  {
    // Set column pins as outputs for writing
    pinMode(colPins[column], OUTPUT); 
    // Make all columns inactive
    digitalWrite(colPins[column], HIGH); 
  }

 

Before we continue with the loop, let’s look at the function that is called on in the loop, namely getKey().

The matric keypad consists of normally open switches that connect a row with a column when pressed. It only makes an electrical connection when the key is pushed.

The getKey() function sets the pin for each column LOW and then checks to see if any of the row pins are LOW. Since pull-up resistors are used, the rows will be pulled up unless the switch is closed. (closing a switch pressing a key produces a LOW signal on the input pin).

In the getKet function, a small delay is used to ensure that the switch is not bouncing.  The code waits for the switch, key from keypad, to be released and the character associated with the switch is found in the keymap array and returned from the function. When there is no switch pressed, the function returns 0.

// returns with the key pressed, or 0 if no key is pressed
char getKey()
{
  // 0 indicates no key pressed
  char key = 0; 
  for (int column = 0; column < numCols; column++)
  {
    // Activate the current column.
    digitalWrite(colPins[column], LOW); 
    // Scan all rows for a key press.
    for (int row = 0; row < numRows; row++) 
    {
      // Is a key pressed?
      if (digitalRead(rowPins[row]) == LOW) 
      {
        delay(debounceTime); // debounce
        // wait for key to be released
        while (digitalRead(rowPins[row]) == LOW); 
         // Remember which key was pressed.
        key = keymap[row][column];
      }
    }
     // De-activate the current column.
    digitalWrite(colPins[column], HIGH);
  }
  // returns the key pressed or 0 if none
  return key; 
}

 

In the void loop() part of the sketch, we call on the function getKey() and place the function’s returned value into a character variable called key.  The if statement checks whether the returned value is not 0 and if that condition is true the pressed key on the keypad is printed to the serial monitor.

// returns with the key pressed, or 0 if no key is pressed
char getKey()
{
  // 0 indicates no key pressed
  char key = 0; 
  for (int column = 0; column < numCols; column++)
  {
    // Activate the current column.
    digitalWrite(colPins[column], LOW); 
    // Scan all rows for a key press.
    for (int row = 0; row < numRows; row++) 
    {
      // Is a key pressed?
      if (digitalRead(rowPins[row]) == LOW) 
      {
        delay(debounceTime); // debounce
        // wait for key to be released
        while (digitalRead(rowPins[row]) == LOW); 
         // Remember which key was pressed.
        key = keymap[row][column];
      }
    }
     // De-activate the current column.
    digitalWrite(colPins[column], HIGH);
  }
  // returns the key pressed or 0 if none
  return key; 
}

 

You might think that the code above is a bit much coding in the main sketch. You could also use a keypad with a library. Using a library simplifies the code, as you will see in the next tutorial.

Previous Post
Reliable detecting a switch with Arduino
Next Post
Reading analog values with Arduino
You must be logged in to post a comment.
Menu