Need help with strange keyboard matrix behavior

Status
Not open for further replies.

kdharbert

Well-known member
I had strange behavior on my first attempt at a keyboard matrix. I'm picking it back up, and things are behaving strangely still.

I'm using the wiring features here:
https://www.baldengineer.com/arduino-keyboard-matrix-tutorial.html

I'm using keypad.h with 4 rows and 9 columns. This to be a one-handed keyboard that uses the pinky for chording to cover all of the keys...so I've built my code out from the multikey example.

In a 'normal' configuration, on the first row the first 5 keys will trigger both that key and the key in the next column. The 6th and 7th column keys work fine. The 8th and 9th on that row are unused. The rest of the rows work fine.

If I add two extra dummy rows and set them to use an empty dummy pin, suddenly all of the keys work correctly...without multi-key presses. With multi-key presses, all the chording works correctly except for two combos that give multiple presses:
A+X = SX
Q+S=WS

I'm left to suspect that there may be timing stuff going on...? It seems that perhaps some resets take place during each scan and the two dummy rows give the system time to settle...?

Anyone seen any behavior like this? Any diagnostics I could try?

First attempt thread:
https://forum.pjrc.com/threads/67795-Keyboard-matrix-behaves-differently-based-on-choice-of-row-pins

Code:

Code:
uint8_t MODIFIER=0;
uint32_t PINKY_MODIFIER=0;
uint32_t key_matrix[10][256];

#include <Keypad.h>

const byte READ_ROWS = 6; 
const byte SCAN_COLS = 9; 

uint8_t keys[READ_ROWS][SCAN_COLS] = {
{199,198,197,196,195,194,193,192,191},
{99,98,97,96,95,94,93,92,91},
{KEY_TAB,KEY_Q,KEY_W,KEY_E,KEY_R,KEY_T,KEY_Y,102,103},
{KEY_CAPS_LOCK,KEY_A,KEY_S,KEY_D,KEY_F,KEY_G,0,KEY_H,104},
{KEY_LEFT_SHIFT,KEY_Z,KEY_X,KEY_C,KEY_V,KEY_B,105,106,KEY_N},
{107,108, KEY_BACKSPACE,KEY_DELETE,KEY_SPACE,109,110,111,112},

};
                       

byte scanPins[SCAN_COLS] = {5,4,3,2,1,0,8,7,6}; 
byte readPins[READ_ROWS] = {9,9,28,29,30,31}; 


Keypad kpd = Keypad( makeKeymap(keys), readPins, scanPins, READ_ROWS, SCAN_COLS );

unsigned long loopCount;
unsigned long startTime;
String msg;


