[solved] Odd behavior on pin 13 for large Keymap on Teensy 3.1

I'm using a Teensy 3.1 with the Keymap library to allow me to use a keyboard key matrix. Everything seems to be going smoothly with the sole exception of pin 13. I know pin 13 is tied to the LED and often written to for use as an indicator, so I suspect one of the libraries I'm using may be doing this and causing the interference I'm experiencing.

My code is almost identical to the code in the MultiKey example. The only difference is that I increased the key matrix to 8x16 to accommodate all of my keys. When I press just about any key on the keyboard I receive a pressed, released, and idle state. However, if the key is on pin 13 (column) I receive each of those states for every key on the corresponding row as well as one seemingly random key (not always the same key).

I tried increasing the setDebounceTime() to 250 which made the keyboard unresponsive to the point where it's hard to use, but even still just tapping any key on pin 13 results in 10-11 key presses.

I've included below my complete code, the key matrix, and an annotated version of the printout to demonstrate the behavior I'm experiencing. Any help/suggestions are greatly appreciated.

#include <Keypad.h>
#define KEY_FN MODIFIERKEY_RIGHT_GUI

const byte ROWS = 8;
const byte COLS = 16;
char keys[ROWS][COLS] = {
  { KEY_DELETE,    KEY_EQUAL,      KEY_F12,    0,             MODIFIERKEY_RIGHT_ALT, 0,        0,                    0,               KEY_N, 0,      KEY_B, KEY_F1, KEY_CAPS_LOCK, KEY_F8, 0,                      0                       },
  { KEY_PAGE_UP,   KEY_MINUS,      KEY_F9,     KEY_BACKSLASH, 0,                     KEY_MENU, 0,                    0,               KEY_6, KEY_FN, KEY_5, KEY_F2, KEY_TILDE,     KEY_F5, 0,                      0                       },
  { KEY_HOME,      KEY_LEFT_BRACE, KEY_F10,    0,             0,                     0,        0,                    KEY_RIGHT_BRACE, KEY_Y, 0,      KEY_T, KEY_F3, KEY_TAB,       KEY_F6, MODIFIERKEY_LEFT_CTRL,  0                       },
  { KEY_END,       KEY_SLASH,      KEY_PERIOD, KEY_SPACE,     0,                     0,        0,                    KEY_COMMA,       KEY_M, 0,      KEY_V, KEY_C,  KEY_Z,         KEY_X,  0,                      MODIFIERKEY_LEFT_SHIFT  },
  { KEY_PAGE_DOWN, KEY_SEMICOLON,  KEY_L,      KEY_ENTER,     0,                     0,        0,                    KEY_K,           KEY_J, 0,      KEY_F, KEY_D,  KEY_A,         KEY_S,  MODIFIERKEY_RIGHT_CTRL, 0                       },
  { KEY_RIGHT,     KEY_0,          KEY_9,      KEY_DOWN,      MODIFIERKEY_LEFT_ALT,  0,        0,                    KEY_8,           KEY_7, 0,      KEY_4, KEY_3,  KEY_1,         KEY_2,  0,                      0                       },
  { KEY_LEFT,      KEY_P,          KEY_O,      KEY_UP,        0,                     0,        0,                    KEY_I,           KEY_U, 0,      KEY_R, KEY_E,  KEY_Q,         KEY_W,  0,                      MODIFIERKEY_RIGHT_SHIFT },
  { KEY_INSERT,    KEY_QUOTE,      KEY_F11,    KEY_BACKSPACE, 0,                     0,        MODIFIERKEY_LEFT_GUI, 0,               KEY_H, 0,      KEY_G, KEY_F4, KEY_ESC,       KEY_F7, 0,                      0                       }
};
byte rowPins[ROWS] = {12, 15, 16, 18, 19, 21, 22, 23};
byte colPins[COLS] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 17, 20};

Keypad kpd = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);

void setup() {
  Serial.begin(9600);
  kpd.setDebounceTime(50);
}

unsigned long loopCount = 0;
unsigned long startTime = millis();
String msg = "";

