sparkfun 4x4 keypad matrix

I was looking through the sparkfun website and found these keypad matrices....

which allow each button to be individually lit by an led. i've decided to use a keypad encoder to limit the number of pins i need to use to run it, so i have a couple of 74C922 keypad encoders on order from Farnell. heres the data sheet

the idea is that the 74C922 ic reads the key pad matrix, and when a button is pressed, it sends a logic signal via the data pin to the arduino, which tells the arduino to read the four input pins from the 74C922 and to save these inputs as a 4 digit binary number. this 4 digit binary number relates to one of the 16 buttons on the keypad.

so far i have written this code, that reads the data pin, and if its HIGH, then it switches on an led on pin 13, and then reads the input pins and prints the data to the serial connection.

int dataPin = 2; // data pin
int in1Pin = 3; // input pin 1
int in2Pin = 4; // input pin 2
int in3Pin = 5; // input pin 3
int in4Pin = 6; // input pin 4
int ledPin = 13; // led pin
int val = 0; 

void setup() {
  pinMode(dataPin, INPUT); // declare pins as input or output
  pinMode(in1Pin, INPUT);
  pinMode(in2Pin, INPUT);
  pinMode(in3Pin, INPUT);
  pinMode(in4Pin, INPUT);
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600); // begin serial

void loop() {
   val = digitalRead(dataPin);  // read data pin value
  if (val == HIGH) {  // if HIGH
  digitalWrite(ledPin, HIGH);     // switch on led pin  
    digitalRead(in1Pin); // read inputs
    Serial.print(in1Pin, BYTE); // print inputs to serial connection
    Serial.print(in2Pin, BYTE);
    Serial.print(in3Pin, BYTE);
    Serial.print(in4Pin, BYTE);
  } else {
    digitalWrite(ledPin, LOW); // if data pin LOW, switch off led pin, and do nothing.

it complies fine, but is so far untested as i dont have the parts yet. what i would like to do is to hold the 4 digit binary number as a string, then print to the serial port. at the moment i think this code will print each input byte individually, but i dont really understand how to store it as a string just yet.

so, any comments or ideas to make it run smoother?



may I suggest that you give the result of the digitalRead action to some variable in the main loop?


void loop() { val = digitalRead(dataPin); // read data pin value if (val == HIGH) { // if HIGH digitalWrite(ledPin, HIGH); // switch on led pin digitalRead(in1Pin); // read inputs digitalRead(in2Pin); digitalRead(in3Pin); digitalRead(in4Pin);


like: tempVar1 = digitalRead(in1Pin); tempVar2 = digitalRead(in2Pin);


so that the read values are somewhere to get.

I have just done this using a Parallax 4x4 Keypad and the 74C922. It’s a little tricky because you need to pool for changes on data available from LOW to HIGH, and then stop pooling until DA is back to LOW, otherwise it will send the key’s value until you release it. There is also some issues with timing. Below is what I came up with (it also includes a little password example… just for fun). Improvements could be made, such as using a “soft delay” with millis() instead of using delay() (if you make it work, can you post an update?).

/* Parallax 4x4 Keypad using 74C922 16 Keys Encoder
 * ---------------
 * Comments
 * (cleft) 2005 by Matthieu Lalonde
 * <>
 * <mailto:mlalonde(at)smurfturf(dot)net>
#define BAUD_RATE 9600
#define statusLED 12

// Inputs from the 74C922 16 Keys Encoder
#define inputKey1 8
#define inputKey2 9
#define inputKey3 10
#define inputKey4 11

// The key encoder will provide HIGH on this pin when new data is available
#define dataAvailable 7

// Needed to manage inputs in a proper fashion (one entry per push)
int dataAvail      = LOW;
int lastDataAvail  = LOW;
byte keyValue      = 0;

// We need to slow down things a little, otherwise the 74C922 misbehaves
int interval       = 15;

char passwdValue[5] = {
  15, 3, 13, 1};
char passwdEntry[5];
int  entryNbr   = 0;
int  badTries   = 0;

void setup(void) {
  // initialize inputs/outputs
  pinMode(dataAvailable, INPUT);

  pinMode(inputKey1, INPUT);
  pinMode(inputKey2, INPUT);
  pinMode(inputKey3, INPUT);
  pinMode(inputKey4, INPUT);

  // start serial


void loop(void) {
  dataAvail = digitalRead(dataAvailable);

  // Do we have a change in the state of dataAvailable or was the key just never released?
  if (dataAvail == HIGH && lastDataAvail == LOW) {
    lastDataAvail = dataAvail;

    // We do our business here
    keyValue = 0;
    keyValue = (digitalRead(inputKey1) << 3) + (digitalRead(inputKey2) << 2) + (digitalRead(inputKey3) << 1) + digitalRead(inputKey4);

    passwdEntry[entryNbr] = keyValue;

    Serial.print(keyValue, HEX);
    if (entryNbr == 4) {
      if (!strCompare(passwdValue, passwdEntry)) {
        Serial.print("We have a winner after ");
        Serial.println(" times!");
        entryNbr = 0;
        badTries = 0;
      else {
        Serial.print("We have a loser that tried ");
        Serial.println(" times!");
        entryNbr = 0;
  // We need to reset the state of dataAvailable
  if (dataAvail == LOW && lastDataAvail == HIGH) {
    lastDataAvail = dataAvail;

int strCompare(char *a, char *b) {
  while (a[0] && b[0]) {
    if (a[0] != b[0]) return 1;

  if (a[0] != 0 || b[0] != 0) return 1;

  return 0; //they are the SAME

// Reports the state of the controller via pin 13's led and serial
void reportAVRState(int howManyTimes, int leaveOn) {
  int i;

  pinMode(statusLED, OUTPUT);

  for (i=0; i< howManyTimes; i++) {
    digitalWrite(statusLED, HIGH);
    digitalWrite(statusLED, LOW);

  if (leaveOn) { 
    digitalWrite(statusLED, HIGH); 

  Serial.println("AVR Initialized");

Here is a picture of the circuit (using SparkFun’s protoshield):

You can see a video example here.

Arduino w / Keypad and feedback. Goodnight I'm doing a one pcb, which contains LCD 16x2 74LS164, 4x4 Keypad with PCF8574A / 74C922 for Arduino. You have an Eagle plane - Schematics - as are the connections?