void setup() {
   Serial.begin(9600);
   for(int i = 0;i<10;i++){
    
    key_matrix[i][(uint8_t)KEY_N]=KEY_RIGHT_SHIFT;    
    key_matrix[i][(uint8_t)KEY_H]=KEY_RIGHT_CTRL;     
    key_matrix[i][(uint8_t)KEY_Y]=KEY_RIGHT_ALT;     
    key_matrix[i][(uint8_t)KEY_TAB]=KEY_ESC;     
   }
 
  key_matrix[0][(uint8_t)KEY_W]=KEY_R;
  key_matrix[0][(uint8_t)KEY_E]=KEY_S;
  key_matrix[0][(uint8_t)KEY_R]=KEY_T;
  key_matrix[0][(uint8_t)KEY_T]=KEY_U;
  
  key_matrix[0][(uint8_t)KEY_S]=KEY_A;
  key_matrix[0][(uint8_t)KEY_D]=KEY_E;
  key_matrix[0][(uint8_t)KEY_F]=KEY_I;
  key_matrix[0][(uint8_t)KEY_G]=KEY_O;

  key_matrix[0][(uint8_t)KEY_X]=KEY_L;  
  key_matrix[0][(uint8_t)KEY_C]=KEY_N;                                
  key_matrix[0][(uint8_t)KEY_V]=KEY_D;  
  key_matrix[0][(uint8_t)KEY_B]=KEY_M;

  key_matrix[0][(uint8_t)KEY_BACKSPACE]=KEY_BACKSPACE;  
  key_matrix[0][(uint8_t)KEY_DELETE]=KEY_DELETE;  
  key_matrix[0][(uint8_t)KEY_SPACE]=KEY_SPACE;                                                                                             

  //1111111
  key_matrix[1][(uint8_t)KEY_W]=KEY_P;
  key_matrix[1][(uint8_t)KEY_E]=KEY_Y;
  key_matrix[1][(uint8_t)KEY_R]=KEY_F;
  key_matrix[1][(uint8_t)KEY_T]=KEY_Z;
  
  key_matrix[1][(uint8_t)KEY_S]=KEY_H;
  key_matrix[1][(uint8_t)KEY_D]=KEY_B;
  key_matrix[1][(uint8_t)KEY_F]=KEY_J;
  key_matrix[1][(uint8_t)KEY_G]=KEY_K;

  key_matrix[1][(uint8_t)KEY_X]=KEY_X;  
  key_matrix[1][(uint8_t)KEY_C]=KEY_C;  
  key_matrix[1][(uint8_t)KEY_V]=KEY_V;  
  key_matrix[1][(uint8_t)KEY_B]=KEY_G;  

  key_matrix[1][(uint8_t)KEY_BACKSPACE]=KEY_Q;  
  key_matrix[1][(uint8_t)KEY_DELETE]=KEY_W;  
  key_matrix[1][(uint8_t)KEY_SPACE]=KEY_ENTER;
  
//222222
  key_matrix[2][(uint8_t)KEY_W]=KEY_PERIOD;
  key_matrix[2][(uint8_t)KEY_E]=KEY_COMMA;
  key_matrix[2][(uint8_t)KEY_R]=KEY_SLASH;
  key_matrix[2][(uint8_t)KEY_T]=KEY_QUOTE;
  
  key_matrix[2][(uint8_t)KEY_S]=KEY_LEFT_BRACE;
  key_matrix[2][(uint8_t)KEY_D]=KEY_RIGHT_BRACE;
  key_matrix[2][(uint8_t)KEY_F]=KEY_SEMICOLON;
  key_matrix[2][(uint8_t)KEY_G]=KEY_MINUS;

  key_matrix[2][(uint8_t)KEY_X]=KEY_EQUAL;  
  key_matrix[2][(uint8_t)KEY_C]=KEY_TILDE;  
  key_matrix[2][(uint8_t)KEY_V]=KEY_ESC;  
       
//33333
  key_matrix[3][(uint8_t)KEY_W]=KEY_0;
  key_matrix[3][(uint8_t)KEY_E]=KEY_1;
  key_matrix[3][(uint8_t)KEY_R]=KEY_2;
  key_matrix[3][(uint8_t)KEY_T]=KEY_3;
  
  key_matrix[3][(uint8_t)KEY_S]=KEY_4;
  key_matrix[3][(uint8_t)KEY_D]=KEY_5;
  key_matrix[3][(uint8_t)KEY_F]=KEY_6;
  key_matrix[3][(uint8_t)KEY_G]=KEY_7;

  key_matrix[3][(uint8_t)KEY_X]=KEY_8;  
  key_matrix[3][(uint8_t)KEY_C]=KEY_9;  
  
  key_matrix[3][(uint8_t)KEY_BACKSPACE]=KEY_PRINTSCREEN;  
  key_matrix[3][(uint8_t)KEY_DELETE]=KEY_SCROLL_LOCK;  
 
  key_matrix[4][(uint8_t)KEY_S]=KEY_HOME;
  key_matrix[4][(uint8_t)KEY_D]=KEY_UP;
  key_matrix[4][(uint8_t)KEY_F]=KEY_END;
  key_matrix[4][(uint8_t)KEY_G]=KEY_PAGE_UP;

  key_matrix[4][(uint8_t)KEY_X]=KEY_LEFT;  
  key_matrix[4][(uint8_t)KEY_C]=KEY_DOWN;  
  key_matrix[4][(uint8_t)KEY_V]=KEY_RIGHT;  
  key_matrix[4][(uint8_t)KEY_B]=KEY_PAGE_DOWN;  

}