void loop() {
  loopCount++;
  if ( (millis()-startTime)>1000 ) {
      Serial.println(loopCount);
      startTime = millis();
      loopCount = 0;
  }
  // Fills kpd.key[ ] array with up-to 10 active keys.
  // Returns true if there are ANY active keys.
  if (kpd.getKeys())
  {
    for (int i=0; i<LIST_MAX; i++)   // Scan the whole key list.
    {
      if ( kpd.key[i].stateChanged )   // Only find keys that have changed state.
      {
        switch (kpd.key[i].kstate) {  // Report active key state : IDLE, PRESSED, HOLD, or RELEASED
            case PRESSED:
                msg = " PRESSED.";
                break;
            case HOLD:
                msg = " HOLD.";
                break;
            case RELEASED:
                msg = " RELEASED.";
                break;
            case IDLE:
                msg = " IDLE.";
        }
        Serial.print("Key ");
        Serial.print(kpd.key[i].kchar, DEC);
        Serial.println(msg);
      }
    }
  }
}

[Press J]
Key 13 PRESSED. (KEY_J)
Key 13 RELEASED.
Key 13 IDLE.

[Press K]
Key 14 PRESSED. (KEY_K)
Key 14 RELEASED.
Key 14 IDLE.

[Press L]
Key 15 PRESSED. (KEY_L)
Key 15 RELEASED.
Key 15 IDLE.

[Press Caps Lock]
Key 76 PRESSED. (KEY_DELETE)
Key 46 PRESSED. (KEY_EQUAL)
Key 69 PRESSED. (KEY_F12)
Key 64 PRESSED. (KEY_F7)
Key 17 PRESSED. (KEY_N)
Key 5 PRESSED. (KEY_B)
Key 58 PRESSED. (KEY_F1)
Key 57 PRESSED. (KEY_CAPS_LOCK)
Key 65 PRESSED. (KEY_F8)
Key 0 PRESSED. (unmapped)
Key 0 PRESSED. (unmapped)
Key 76 RELEASED.
Key 46 RELEASED.
Key 69 RELEASED.
Key 64 RELEASED.
Key 17 RELEASED.
Key 5 RELEASED.
Key 58 RELEASED.
Key 57 RELEASED.
Key 65 RELEASED.
Key 0 RELEASED.
Key 76 IDLE.
Key 46 IDLE.
Key 69 IDLE.
Key 64 IDLE.
Key 17 IDLE.
Key 5 IDLE.
Key 58 IDLE.
Key 57 IDLE.
Key 65 IDLE.
Key 0 IDLE.

[Press Tilde]
Key 75 PRESSED. (KEY_PAGE_UP)
Key 45 PRESSED. (KEY_MINUS)
Key 66 PRESSED. (KEY_F9)
Key 49 PRESSED. (KEY_BACKSLASH)
Key 101 PRESSED. (KEY_MENU)
Key 35 PRESSED. (KEY_6)
Key 128 PRESSED. (MODIFIERKEY_RIGHT_GUI)
Key 34 PRESSED. (KEY_5)
Key 59 PRESSED. (KEY_F2)
Key 53 PRESSED. (KEY_TILDE)
Key 75 RELEASED.
Key 45 RELEASED.
Key 66 RELEASED.
Key 49 RELEASED.
Key 101 RELEASED.
Key 35 RELEASED.
Key 128 RELEASED.
Key 34 RELEASED.
Key 59 RELEASED.
Key 53 RELEASED.
Key 75 IDLE.
Key 45 IDLE.
Key 66 IDLE.
Key 49 IDLE.
Key 101 IDLE.
Key 35 IDLE.
Key 128 IDLE.
Key 34 IDLE.
Key 59 IDLE.
Key 53 IDLE.

[Press Tab]
Key 74 PRESSED. (KEY_HOME)
Key 47 PRESSED. (KEY_LEFT_BRACE)
Key 67 PRESSED. (KEY_F10)
Key 48 PRESSED. (KEY_RIGHT_BRACE)
Key 28 PRESSED. (KEY_Y)
Key 23 PRESSED. (KEY_T)
Key 60 PRESSED. (KEY_F3)
Key 43 PRESSED. (KEY_TAB)
Key 63 PRESSED. (KEY_F6)
Key 1 PRESSED. (MODIFIERKEY_CTRL)
Key 74 RELEASED.
Key 47 RELEASED.
Key 67 RELEASED.
Key 48 RELEASED.
Key 28 RELEASED.
Key 23 RELEASED.
Key 60 RELEASED.
Key 43 RELEASED.
Key 63 RELEASED.
Key 1 RELEASED.
Key 74 IDLE.
Key 47 IDLE.
Key 67 IDLE.
Key 48 IDLE.
Key 28 IDLE.
Key 23 IDLE.
Key 60 IDLE.
Key 43 IDLE.
Key 63 IDLE.
Key 1 IDLE.

