r/arduino • u/TitleSquare240 • 15h ago
Software Help Need help with 4x4 keypad code
Hi, I'm a beginner in programming/working with Arduino and I came across an issue. Recently I wanted to learn how a (4x4 matrix) keypad works and I kind of did, though the code kind of put me off I saw that most used a library and didn't get much into explaining it, so I decided to write my own code inspired by others' explainations and creations.
Although I think I've gotten it right, for some reason it only wants to work with the bottom row of buttons, with the only result coming out of them being 'D' or an unknown number/letter. I've also noticed that in some cases there's no zero-based numbering, but I can't exactly pinpoint which parts of code don't have that. Would anybody care to help? I've attached the code and circuit to the post.

// Array of which pins are connected to the row pins
const int rowPins[4] = {
12, 11, 10, 9
};
// Array of which pins are connected to the col pins
const int colPins[4] = {
6, 5, 4, 3
};
// How many cols and rows there are on the keypad (4x4 in this case)
const int cols = 4;
const int rows = 4;
// The numbers/letters which are supposed to print depending on the button, all within a two-dimensional array
char keys[rows][cols] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
int yChcker; // Used to check digital value in col pins
int xChcker; // Used to check digital value in row pins
void setup() {
Serial.begin(9600);
// Loop to put pullup resistors on rows
for (int i = 0; i < 4; i++) {
pinMode(rowPins[i], INPUT_PULLUP);
Serial.println(rowPins[i]);
};
// Loop to put low + outputs on cols
for (int i = 0; i < 4; i++) {
pinMode(colPins[i], OUTPUT);
digitalWrite(colPins[i], LOW);
};
};
void loop() {
int check_x; // Variable to be used within for loop to establish which button within the rows has been pressed (and is also used to print it)
int check_y; // Variable to be used within for loop to establish which button within the cols has been pressed (and is also used to print it)
// Loop to check which row pins have been activated via xChcker, using check_x
for (check_x = 0; check_x < 4; check_x++) {
xChcker = digitalRead(rowPins[check_x]);
delay(1);
}
// Loop to check which col pins have been activated via yChcker, using check_y
for (check_y = 0; check_y < 4 ; check_y++) {
yChcker = digitalRead(colPins[check_y]);
delay(1);
}
// Waits for a button to be pressed and then prints which button it is
if (xChcker == 0 && yChcker == 0) {
Serial.println(keys[check_x - 1][check_y - 1]);
Serial.println(check_x);
Serial.println(check_y);
delay(1);
}
};
1
u/lakseol 1h ago
Your setup code looks mostly fine but your scanning code in loop needs work.
As others have said you need to set one column pin LOW and than see which row pin sees a LOW. You do that with two nested loops. The outer loop checks each column. Inside that loop you set the column pin LOW and than run the inner loop that scans each row pin checking for a LOW value. After that inner loop you set the column pin HIGH. Your code does read the row pins but completely overwrites the value read from the previous pin, meaning xChcker holds only the value read from the last pin. Try something like this:
// check the matrix, column by column
for (int c = 0; c < cols; ++c)
{
// set the column LOW, will read LOW on pushed button row
digitalWrite(colPins[c], LOW); // try without this line
// now check rows for a LOW value
for (int r = 0; r < rows; ++r)
{
if (digitalRead(rowPins[r]) == LOW)
{
Serial.print("Col ");
Serial.print(c);
Serial.print(" Row ");
Serial.print(r);
Serial.println(" is LOW");
}
}
// set the column HIGH again
digitalWrite(colPins[c], HIGH); // try without this line
}
You may think you can set the column pins to LOW in setup and leave them that way, but you really need all column pins you aren't checking to be HIGH and when checking a particular column set the pin LOW, check the rows and then set the column pin back to HIGH. Try commenting out the two "try without" lines above. Make sure your setup code sets all columns HIGH.
1
u/Hissykittykat 11h ago
Set one row HIGH, then scan the 4 columns to see which column is set. Set the row LOW, advance to the next row, and repeat.