Troubleshooting a 4x4 16 keys keypad [solved]

Hello community, I come here because I'm not quite sure if I'm doing something wrong or if there is something wrong with my hardware. Here's the deal:

  1. I have connected as directed per tutorial a 4x4 keypad to an arduino leonardo using the following code:
#include <Keypad.h>

const byte ROWS = 4; // Four rows
const byte COLS = 4; // Four columns
// Define the Keymap
char keys[ROWS][COLS] = {
// Connect keypad ROW0, ROW1, ROW2 and ROW3 to these Arduino pins.
byte rowPins[ROWS] = { 6, 8, 7, 9 };
// Connect keypad COL0, COL1 and COL2 to these Arduino pins.
byte colPins[COLS] = { 2, 5, 4, 3 }; 

// Create the Keypad
Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

void setup()

void loop()
  char key = kpd.getKey();
  if(key)  // Check for a valid key.

It works quite ok, but some keys are not read by the Arduino when the're hit.

  • Keys that don't work: 2, 3, A & 4, 7, *.
  • All rest work and show accordingly
  • All col OR row have at least 1 key working OK

What am i missing here?

Sounds like a bdy [edit: bad] keypad.
If you use a jumper wire and connect the two pins that make up any keypress, can you see all the characters?

For example, put a jumper wire on 6, and touch it to 2,5,4,3, then 7 and 2,5,4,3, then 8 and 2,5,4,3, then 9 and 2,5,4,3.

Hey CrossRoads,

what's a bdy ? a typo or abbreviation for...

If I jump pin 6 with the other pins, I get all the keys that are missing on ROW0 (2,3,A) without pressing the keypad.
Also if I jump 2 with the rest, I get all the missing keys in COL0 (4,7,*) without pressing the keypad.

What should I do?

After all it wasn't a hardware problem, I believe that with my keypad there's a need to include some pull-up resistors. I actually figure this out after changing my scope. As I wouldn't be able to use as many I/O pins anyways, I connected the keypad via I2C with a PCF8574AN (As instructed) with the Arduino Playground - I2CPortExpanderAndKeypads library and the modifications suggested by PaulS here:,102018.0.html (5th post).

I was able to connect a pad directly to the digital pins on my mega. Below is the code I used.

Happy coding :slight_smile:

int row[4] = {36,34,32,30};  // from left to right, the first four connections
int col[4] = {28,26,24,22};  // from left to right, the next four connections
int results[4][4] = {{1,2,3,-2},{4,5,6,-3},{7,8,9,-4},{-6,0,-7,-5}};  // This is the array to match up the keystroke with the associated value
                                                                      // I use the special keys as function keys, so I want to capture those strokes.

void setup()
  for (int x=0;x<4;x++)  {
  pinMode(row[x],OUTPUT);          //  I assign the rows as output
  pinMode(col[x],INPUT_PULLUP);    //  I assign the columns as inputs and use the internal pullup (probably not necessary, but I did it anyway)
  digitalWrite(row[x],HIGH);       //  I cycle through and set up the entire row index as high.
  Serial.begin(38400);             //  This is used just to debug. Make sure you test all the keys, as it is easy to plug things into the wrong pin.

int keyboard_read() {              //  This is the meaty function to scan the keypad
 int value = -1;                   //  I set -1 as my null value, as I want to be able to receive back a zero key-stroke
  for (int x=0;x<4;x++)  {
    digitalWrite(row[x],LOW);      //  I set the active row as low
    delay(5);                      //  I put the delay in, because I want to be sure the full row is pulled low, again probably not necessary
    for (int y=0;y<4;y++)  {
       if (digitalRead(col[y]) == LOW) {  //  As I cycle through, the key pressed will be the one that returns a low signal
         delay(250);                      //  I know I'm cheating, but I just put a delay in after a key-stroke to make sure there is time to let the key up before the next read
         value=results[x][y];      //  After reading which row and column was pressed, I pull the associated value from the key array.
  digitalWrite(row[x],HIGH);       //  Don't forget to set the row back to high, so the next row read is correct.
return(value);                     //  The function then returns the value read, or the default -1 if no key was pressed

void loop()
  int key_stroke;                 
if (key_stroke != -1)  {              //  Yes, I could have read the function straight in, but because of where I put the delay on a key-press
 Serial.println(String(key_stroke));  //  I would often have the if statement trigger, only to read the board again and return the no-key -1 value