[Press Z]
Key 77 PRESSED. (KEY_END)
Key 56 PRESSED. (KEY_SLASH)
Key 55 PRESSED. (KEY_PERIOD)
Key 44 PRESSED. (KEY_SPACE)
Key 54 PRESSED. (KEY_COMMA)
Key 16 PRESSED. (KEY_M)
Key 25 PRESSED. (KEY_V)
Key 6 PRESSED. (KEY_C)
Key 29 PRESSED. (KEY_Z)
Key 27 PRESSED. (KEY_X)
Key 77 RELEASED.
Key 56 RELEASED.
Key 55 RELEASED.
Key 44 RELEASED.
Key 54 RELEASED.
Key 16 RELEASED.
Key 25 RELEASED.
Key 6 RELEASED.
Key 29 RELEASED.
Key 27 RELEASED.
Key 77 IDLE.
Key 56 IDLE.
Key 55 IDLE.
Key 44 IDLE.
Key 54 IDLE.
Key 16 IDLE.
Key 25 IDLE.
Key 6 IDLE.
Key 29 IDLE.
Key 27 IDLE.

[Press A]
Key 78 PRESSED. (KEY_PAGE_DOWN)
Key 51 PRESSED. (KEY_SEMICOLON)
Key 15 PRESSED. (KEY_L)
Key 40 PRESSED. (KEY_ENTER)
Key 14 PRESSED. (KEY_K)
Key 13 PRESSED. (KEY_J)
Key 9 PRESSED. (KEY_F)
Key 7 PRESSED. (KEY_D)
Key 4 PRESSED. (KEY_A)
Key 22 PRESSED. (KEY_S)
Key 78 RELEASED.
Key 22 RELEASED.
Key 78 IDLE.
Key 22 IDLE.
Key 51 RELEASED.
Key 15 RELEASED.
Key 40 RELEASED.
Key 14 RELEASED.
Key 13 RELEASED.
Key 9 RELEASED.
Key 7 RELEASED.
Key 4 RELEASED.
Key 51 IDLE.
Key 15 IDLE.
Key 40 IDLE.
Key 14 IDLE.
Key 13 IDLE.
Key 9 IDLE.
Key 7 IDLE.
Key 4 IDLE.

[Press 1]
Key 79 PRESSED. (KEY_RIGHT)
Key 39 PRESSED. (KEY_0)
Key 38 PRESSED. (KEY_9)
Key 81 PRESSED. (KEY_DOWN)
Key 4 PRESSED. (KEY_A)
Key 37 PRESSED. (KEY_8)
Key 36 PRESSED. (KEY_7)
Key 33 PRESSED. (KEY_4)
Key 32 PRESSED. (KEY_3)
Key 30 PRESSED. (KEY_1)
Key 79 RELEASED.
Key 39 RELEASED.
Key 38 RELEASED.
Key 81 RELEASED.
Key 4 RELEASED.
Key 37 RELEASED.
Key 36 RELEASED.
Key 33 RELEASED.
Key 32 RELEASED.
Key 30 RELEASED.
Key 79 IDLE.
Key 39 IDLE.
Key 38 IDLE.
Key 81 IDLE.
Key 4 IDLE.
Key 37 IDLE.
Key 36 IDLE.
Key 33 IDLE.
Key 32 IDLE.
Key 30 IDLE.

[Press Q]
Key 80 PRESSED. (KEY_LEFT)
Key 19 PRESSED. (KEY_P)
Key 18 PRESSED. (KEY_O)
Key 82 PRESSED. (KEY_UP)
Key 12 PRESSED. (KEY_I)
Key 24 PRESSED. (KEY_U)
Key 21 PRESSED. (KEY_R)
Key 8 PRESSED. (KEY_E)
Key 20 PRESSED. (KEY_Q)
Key 26 PRESSED. (KEY_W)
Key 80 RELEASED.
Key 19 RELEASED.
Key 18 RELEASED.
Key 82 RELEASED.
Key 12 RELEASED.
Key 24 RELEASED.
Key 21 RELEASED.
Key 8 RELEASED.
Key 20 RELEASED.
Key 26 RELEASED.
Key 80 IDLE.
Key 19 IDLE.
Key 18 IDLE.
Key 82 IDLE.
Key 12 IDLE.
Key 24 IDLE.
Key 21 IDLE.
Key 8 IDLE.
Key 20 IDLE.
Key 26 IDLE.

