Fads to Obsessions and Beyond...




Free domain for life, exceptional technical support, website transfer

Matrix Keypad

Demonstrate interfacing Arduino Nano with matrix keypad. In particular, using I2C with the PCF8574A 8-bit port expansion chip, which only requires 2 x I/O pins on the Arduino Nano.

User input can be obtained via discrete, independant buttons (e.g., toggle the state of a particular function to be either 'on' or 'off') which are determined by reading the state of the button via a I/O port on the microcontroller. However, when 'numeric' and or 'text' user input is required, having discrete buttons for each 'number' or 'letter' quickly outstrips the number of I/O pins available with boards such as the Arduino Nano. Hence, matrix keypads are used instead to decrease the number of required I/O pins. Matrix keypads operate with a process called 'keypad scanning' in conjunction with circuitry attached to the matrix keypad with pullup resistors at either the 'rows' or 'columns'.

Matrix Keypad Schematic

Matrix Keypad Diagram

Matrix Keyboard 'scanning'

The microcontroller determines which individual key is pressed using the following steps:

  • Step 1: First set all ROWS to OUTPUT and set them at +5V. Next set all COLUMNS as INPUT to sense the HIGH logic. Now consider a button is pressed on keypad. And that key is at 2ND COLUMN and 3rd ROW. With the button being pressed the current flows through the connection between Row 2 to Column 2. With that a voltage of +5V appears at terminal C2. Since the COLUMN pins are set as INPUTS, the controller can sense C2 going high. The controller is coded to remember that C2 going high and the button pressed is in C2 COLUMN.
  • Step 2: Next set all COLUMNS to OUTPUT and set them at +5V. Next set all ROWS as INPUT to sense the HIGH logic. Since the key pressed is at 2ND COLUMN and 3rd ROW. The current now flows through the connection between Column 2 to Row 3. With that current flow a positive voltage of +5V appears at Row 3 pin. Since all ROWS are set as INPUTS, the controller can sense +5V at Row 3 pin. The controller is coded to remember the key being pressed at third ROW of KEYPAD MATRIX.
  • Step 2: The microcontroller now knows the COLUMN number of key pressed and the ROW number. With that the matched key being pressed can be found. In this way the individual particular key being pressed on the 4X4 KEYPAD MODULE can be determined.

This sounds a little complex, but the Arduino 'Keypad library' (1) provides the necessary 'keypad scanning' code, abstracting the circuit operation to simply calling the appropriate read statement. This enables for example, a 4 x 4 matrix keypad (i.e., sixteen (16) keys) to be read using only eight (8) I/O pins on the Arduino Nano, rather than 16 I/O pins if the keypad was in effect discrete buttons.

While the Arduino Nano is advantageous in terms of small physical size and low cost per GPIO/onboard peripheral available (particularly good for 'small' DIY projects controlling a single sensor and or output for example), the small physical size means limited input/output pins. Therefore, using the Arduino 'Keypad library' with a 4x4 matrix keypad means the Arduino Nano input pins are severly limited for connectivity with other circuit components.

Conveniently, there are I/O port expanders available such as the PCF8574 which can be interfaced using only 2 pins, and provide 8 GPIO's. Further, the PCF8574 can be daisy-chained so that multiple's of additional 8 GPIO's can be achieved. The interface for connecting the PCF8574 to the Arduino Nano is called I2C (I2C is an acronym for “Inter-Integrated Circuit”).

This project will focus on using the PCF8574 with a 4x4 matrix keypad, as minimising the number of I/O ports used on the Arduino Nano to connect a keypad will likely be the general requirement.

In addition to the benefit of gaining additional GPIO's by using PCF8574 port expanders is learning how to use the I2C interface. There are literally thousands of components that use the I2C interface such a real-time clocks, digital potentiometers, temperature sensors, digital compasses, memory chips etc. So once the PCF8574 interface to the Arduino Nano is successfully achieved, the same process can then be used with additional components as required.

First some background about I2C and then some specifics about the PCF8574.

Details on how to setup the Arduino IDE and environment to programme Arduino Nano microcontrollers are given in the Arduino Nano introduction.

I2C “Inter-Integrated Circuit”

I2C orginated from Philips Semiconductor (now NXP) as a way of standardising the data lines that travel between various integrated circuits, which only requires two wires (SDA – data, and SCL – clock). In terms of the hardware and communications protocol, the software library abstracts the majority of the details i.e., you don't really need to know - but if interested, the sparkfun page gives an easy introduction (4). However, some knowledge about the hardware/signal levels is necessary so the importance of having pull-up resistors on the SDA/SCL lines is appreciated.

