Code for keypads

I got a matrix keypad for a project. I’m trying to write my own keypad code to integrate into my other code. So I downloaded the keypad library from playground and peeked inside.

Here is initialization code for column and row pins. I’ve never used matrix keypads but the concept doesn’t seem so hard. In this particular lib, column pins are pulled HIGH, and row pins are turned into inputs with internal pullup resistor. So when you scan columns, you pull each column pin LOW and read which row is LOW to find out the key pressed. Was the above an appropriate way to access matrix keypads?

What I don’t understand about the lib’s init code is that they put column init inside a for-loop for row init so the column gets initialized multiple times. No big deal but any reason I don’t really know? Can someone provide an answer? Thanks.

void Keypad::initializePins(){
	for (byte r=0; r<size.rows; r++){
        for (byte c=0; c<size.columns; c++){
			pinMode(columnPins[c],OUTPUT);
			digitalWrite(columnPins[c],HIGH);
        }
		//configure row pin modes and states
		pinMode(rowPins[r],INPUT);
		digitalWrite(rowPins[r],HIGH);
    }
}

Sensing code. They pull one column pin LOW and scan all row pins, then pull the column back to HIGH and move on to the next column.

char Keypad::getKey(){
	char key = NO_KEY; // Assume that no key is pressed, this is the default return for getKey()
    for (byte c=0; c<size.columns; c++){
		digitalWrite(columnPins[c],LOW);	// Activate the current column.
		for (byte r=0; r<size.rows; r++){	// Scan all the rows for a key press.
			//  The user pressed a button for more then debounceTime microseconds.
			if (currentKey == keymap[c+(r*size.columns)]){
				// Button hold
				if (((millis()-lastUpdate) >= holdTime) && digitalRead(rowPins[r]) == LOW){
					transitionTo(HOLD);
				}
				// Button release
				if (((millis()-lastUpdate) >= debounceTime) && digitalRead(rowPins[r]) == HIGH){
					transitionTo(RELEASED);
					currentKey = NO_KEY;
				}
			} 
			// Button pressed event.  The user pressed a button.
			else if (((millis()-lastUpdate) >= debounceTime) && digitalRead(rowPins[r]) == LOW){
				digitalWrite(columnPins[c],HIGH);	// De-activate the current column.
				key = keymap[c+(r*size.columns)];
				lastUpdate = millis();
				goto EVALUATE_KEY; 			// Save resources and do not attempt to parse to keys at a time
			} 
		}
		digitalWrite(columnPins[c],HIGH);	// De-activate the current column.
	}
	
	EVALUATE_KEY:
	if (key != NO_KEY && key != currentKey){ 
		currentKey = key;
		transitionTo(PRESSED);
		return currentKey;
	} 
	else{
		return NO_KEY;
	}
}

Was the above an appropriate way to access matrix keypads?

Yes.

What I don't understand about the lib's init code is that they put column init inside a for-loop for row init so the column gets initialized multiple times. No big deal but any reason I don't really know? Can someone provide an answer? Thanks.

It's been pointed out before that the initialization code is sub-optimal. There was a proposed fix. I don't know who should incorporate the fix.

Paul,

Thanks for your answers. I am going to write my own keypad code then. I'll give it a try after holidays (7/4). I'm thinking about making a pad like this:

               Y  U  N
0  2  4  6  8  L     R
1  3  5  7  9  *  D  *

The "*" are two LED indicators.

Just one more question:

If I use 4 rows and 4 columns, I'm out 8 pins for 16 buttons. Can I do 2 rows and 8 columns and just drive the columns with 595? This way I just use 5 pins and I can easily scan columns with shifting a B00000001 across the register and could add a second 595 to control a few status lights. Thanks.

just a (probably newbee stupid) question, as I have never worked with keypads (or many other components) before, but ..

couldn't you connect a different valued resistor to each key, and connect then all to the same analog input. Shouldn't be too hard to write code to link the different voltages received on the pin to the corresponding key, and would only use 1 input pin on the board.

2c

How do I make a 16-key panel with analog pad then? I’ve seen some versions of analog pad with 5 keys but not as many as 16. Maybe it is easily doable by dividing 1024 into 16 bins. Any circuit diagram you can suggest? Maybe an R-2R ladder used backwards?

OK, I gave it a thought, too many registers, even one register per button :) I'll stay on digital matrix pad.