# Arduino matrix buttons not working,

Joined Nov 21, 2018
807
I made a 3*5 arduino matrix buttons, used A2-A5, but not works well, actually, not response at all.

Code:
byte rows[] = {9,10,11};
const int rowCount = sizeof(rows)/sizeof(rows[0]);
// JP2 and JP3 are outputs

byte cols[] = {8,A2,A3,A4,A5};
const int colCount = sizeof(cols)/sizeof(cols[0]);
byte keys[colCount][rowCount];
void setup() {
Serial.begin(9600);
for(int x=0; x<rowCount; x++) {
Serial.print(rows[x]); Serial.println(" as input");
pinMode(rows[x], INPUT);
}
for (int x=0; x<colCount; x++) {
Serial.print(cols[x]); Serial.println(" as input-pullup");
pinMode(cols[x], INPUT_PULLUP);
}

}
// iterate the columns
for (int colIndex=0; colIndex < colCount; colIndex++) {
// col: set to output to low
byte curCol = cols[colIndex];
pinMode(curCol, OUTPUT);
digitalWrite(curCol, LOW);
// row: interate through the rows
for (int rowIndex=0; rowIndex < rowCount; rowIndex++) {
byte rowCol = rows[rowIndex];
pinMode(rowCol, INPUT_PULLUP);
pinMode(rowCol, INPUT);
}
// disable the column
pinMode(curCol, INPUT);
}
}
void printMatrix() {
for (int rowIndex=0; rowIndex < rowCount; rowIndex++) {
if (rowIndex < 10)
Serial.print(F("0"));
Serial.print(rowIndex); Serial.print(F(": "));
for (int colIndex=0; colIndex < colCount; colIndex++) {
Serial.print(keys[colIndex][rowIndex]);
if (colIndex < colCount)
Serial.print(F(", "));
}
Serial.println("");
}
Serial.println("");
}
void loop() {
printMatrix();
}

Last edited:

#### djsfantasi

Joined Apr 11, 2010
8,255
I’m very confused... your cols[] array looks like it refers to you rows... And vice versa!

Your technique for disabling pins likely won’t work. I can’t be sure because I’m on a mobile device and I cannot read the code clearly.

Plus there are discrepancies between your description, the code and even within the code.

No offense intended, but I think you’ve confused yourself. I’ll respond in detail soon, but what I see now is a spaghetti plate of code.

#### sagor

Joined Mar 10, 2019
671
Another thing to remember is to put in pull up resistors, or pull-downs (depending if sensing high or low).
Often input pins run at high impedance, and voltage levels can be in some range that cannot be read properly.
You may only need pull ups (or pulldowns) on the columns only, or the rows only, again depending on how you read them
I find that on some processors, the internal pullups are just not enough...

Joined Nov 21, 2018
807
I’m very confused... your cols[] array looks like it refers to you rows... And vice versa!

Your technique for disabling pins likely won’t work. I can’t be sure because I’m on a mobile device and I cannot read the code clearly.

Plus there are discrepancies between your description, the code and even within the code.

No offense intended, but I think you’ve confused yourself. I’ll respond in detail soon, but what I see now is a spaghetti plate of code.
Thank you.
I exchanged the cols and rows, nothing improved.

Joined Nov 21, 2018
807
Another thing to remember is to put in pull up resistors, or pull-downs (depending if sensing high or low).
Often input pins run at high impedance, and voltage levels can be in some range that cannot be read properly.
You may only need pull ups (or pulldowns) on the columns only, or the rows only, again depending on how you read them
I find that on some processors, the internal pullups are just not enough...
Thanks.
Yes, the cols or rows pulluped.

#### KeithWalker

Joined Jul 10, 2017
2,295
I made a 3*5 arduino matrix buttons, used A2-A5, but not works well, actually, not response at all.

Code:
byte rows[] = {9,10,11};
const int rowCount = sizeof(rows)/sizeof(rows[0]);
// JP2 and JP3 are outputs

byte cols[] = {8,A2,A3,A4,A5};
const int colCount = sizeof(cols)/sizeof(cols[0]);
byte keys[colCount][rowCount];
void setup() {
Serial.begin(9600);
for(int x=0; x<rowCount; x++) {
Serial.print(rows[x]); Serial.println(" as input");
pinMode(rows[x], INPUT);
}
for (int x=0; x<colCount; x++) {
Serial.print(cols[x]); Serial.println(" as input-pullup");
pinMode(cols[x], INPUT_PULLUP);
}

}
// iterate the columns
for (int colIndex=0; colIndex < colCount; colIndex++) {
// col: set to output to low
byte curCol = cols[colIndex];
pinMode(curCol, OUTPUT);
digitalWrite(curCol, LOW);
// row: interate through the rows
for (int rowIndex=0; rowIndex < rowCount; rowIndex++) {
byte rowCol = rows[rowIndex];
pinMode(rowCol, INPUT_PULLUP);
pinMode(rowCol, INPUT);
}
// disable the column
pinMode(curCol, INPUT);
}
}
void printMatrix() {
for (int rowIndex=0; rowIndex < rowCount; rowIndex++) {
if (rowIndex < 10)
Serial.print(F("0"));
Serial.print(rowIndex); Serial.print(F(": "));
for (int colIndex=0; colIndex < colCount; colIndex++) {
Serial.print(keys[colIndex][rowIndex]);
if (colIndex < colCount)
Serial.print(F(", "));
}
Serial.println("");
}
Serial.println("");
}
void loop() {
printMatrix();
}
View attachment 183484
Before you do anything else, check the continuity of each push button by measuring the resistance between the rows and columns pins on the connector to make sure it is working correctly.
You have written a very confusing program that will be difficult to debug. Why did you use functions when each one is used just once each time through the loop. It would make much more sense and make it much easier to follow if you just put the code from the functions into the loop. Then you could add serial prints to see what is going on at different places in the loop.
While you are debugging, add a delay in the end of the loop so you don't get flooded out with data.