Each I2C bus consists of two signals: SCL and SDA. SCL is the clock signal, and SDA is the data signal. The clock signal is always generated by the current bus master. The I2C bus drivers are “open drain”, meaning that they can pull the corresponding signal line low, but cannot drive it high. This eliminates possibility of data bus contention where one device is trying to drive the line high while another tries to pull it low. However, this means it is mandatory that each signal line has a pull-up resistor on it, to restore the signal to high when no device is asserting it low.

The usual value for these pull-up resistors is 4K7 (but sometimes if multiple devices on the bus 10K may be appropriate). Also, the I2C bus is meant for short distances (generally on the same PCB). The maximum length of an I2C bus is approximately 1 meter.

Devices with I2C can be connected in any physical order, there are 'address pins' on each device which can be phyiscally set to determine unique addresses.

PCF8574 Port Expander

The datasheet (see Bill of Materials Section) gives all the necessary details. Note there are alternatives to the PCF8574 (I just have a bunch of these available) such as the MCP23008 (which has 25mA sink/source per I/O pin) and 16-bit varieties (e.g. MCP23018 which gives 16 I/O lines on a single chip).

Important to realise is that the PCF8574 is a current sink device rather than current source. This means that external components need to be connected to Vcc via pull-up resistors.


The Arduino Nano board has a surface mount microcontroller with headers for all pins. Additionally, the board provides a 5V regulator for external DC power input and PCB copper traces that enable insertion into standard USB connector which can then be used for DC power source. There is an onboard LED to indicate power-on and an additional LED/resistor connected to pin1 for user control.

For convenience for this simple test, the USB power supply is used.

ISP programming is used as detailed in the Arduino Nano introduction.

Matrix Keypad

A matrix keypad is a combination of row and column circuits. The buttons themselves are simple switch like closures. There is 1 pin for each column and 1 pin for each row. So for the 4x4 keypad, there are 4 + 4 = 8 total pins. For the 3x4 keypad, there are 3 + 4 = 7 pins. Each of these pins needs to be connected to a separate digital pin on the microcontroller.

Matrix Keypad Schematic

Matrix Keypad Diagram

In addition, to enable the required 'keypad scanning' to be able to determine which individual key was pressed on the matrix keypad, the 'columns' or 'rows' of the matrix keypad need to be connected via pullup resistors (generally 10K ohm) to Vcc.

PCF8574 Port Expander

Pin 8 is connected to ground and pin 16 to Vcc (i.e., 5V). Pins 1 through 3 (A0, A1, A2 respectively) determine the device address. The PCF8574 has a device address of 0100 + A2,A1,A0 whereas the PCF8574A has a device address of 0111 + A2, A1, A0. Therefore, with pins 1 through 3 on the PCF8574A connected to ground, the device address will be 0111000 which is 0x38.

Pin 15 is the I2C data line, which is connected pin 23 (marked A4 on the Nano silk screen) on the Arduino Nano. Whereas, pin 14 is the I2C clock line, and is connected to pin 24 (marked A5 on the Nano silk screen) on the Arduino Nano.

As discussed in the Background Section, pull-up 4K7 resistors are mandatory on pin 14 and 15.


Note: Image loading can be slow depending on server load.

  • Matrix Keypad SchematicMatrix Keypad Schematic

    Silver Membership registration gives access to full resolution schematic diagrams.

    Arduino Nano Matrix Keypad with PCF8574A Schematic

    Arduino Nano Matrix Keypad with PCF8574A Schematic

This project did not require a PCB.

The construction was done using prototyping board. See the photographs and schematic diagram sections.

Qty Schematic Part-Reference Value Notes
Resistors
2R10,R114K71/4W, 10% 
4R6 to R910K1/4W, 10% 
Diodes
4D6 to D9LED 
Integrated Circuits
1U1Arduino/Nanomicrocontroller datasheet
1U3PCF8574A8-bit port expander datasheet
Miscellaeous
3J1wiresDupont pin jumper wires
1Z1Keypad4x4 matrix Keypad
Description Downloads
Bill of Materials Text File Download

Before connecting the Arduino Nano to the USB port, check for any shorts (direct positive voltage to ground connection) as this could damage both the Nano board and the USB/PC.

Initial testing of a I2C interfaced device (and if the I2C interface library is working on the Arduino Nano) is to use the I2C scanner sketch (Code Snippet 1 below).

Once it is determined that I2C communication is working with the Arduino Nano and the PCF8574A, the next steps are using the various keypad libraries to use the PCF8574 to get the input from the matrix keypad (Code Snippet 2 below).

I2C Device Address Scanner

The I2C device (the PCF8574A in this case) needs to be connected via the SDA and SCK pins (with pullup resistors, and obviously connect Gnd and Vcc) to the Arduino Nano. The Serial Monitor on the Arduino IDE is used so output can be directed via USB to a PC Com serial port.