void loop() {
    loopCount++;
    if ( (millis()-startTime)>5000 ) {
        Serial.print("Average loops per second = ");
        Serial.println(loopCount/5);
        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.";
                      
                      if(kpd.key[i].kchar==KEY_RIGHT_CTRL){MODIFIER |= MODIFIERKEY_CTRL;Keyboard.set_modifier(MODIFIER);return;}
                      if(kpd.key[i].kchar==KEY_RIGHT_SHIFT){MODIFIER |= MODIFIERKEY_ALT;Keyboard.set_modifier(MODIFIER);return;}
                      if(kpd.key[i].kchar==KEY_RIGHT_ALT){MODIFIER |= MODIFIERKEY_SHIFT;Keyboard.set_modifier(MODIFIER);return;}
                                       
                     //find the pinky modifiers
                     if(kpd.key[i].kchar==(uint8_t)KEY_A){PINKY_MODIFIER=1;return;}
                     if(kpd.key[i].kchar==(uint8_t)KEY_CAPS_LOCK){PINKY_MODIFIER=2;return;}
                     if(kpd.key[i].kchar==(uint8_t)KEY_Q){PINKY_MODIFIER=3;return;}
                     if(kpd.key[i].kchar==(uint8_t)KEY_Z){PINKY_MODIFIER=4;return;}
                                                             
                     Serial.println(PINKY_MODIFIER);                     
                     Serial.println(MODIFIER);                     
                     Keyboard.press(key_matrix[PINKY_MODIFIER][uint8_t(kpd.key[i].kchar)]);
                                       
                break;
                    case HOLD:
                    msg = " HOLD.";
                break;
                    case RELEASED:
                    msg = " RELEASED.";
                      
                      if(kpd.key[i].kchar==(uint8_t)KEY_RIGHT_CTRL){MODIFIER &= ~MODIFIERKEY_CTRL;Keyboard.set_modifier(MODIFIER);return;}
                      if(kpd.key[i].kchar==(uint8_t)KEY_RIGHT_SHIFT){MODIFIER &= ~MODIFIERKEY_ALT;Keyboard.set_modifier(MODIFIER);return;}
                      if(kpd.key[i].kchar==(uint8_t)KEY_RIGHT_ALT){MODIFIER &= ~MODIFIERKEY_SHIFT;Keyboard.set_modifier(MODIFIER);return;}
                                            
                      //find the pinky modifiers99
                      if(kpd.key[i].kchar==(uint8_t)KEY_A){PINKY_MODIFIER=0;return;}
                      if(kpd.key[i].kchar==(uint8_t)KEY_CAPS_LOCK){PINKY_MODIFIER=0;return;}
                      if(kpd.key[i].kchar==(uint8_t)KEY_Q){PINKY_MODIFIER=0;return;}
                      if(kpd.key[i].kchar==(uint8_t)KEY_Z){PINKY_MODIFIER=0;return;}

                      //release all keys regardless of modifier
                      for(int j=0;j<8;j++){
                        Keyboard.release(key_matrix[j][uint8_t(kpd.key[i].kchar)]);
                      }
                break;
                    case IDLE:
                    msg = " IDLE.";
                }
                Serial.print("Key ");
                Serial.print(uint8_t(kpd.key[i].kchar));
                Serial.println(msg);


                
            }
        }
    }
}
 
This turned out to be a really messed up Teensy 4.1 unit. I switch to a spare 3.2 and everything worked fine.
 
Status
Not open for further replies.
Back
Top