Keypad library seems to be broken on Teensy LC at least ~ clock speed

fitek

Member
Hi all,

Keypad library appears to be at least semi-broken on Teensy LC. Lowering clock speed appears to help somewhat. Wondering if anyone has suggestions for alternatives?

I had a 4x6 matrix keypad fully working with I think a Teensy 2.0 some time back. I wired the same matrix up to a Teensy LC and it was wonky-- some keys don't trigger and I have ghost presses. I literally spent about 3 days stubbornly troubleshooting all the hardware but...

I wired up a 1x1 matrix using the CustomKeypad example-- just one wire for row, one for column. Per a forum post, I see that timing might be an issue. At the default clock speed, the example doesn't detect key presses at all using digital pins 15 and 16. If I halve the clock speed it works but not reliably. There are no other options in the menu to slow it down further. I'm out of ideas on what to try next. Teensy 2.0 is not available for purchase anymore.
 
Always post complete source code & details to reproduce any issue!
Could you observe the forum rules as shown above then someone might be able to replicate the problem and help you.
The keypad library has not changed since 2013.
 
Could you observe the forum rules as shown above then someone might be able to replicate the problem and help you.
The keypad library has not changed since 2013.

It's just the CustomKeypad example Arduino provides. Below is the example with some extra debugging lines added and changed to a 1x1 matrix. I feel like I should be logging a bug somewhere, but no idea where. I tried poking around the library but not seeing why it might stop working at faster speeds.

I suspect that using an alternative keypad implementation will be the fix, but I don't know of any others, hence my post...

Code:
/* @file CustomKeypad.pde
|| @version 1.0
|| @author Alexander Brevig
|| @contact alexanderbrevig@gmail.com
||
|| @description
|| | Demonstrates changing the keypad size and key values.
|| #
*/
#include <Keypad.h>

const byte ROWS = 1; //four rows
const byte COLS = 1; //four columns
//define the cymbols on the buttons of the keypads
char hexaKeys[ROWS][COLS] = {
  {1}
 /* {'0','1','2','3'},
  {'4','5','6','7'},
  {'8','9','A','B'},
  {'C','D','E','F'}*/
};
byte rowPins[ROWS] = {15}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {16}; //connect to the column pinouts of the keypad

//byte rowPins[ROWS] = {3, 2, 1, 0}; //connect to the row pinouts of the keypad
//byte colPins[COLS] = {7, 6, 5, 4}; //connect to the column pinouts of the keypad

//initialize an instance of class NewKeypad
Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS); 

void setup(){
  Serial.begin(9600);
  Serial.println("starting");
}
  
void loop(){
  char customKey = customKeypad.getKey();
  
  if (customKey){
    Serial.print(customKey);
    Serial.print(" ");
    Serial.println(millis());
  }
}
 
Have you tried altering the "DebounceTime" or the "HoldTime"?
See keypad.h

That seems to let me make it worse but not better. I have DMM on it and the switch reads 180 ohms when pressed. I can press it 7 times in a row and I'll get usually about 4 key presses acknowledged. If I lower debounce time below 10 not surprisingly I sometimes get multiple presses for one key press. I wonder also if maybe the internal pull ups are different than those in the Teensy 2.0, it being a completely different chip. I'm going to wire an external pullup and report back. I know I did another project with a membrane switch where i ended up using 10k external pull up resistors.
 
Hmm changed line 68 of Keypad.cpp from INPUT_PULLUP to INPUT and put a 10k pull up on the row pin (15) since it's the rows that were set to INPUT_PULLUP. DMM on pin 15 and it's always 3.3v. Hmm am I missing something else? relevant lines from Keypad.cpp

Code:
void Keypad::scanKeys() {
	// Re-intialize the row pins. Allows sharing these pins with other hardware.
	for (byte r=0; r<sizeKpd.rows; r++) {
		pin_mode(rowPins[r],INPUT); // was INPUT_PULLUP
	}

	// bitMap stores ALL the keys that are being pressed.
	for (byte c=0; c<sizeKpd.columns; c++) {
		pin_mode(columnPins[c],OUTPUT);
		pin_write(columnPins[c], LOW);	// Begin column pulse output.
		for (byte r=0; r<sizeKpd.rows; r++) {
			bitWrite(bitMap[r], c, !pin_read(rowPins[r]));  // keypress is active low so invert to high.
		}
		// Set pin to high impedance input. Effectively ends column pulse.
		pin_write(columnPins[c],HIGH);
		pin_mode(columnPins[c],INPUT);
	}
}
 
The code you posted in #6 sets the column pin to low and immediately after reads in the row pins. The Teensy4 is fast enough that the level change on the column pin may have not yet arrived/stabilized at the keypad when you read in the row pins. Can you check if a delaymicroseconds(10) after setting the column pin to LOW fixes it? If so, you can reduce the delay to smaller values until it gets unstable again.
 
The Teensy4 is fast enough that the level change on the column pin may have not yet arrived/stabilized at the keypad when you read in the row pins.
He's using an LC.
 
Oh, that makes it less likely. Anyhow, adding that delay is quickly done and would at least exclude timing issues.
 
Hi,

I confirm about delayMicroSeconds, got the problem with Teensy 4.1.
Just modified the library like so :
Code:
// Private : Hardware scan
void Keypad::scanKeys() {
	// Re-intialize the row pins. Allows sharing these pins with other hardware.
	for (byte r = 0; r < sizeKpd.rows; r++) {
		pin_mode(rowPins[r], INPUT_PULLUP);
	}

	// bitMap stores ALL the keys that are being pressed.
	for (byte c = 0; c < sizeKpd.columns; c++) {
		pin_mode(columnPins[c], OUTPUT);
		pin_write(columnPins[c], LOW);	// Begin column pulse output.
[COLOR="#FF0000"]		delayMicroseconds(10);
[/COLOR]		for (byte r = 0; r < sizeKpd.rows; r++) {
			bitWrite(bitMap[r], c, !pin_read(rowPins[r]));  // keypress is active low so invert to high.
		}
		// Set pin to high impedance input. Effectively ends column pulse.
		pin_write(columnPins[c], HIGH);
		pin_mode(columnPins[c], INPUT);
	}
}
 
Back
Top