Using a PCF8574A and PCF8574 pins 1 through 3 (ie A0 to A2) tied to ground produces an I2C device address of 0+0111+0+0+0 = 0x38, so the code below should report a single device found with address of 0x38 hexadecimal. Altering which of the PCF8574A pins 1 through 3 are tied to ground or Vcc will change the reported address (the datasheet gives the table showing what the resultant addresses should be).

Code Snippet 1: I2C Device Address Scanner


 #include 

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

 	  bool PCF_Found = false ;

     // SEARCH FOR PCF8574
     for(int i = 0;i < 8;i++) {
         int address = PCF8574::combinationToAddress(i, false);
         if(PCF8574(address).read() != -1) {
             Serial.print("Found PCF8574: addr = 0x");
             Serial.println(address, HEX);
				 PCF_Found = true ;
         }
     }

     // SEARCH FOR PCF8574A
     for(int i = 0;i < 8;i++) {
         int address = PCF8574::combinationToAddress(i, true);
         if(PCF8574(address).read() != -1) {
             Serial.print("Found PCF8574A: addr = 0x");
             Serial.println(address, HEX);
				 PCF_Found = true ;
         }
     }
     if (!PCF_Found ) {
     Serial.println("Search done. No PCF8574 devices found.") };
 }

 void loop() {}
   				

Using 4x4 Matrix keypad with PCF8574

The matrix keypad library by 'joeyoung' on github (2) contains several separate arduino format libraries, each one adding to the library Keypad external expansion port communication via an I2C port on the Arduino Nano. The 'Keypad_I2C' is the particular library for use with the PCF8574 expansion chip.

The library by 'joeyoung' builds upon the 'Keypad library for Arduino' (3) which also needs to be installed with the Arduino IDE.

The benefit of using the PCF8574 with the keypad, rather than just using the normal Arduino method of direct connection to the various ports on the Nano (or other Arduino board), is that only 2 pins on the Nano are required.

The following code snippet demonstrates using the PCF8574 to interface the Arduino Nano with a 4x4 matrix keypad (as per the circuit in the Schematics Section). The schematic shows 10 Kohm pull-up resistors for the columns (which is needed for a 'direct connect' version). However, this is not required for the PCF8574A which has lightly pulled up 'input' state for I/O pins - by default it will read as a high logic level, but connecting the GPIO to ground will cause it to read as a low logic level.

Code Snippet 2: 4x4 Matrix keypad connected to PCF8574


#include 
#include 
#include 
#define I2CADDR 0x38

const byte ROWS = 4; //four rows on keypad
const byte COLS = 4; //four columns on keypad

// define the character represented by each key
char keys[ROWS][COLS] = {
 {'1','4','7','0'},
 {'2','5','8','F'},
 {'3','6','9','E'},
 {'A','B','C','D'}
};

byte rowPins[ROWS] = {0, 1, 2, 3}; //PCF8574 pins connect to the row pinouts of the keypad
byte colPins[COLS] = {4, 5, 6, 7}; //PCF8574 pins connect to the column pinouts of the keypad

TwoWire *jwire = &Wire;   //test passing pointer to keypad lib
Keypad_I2C kpd( makeKeymap(keys), rowPins, colPins, ROWS, COLS, I2CADDR, PCF8574, jwire );

void setup(){
 Serial.begin(9600);
 while( !Serial ){ /*wait*/ }
 jwire->begin();
 kpd.begin();
 Serial.print( "start with pinState = " );
 Serial.println( kpd.pinState_set(), HEX );
}
void loop(){

 char key = kpd.getKey();

 if (key){
   Serial.println(key); //echo key to the serial monitor/connected PC
 }
}
               

The circuit is the basic minimum required to enable the Arduino Nano microcontroller to operate after being programmed with a suitable .hex file. So this circuit was only laid out on a breadboard.

Before connecting the Arduino Nano to the USB port, check for any shorts (direct positive voltage to ground connection) as this could damage both the Digispark board and the USB/PC.

As discussed in the Background Section, pull-up 4K7 resistors are mandatory on pin 14 and 15 of the PCF8574. This is probably the most common Gotch'ya.

Another common problem is to remember that the I2C address for the PCF8574 (0100+A2,A1,A0) is different to the PCF8574A (0111+A2,A1,A0).


Note: Video loading can be slow depending on server load.

No video's for this topic.


Comments/Questions

No comments yet.

Add Comment/Question

Only Logged-In Members can add comments

"If we could sell our experiences for what they cost us, we'd all be millionaires".

Please donate any amount to help with hosting this web site.

If you subscribe (only $2/annum) you can view the site without advertisements and get emails abouts updates etc.

X

Sorry!

Only logged-in users with Silver Membership and above can download.


Silver Membership is only $2, so join now!