50Views5Replies

Author Options:

Need help in debugging code for 4x4 keypad Answered

Greetings,
I am relatively new to this forum. Please pardon me for any mistakes I make while posting new topic in this forum. With this being said, I have been trying to write a 'standard' 4x4 keypad scanning code. However, the code did not work correctly, I have tried to debug my code using the Serial Monitor with no luck. According to the Serial Monitor, only few keys would actually be correctly registered (usually 5, 8, 4, and 1), and the rest give me no output at all. However, when I insert a delay of 1 second within the loop itself, all the keys are correctly registered, but it give me a 'cyclic' pattern (ie. pressing 7, will give me 1, 4, and then 7). I have spent a lot of time on this, and a Google search of 4x4 keypad always refer me to the Arduino library.

Overview of the code:

set column pins to pull_up resistor, and set the row pins as output. Begin to scan the column pins with a given row pin output, and return the index.

*Note: I know there is an Arduino library for this, but I want to practice in coding/programming the 4x4 keypad, and I don't know where did I went wrong.


const byte ROWS = 4;
const byte COLS = 4; int rowval; int colval; char hexaKeys[ROWS][COLS] = {{'1', '2', '3', 'A'}, {'4', '5', '6', 'B'}, {'7', '8', '9', 'C'}, {'*', '0', '#', 'D'}}; int rowPins[ROWS] = {7, 6, 5, 4}; int colPins[COLS] = {3, 2, 1, 0}; boolean col_state; boolean prev_state; void setup() { Serial.begin(9600); for (int i = 0; i < 4; i++) { pinMode(colPins[i], INPUT_PULLUP); pinMode(rowPins[i],OUTPUT); digitalWrite(rowPins[i],HIGH); } }
void loop() {
  
  for (int i = 0; i < 4; i++) {
    rowval=0;
    colval=0;
    pinMode(rowPins[i], OUTPUT);
    digitalWrite(rowPins[i], LOW);
    for (int j = 0; j < 4; j++) {
      col_state = digitalRead(colPins[j]);
      if (col_state == 0) {
        prev_state=col_state;
        delay(50);
        if(digitalRead(colPins[j])==prev_state){
        rowval = i;
        colval = j;
        Serial.println(hexaKeys[rowval][colval]);
        delay(1000); ///add a 1 second delay here to make the output of Serial monitor more manageable
        digitalWrite(rowPins[i],HIGH);
        pinMode(rowPins[0], INPUT);
        break;
        }
      }
    }
    if(rowval!=0 && colval!=0)
      break;
  }
}

Discussions

1
ShamnadT
ShamnadT

4 weeks ago

Hi Arthur091,

Please consider printing the value outside the key scanning loop. That'll be easier to program.


const byte ROWS = 4;
const byte COLS = 4;
char hexaKeys[ROWS][COLS] = {{'1', '2', '3', 'A'}, {'4', '5', '6', 'B'}, {'7', '8', '9', 'C'}, {'*', '0', '#', 'D'}};
int rowPins[ROWS] = {7, 6, 5, 4};
int colPins[COLS] = {3, 2, 1, 0};
boolean col_state;
boolean Key_pressed ;
char Key;
void setup() {
Serial.begin(9600);
for (int i = 0; i < 4; i++) {
pinMode(colPins[i], INPUT_PULLUP);
pinMode(rowPins[i], OUTPUT);
digitalWrite(rowPins[i], HIGH);
}
}
void loop() {
Key_pressed = false; // initialize everytime
for (int i = 0; i < 4; i++) {
digitalWrite(rowPins[i], LOW);
for (int j = 0; j < 4; j++) {
col_state = digitalRead(colPins[j]); // read first time
if (col_state == 0) {
delay(10); // 10-20ms is enough
if(digitalRead(colPins[j])==col_state){ // compare with previous read
Key = hexaKeys[i][j];
Key_pressed = true;
digitalWrite(rowPins[i],HIGH);
break; // first for-loop break
}
}
}
if(Key_pressed){
break; // second for loop break if key got already
}
}
if(Key_pressed) {
Serial.println(Key);
delay(300); ///300ms is enough. Putting high values will give irregular readings
}
}

Check one of my keypad program in Github. It's a complex program but may help you to learn some coding practices.
0
Arthur091
Arthur091

Reply 4 weeks ago

I have tried your implementation. The keypad still give me weird outputs. At this point, I'm really thinking there are shorts within my 4x4 keypad. When I pressed 1, sometimes it gives me 4,7, and * as output. I can't think of why it behaving this way except for the whole column is being shorted together.

0
ShamnadT
ShamnadT

Reply 4 weeks ago

It seems to be hardware problem. If the same thing happens with 2,5,8,0 column values and others, then it might not be a hardware problem. This can happen if multiple rows are pulled LOW. At any point, more than one row shouldn't be pulled LOW. Check your program doesn't do this.

Anyway, I want point out 3 more things.
1) Check your hardware. Use a multi-meter to check shorts in keypad. Or, replace the keypad.
2) The debounce delay might be too short. Increase it step by step up to 50ms and test.
3) Modify your program to get the key value when the user releases the key from pressed state. That means, confirm the value only after column input pin goes from LOW to HIGH(rising edge detection). This prevents 'same key' repetition but, blocks the program execution.


0
Downunder35m
Downunder35m

4 weeks ago

Sure you won't need an input instead of the output here?
pinMode(colPins[i], INPUT_PULLUP);

pinMode(rowPins[i],OUTPUT);

0
Arthur091
Arthur091

Reply 4 weeks ago

My plan is to attach all the column pins to the pull-up resistor. Then I will read the row pins and if the Arduino detect LOW on the column pin with a given row pins currently being chosen, it will return index of i and j to fetch the corresponding key.