Last edited:

Joined Nov 21, 2018
807
Before you do anything else, check the continuity of each push button by measuring the resistance between the rows and columns pins on the connector to make sure it is working correctly.
You have written a very confusing program that will be difficult to debug. Why did you use functions when each one is used just once each time through the loop. It would make much more sense and make it much easier to follow if you just put the code from the functions into the loop. Then you could add serial prints to see what is going on at different places in the loop.
While you are debugging, add a delay in the end of the loop so you don't get flooded out with data.
Thanks,
I did checked them all works fine.
The code I copied from:
https://www.baldengineer.com/arduino-keyboard-matrix-tutorial.html
Just changed the pins cause of I used digital pin for some thing else.
Can you refer a better code please.

#### djsfantasi

Joined Apr 11, 2010
8,255

When scanning a keyboard matrix, either the rows or column pins are inputs. The other choice must be an output.

So let’s say the rows are inputs. That means the columns must be outputs. All your outputs should be initialized with a HIGH value. All your inputs or rows should be initialized as INPUT_PULLUP.

CHANGING PIN MODES OUTSIDE OF SETUP IS UNNECESSARY AND SHOULD BE AVOIDED!

To scan, you repeat the following steps:
1. Set one column pin LOW
2. Loop through all rows, performing s digitalRead() on the associated pin.
3. If you find a row pin that is LOW, then the button at [row][column] is pressed. (There is a potential issue of bounce, but get this working first)
4. Otherwise after you’ve checked every row...
5. Set the active column pin HIGH
6. Set the next column pin LOW (if the next column is greater than the number of columns, set the column back to zero)
7. Loop through all columns.
First thing that I noticed is the original author is doing all sorts of crap (technical term) with pinMode(). Almost all of it is unnecessary, and I said almost as a waffle. IMHO, if it’s not in setup() - it’s unnecessary. I’ve seen code similar to what the author has used, but it’s crap (that technical term again) and shows a lack of understanding of Arduinos.

I just printed out the code. But I have to leave for a doctors appointment soon. Hopefully, you or someone might see something with the pseudo code. I’m having trouble reading the code with all of the superfluous pinMode() commands.

Joined Nov 21, 2018
807

When scanning a keyboard matrix, either the rows or column pins are inputs. The other choice must be an output.

So let’s say the rows are inputs. That means the columns must be outputs. All your outputs should be initialized with a HIGH value. All your inputs or rows should be initialized as INPUT_PULLUP.

CHANGING PIN MODES OUTSIDE OF SETUP IS UNNECESSARY AND SHOULD BE AVOIDED!

To scan, you repeat the following steps:
1. Set one column pin LOW
2. Loop through all rows, performing s digitalRead() on the associated pin.
3. If you find a row pin that is LOW, then the button at [row][column] is pressed. (There is a potential issue of bounce, but get this working first)
4. Otherwise after you’ve checked every row...
5. Set the active column pin HIGH
6. Set the next column pin LOW (if the next column is greater than the number of columns, set the column back to zero)
7. Loop through all columns.
First thing that I noticed is the original author is doing all sorts of crap (technical term) with pinMode(). Almost all of it is unnecessary, and I said almost as a waffle. IMHO, if it’s not in setup() - it’s unnecessary. I’ve seen code similar to what the author has used, but it’s crap (that technical term again) and shows a lack of understanding of Arduinos.

I just printed out the code. But I have to leave for a doctors appointment soon. Hopefully, you or someone might see something with the pseudo code. I’m having trouble reading the code with all of the superfluous pinMode() commands.
Thank you,
You are right, I do need re write the code.

#### djsfantasi

Joined Apr 11, 2010
8,255

So, I've made some minor, but critical changes. I didn't try to redesign your code, but some work in that area is needed... If you run this, then any key you press will show as a zero in the keys matrix/array. Nothing will print out until you enter an "!" character through the console. A critical addition I made was in your code to check for an "!". What would happen is if there was no character, the sketch would loop. When it does that, the readMatrix function would clear out all previous data. So unless you were extremely lucky to type !<return> at the exact moment that readMatrix exited, nothing would ever appear to work. The suggested code to wait for a character should fix that problem.

Code:
byte rows[] = {9,10,11};
const int rowCount = sizeof(rows)/sizeof(rows[0]);

