Hello,
I made a post a while ago under programming questions (Teensy keyboard troubleshooting) but I've realised it's actually a hardware problem so am creating a new thread in (hopefully) the right place.
I am building a keyboard and having trouble with the matrix. I am using a Teensy 4.1, with the code found here (at bottom of this post also): https://www.gammon.com.au/forum/?id=14175
Upon advice from the previous thread, I have added pullup resistors on all the rows and columns. I have tried both 4.7k and 10k resistors with limited success.
Previously I was having trouble with each key registering a key press for both the key intended and the key below. Using any value resistor has reduced most of this.
Issues I am still having include:
- Some keys output the key below. E.g. Key 0 outputs 'Key 22 pressed'
- Some keys don't register a key press at all, or only work occasionally
- Some keys registering multiple presses each time.
All switches and diodes have been tested, and there are no shorts.
Key layout is 22 columns, 6 rows
Key outputs using 4.7k resistors are in the images here (Apologies, I think I'm too new to upload photos directly).
On column 6, all the keys were registering multiple key presses. I assumed this was due to too little resistance. I've tried replacing the 4.7k with a 10k and a 6.8k, and both give no output. I've also tried 470ohm and 1k and those outputted multiple key presses for key 6 and 28 when pressing key 6.
I've tried changing some of the resistors on the other problematic columns and had similar results.
Any guidance or ideas would be greatly appreciated, many thanks in advance.
// Keypad_Decoder
//
// Author: Nick Gammon
// Date: 17th February 2018
/*
*
*
*/
// Outputs to Serial in the format: 0b1nnnnnnn for a key down and 0b0nnnnnnn for a key-up
// nnnnnnn will be the current row/column combination
// Also every HEARTBEAT_TIME outputs 0xFF if all keys are up (heartbeat)
#include <limits.h> /* for CHAR_BIT */
const byte ROWS = 6;
const byte COLS = 22;
const bool ENABLE_PULLUPS = true; // make false if you are using external pull-ups
const unsigned long DEBOUNCE_TIME = 10; // milliseconds
const unsigned long HEARTBEAT_TIME = 2000; // milliseconds
const bool DEBUGGING = true; // make true for human-readable output
// define here where each row and column is connected to
const byte rowPins [ROWS] = {38,37,36,35,34,33}; //connect to the row pinouts of the keypad
const byte colPins [COLS] = {3,4,5,6,7,8,9,10,11,12,13,14,40,24,25,26,27,28,29,30,31,32}; //connect to the column pinouts of the keypad
// See: http://c-faq.com/misc/bitsets.html
#define BITMASK(b) (1 << ((b) % CHAR_BIT))
#define BITSLOT(b) ((b) / CHAR_BIT)
#define BITSET(a, b) ((a)[BITSLOT(b)] |= BITMASK(b))
#define BITCLEAR(a, b) ((a)[BITSLOT(b)] &= ~BITMASK(b))
#define BITTEST(a, b) ((a)[BITSLOT(b)] & BITMASK(b))
// number of items in an array
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
// total number of keys
const byte TOTAL_KEYS = ROWS * COLS;
// remember previous setting of each key
char lastKeySetting [(TOTAL_KEYS + CHAR_BIT - 1) / CHAR_BIT]; // one bit each, 0 = up, 1 = down
unsigned long lastKeyTime [TOTAL_KEYS]; // when that key last changed
unsigned long lastHeartbeat; // when we last sent the heartbeat
void setup ()
{
Serial.begin (115200);
while (!Serial) { } // wait for Serial to become ready (Leonardo etc.)
// set each column to input-pullup (optional)
if (ENABLE_PULLUPS)
for (byte i = 0; i < COLS; i++)
pinMode (colPins [i], INPUT_PULLUP);
} // end of setup
void loop ()
{
byte keyNumber = 0;
unsigned long now = millis (); // for debouncing
// check each row
for (byte row = 0; row < ROWS; row++)
{
// set that row to OUTPUT and LOW
pinMode (rowPins [row], OUTPUT);
digitalWrite (rowPins [row], LOW);
// check each column to see if the switch has driven that column LOW
for (byte col = 0; col < COLS; col++)
{
// debounce - ignore if not enough time has elapsed since last change
if (now - lastKeyTime [keyNumber] >= DEBOUNCE_TIME)
{
bool keyState = digitalRead (colPins [col]) == LOW; // true means pressed
if (keyState != (BITTEST (lastKeySetting, keyNumber) != 0)) // changed?
{
lastKeyTime [keyNumber] = now; // remember time it changed
// remember new state
if (keyState)
BITSET (lastKeySetting, keyNumber);
else
BITCLEAR (lastKeySetting, keyNumber);
if (DEBUGGING)
{
Serial.print (F("Key "));
Serial.print (keyNumber);
if (keyState)
Serial.println (F(" down."));
else
Serial.println (F(" up."));
} // if debugging
else
Serial.write ((keyState ? 0x80 : 0x00) | keyNumber);
} // if key state has changed
} // debounce time up
keyNumber++;
} // end of for each column
// put row back to high-impedance (input)
pinMode (rowPins [row], INPUT);
} // end of for each row
// Send a heartbeat code (0xFF) every few seconds in case
// the receiver loses an occasional keyup.
// Only send if all keys are not pressed (presumably the normal state).
if (now - lastHeartbeat >= HEARTBEAT_TIME)
{
lastHeartbeat = now;
bool allUp = true;
for (byte i = 0; i < ARRAY_SIZE (lastKeySetting); i++)
if (lastKeySetting [i])
allUp = false;
if (allUp)
{
if (DEBUGGING)
Serial.println (F("No keys pressed."));
else
Serial.write (0xFF);
} // end of all keys up
} // end if time for heartbeat
} // end of loop