[Press Esc]
Key 73 PRESSED. (KEY_INSERT)
Key 52 PRESSED. (KEY_QUOTE)
Key 68 PRESSED. (KEY_F11)
Key 42 PRESSED. (KEY_BACKSPACE)
Key 8 PRESSED. (KEY_E)
Key 11 PRESSED. (KEY_H)
Key 10 PRESSED. (KEY_G)
Key 61 PRESSED. (KEY_F4)
Key 41 PRESSED. (KEY_ESC)
Key 64 PRESSED. (KEY_F7)
Key 73 RELEASED.
Key 52 RELEASED.
Key 68 RELEASED.
Key 42 RELEASED.
Key 8 RELEASED.
Key 11 RELEASED.
Key 10 RELEASED.
Key 61 RELEASED.
Key 41 RELEASED.
Key 64 RELEASED.
Key 73 IDLE.
Key 52 IDLE.
Key 68 IDLE.
Key 42 IDLE.
Key 8 IDLE.
Key 11 IDLE.
Key 10 IDLE.
Key 61 IDLE.
Key 41 IDLE.
Key 64 IDLE.

A couple additional observations:

  1. When the program is run the LED on pin 13 glows dimly, but lights up every time a key connected to that pin is pressed. This is probably to be expected.
  2. The unexpected behavior also occurs when my only alteration to the MultiKey example is changing the pin numbers to include pin 13.
/* @file MultiKey.ino
|| @version 1.0
|| @author Mark Stanley
|| @contact mstanley@technologist.com
||
|| @description
|| | The latest version, 3.0, of the keypad library supports up to 10
|| | active keys all being pressed at the same time. This sketch is an
|| | example of how you can get multiple key presses from a keypad or
|| | keyboard.
|| #
*/

#include <Keypad.h>

const byte ROWS = 4; //four rows
const byte COLS = 3; //three columns
char keys[ROWS][COLS] = {
  {'1','2','3'},
  {'4','5','6'},
  {'7','8','9'},
  {'*','0','#'}
};
byte rowPins[ROWS] = {10, 11, 13, 14}; //connect to the row pinouts of the kpd
byte colPins[COLS] = {18, 19, 21}; //connect to the column pinouts of the kpd

Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );



void setup() {
  Serial.begin(9600);
  kpd.setDebounceTime(1);
}

unsigned long loopCount = 0;
unsigned long startTime = millis();
String msg = "";



void loop() {

  loopCount++;
  if ( (millis()-startTime)>1000 ) {
      Serial.println(loopCount);
      startTime = millis();
      loopCount = 0;
  }

  // Fills kpd.key[ ] array with up-to 10 active keys.
  // Returns true if there are ANY active keys.
  if (kpd.getKeys())
  {
    for (int i=0; i<LIST_MAX; i++)   // Scan the whole key list.
    {
      if ( kpd.key[i].stateChanged )   // Only find keys that have changed state.
      {
        switch (kpd.key[i].kstate) {  // Report active key state : IDLE, PRESSED, HOLD, or RELEASED
            case PRESSED:
                msg = " PRESSED.";
                break;
            case HOLD:
                msg = " HOLD.";
                break;
            case RELEASED:
                msg = " RELEASED.";
                break;
            case IDLE:
                msg = " IDLE.";
        }
        Serial.print("Key ");
        Serial.print(kpd.key[i].kchar);
        Serial.println(msg);
      }
    }
  }
}  // End loop

I came across this documentation which suggests that the LED's connection to ground interferes with the signal. Are there software workarounds for this or will I have to remove or burn out the LED to fix this pin?

Severing the top right line connecting the LED to pin 13 ended up being the easiest way to fix the problem. Just took a sharp knife and a few minutes of scraping to remove it. Now I'm getting the behavior I expected.