byte cols[] = {8,A2,A3,A4,A5};
const int colCount = sizeof(cols)/sizeof(cols[0]);

byte keys[colCount][rowCount];

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

// Row pins are define as output; You set one LOW at a time
// Col pins are  input. When one row is LOW, the column of
// a pressed key will be LOW as well.

for(int x=0; x<rowCount; x++) {
pinMode( rows[x], OUTPUT); // define cols as output
digitalWrite(rows[x],HIGH};
}

for (int x=0; x<colCount; x++) pinMode(cols[x],INPUT_PULLUP); // define cols as input, active low!

}

// iterate through the columns
for (int colIndex=0; colIndex < colCount; colIndex++) {
byte colPin = cols[colIndex];
digitalWrite(colPin, LOW); // select one column to scan

// interate through the rows
for (int rowIndex=0; rowIndex < rowCount; rowIndex++) {
byte rowPin = rows[rowIndex];
}

// disable the column
digitalWrite(colPin, HIGH);
}
}

void printMatrix() {
for (int rowIndex=0; rowIndex < rowCount; rowIndex++) {
if (rowIndex < 10)
Serial.print(F("0"));
Serial.print(rowIndex); Serial.print(F(": "));
for (int colIndex=0; colIndex < colCount; colIndex++) {
Serial.print(keys[colIndex][rowIndex]);
if (colIndex < colCount)
Serial.print(F(", "));
}
Serial.println("");
}
Serial.println("");
}

void loop() {

while (!Serial.available()); // wait for a character

// Read included in while() loop to flush buffer

}
I've pulled out a couple of egregious problems...

Code:
//    for(int x=0; x
//    This is not even a valid statement!
and

Code:
//    for (int x=0; x<="" li="">
//    Not sure what this statement will do.
//    At first glance, it will loop ONCE where x=0
//    But it's missing properly formatted termination criteria!
and then there is this problem:

Code:
//    if (Serial.read()=='!')
//        printMatrix();
// ... I assume you only want to printout the matrix when you type a "!"
// into the console... You should only read if there are characters present
// And you should read until the buffer is empty... Entering a ! into the console
// actually enters two characters, the exclamation mark and a return

Joined Nov 21, 2018
807

So, I've made some minor, but critical changes. I didn't try to redesign your code, but some work in that area is needed... If you run this, then any key you press will show as a zero in the keys matrix/array. Nothing will print out until you enter an "!" character through the console. A critical addition I made was in your code to check for an "!". What would happen is if there was no character, the sketch would loop. When it does that, the readMatrix function would clear out all previous data. So unless you were extremely lucky to type !<return> at the exact moment that readMatrix exited, nothing would ever appear to work. The suggested code to wait for a character should fix that problem.

Thank you.
I'll test it out later on.

Code:
byte rows[] = {9,10,11};
const int rowCount = sizeof(rows)/sizeof(rows[0]);

byte cols[] = {8,A2,A3,A4,A5};
const int colCount = sizeof(cols)/sizeof(cols[0]);

byte keys[colCount][rowCount];

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

// Row pins are define as output; You set one LOW at a time
// Col pins are  input. When one row is LOW, the column of
// a pressed key will be LOW as well.

for(int x=0; x<rowCount; x++) {
pinMode( rows[x], OUTPUT); // define cols as output
digitalWrite(rows[x],HIGH};
}

for (int x=0; x<colCount; x++) pinMode(cols[x],INPUT_PULLUP); // define cols as input, active low!

}

// iterate through the columns
for (int colIndex=0; colIndex < colCount; colIndex++) {
byte colPin = cols[colIndex];
digitalWrite(colPin, LOW); // select one column to scan

// interate through the rows
for (int rowIndex=0; rowIndex < rowCount; rowIndex++) {
byte rowPin = rows[rowIndex];
}

// disable the column
digitalWrite(colPin, HIGH);
}
}

void printMatrix() {
for (int rowIndex=0; rowIndex < rowCount; rowIndex++) {
if (rowIndex < 10)
Serial.print(F("0"));
Serial.print(rowIndex); Serial.print(F(": "));
for (int colIndex=0; colIndex < colCount; colIndex++) {
Serial.print(keys[colIndex][rowIndex]);
if (colIndex < colCount)
Serial.print(F(", "));
}
Serial.println("");
}
Serial.println("");
}

void loop() {

while (!Serial.available()); // wait for a character

// Read included in while() loop to flush buffer

}
I've pulled out a couple of egregious problems...

Code:
//    for(int x=0; x
//    This is not even a valid statement!
and

Code:
//    for (int x=0; x<="" li="">
//    Not sure what this statement will do.
//    At first glance, it will loop ONCE where x=0
//    But it's missing properly formatted termination criteria!
and then there is this problem:

Code:
//    if (Serial.read()=='!')
//        printMatrix();
// ... I assume you only want to printout the matrix when you type a "!"
// into the console... You should only read if there are characters present
// And you should read until the buffer is empty... Entering a ! into the console
// actually enters two characters, the exclamation mark and a return

#### djsfantasi

Joined Apr 11, 2010
8,255
Did you mean to say anything?