If you want to use the keypad library there are still a couple of outstanding issues.
Though Nick Gammons changes Arduino Forum were partly implemented a slight bug crept in.
Spot the difference.
Suggested:
void Keypad::initializePins(){
for (byte r=0; r<size.rows; r++){
//configure row pin modes and states
pinMode(rowPins[r],INPUT);
digitalWrite(rowPins[r],HIGH);
}
for (byte c=0; c<size.columns; c++){
//configure column pin modes and states
pinMode(columnPins[c],OUTPUT);
digitalWrite(columnPins[c],HIGH);
}
}
In Current Version:
void Keypad::initializePins(){
for (byte r=0; r<size.rows; r++){
//configure row pin modes and states
pinMode(rowPins[r],INPUT);
digitalWrite(rowPins[r],HIGH);
}
for (byte c=0; c<size.columns; c++){
//configure column pin modes and states
pinMode(columnPins[c],OUTPUT);
digitalWrite(columnPins[c],LOW);
}
}
This means before every scan. All column outputs are taken low. Turning on all columns.
Then during every scan for each column it is taken low again (allready in that state) before scanning each row. Once each row has scanned it takes it high before doing the next column. Basically they start all on and are turned off one by one. So when it scans first column it will pick up keys from any column. On subsequent columns if basically picks up that column and all buttons to the right.
That means that any button press has the equivalence of pressing all buttons to its left as well. Fortunately this still works miraculously as the right most key is the last one to be scanned and therefore the only one remembered.
NO FOR MORE SERIOUS ISSUE:
It is claimed that the library does not need diodes. This would be true if the statement that all ouputs not being pulled low are converted to inputs to make them high impedance, but i see no evidence of this. Now if you pressed two buttons from the same row but on different colums you could short an output in its high state to one in its low state.
So here is how i suggest it can be cured.
initilizePins method should be:
void Keypad::initializePins(){
for (byte r=0; r<size.rows; r++){
//configure row pin modes and states
pinMode(rowPins[r],INPUT);
digitalWrite(rowPins[r],HIGH);
}
for (byte c=0; c<size.columns; c++){
//configure column pin modes and states
pinMode(columnPins[c],INPUT);
digitalWrite(columnPins[c],HIGH);
}
}
scanKeys method should be:
boolean Keypad::scanKeys() {
static unsigned int allKeys=0;
byte curKey=0;
boolean anyKey;
// Assume that some other device is sharing the data pins used by the
// keypad. If that is the case then the pins will need to be re-intialized
// each time before they are used.
initializePins();
// I rewrote this method to provide a status change (anyKey OPEN/CLOSED) to the
// getKeyState() function which handles debouncing. Now we can scan the keypad
// without having to worry about huge debounce time delays.
for( int c=0; c<size.columns; c++) {
pinMode(columnPins[c],OUTPUT);
digitalWrite(columnPins[c], LOW);
for( int r=0; r<size.rows; r++) {
curKey = digitalRead(rowPins[r]);
allKeys += curKey;
if(curKey==0) currentKey = keymap[c+(r*size.columns)];
// All keys have been scanned. Set 'anyKey' value for use by getKeyState().
if( r==(size.rows-1) && c==(size.columns-1) ) {
if( allKeys==(size.rows*size.columns) )
anyKey = OPEN;
else
anyKey = CLOSED;
}
}
pinMode(columnPins[c],INPUT);
digitalWrite(columnPins[c], HIGH);
}
allKeys = 0;
return anyKey; // Status tells if keys are OPEN or CLOSED.
}