Loading...
Pages: [1] 2 3 4   Go Down
Author Topic: using Keypad library for a full QWERTY keyboard  (Read 2411 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi all. I'm working on a project that includes wiring an old Apple IIc keyboard to a teensy board to act as a USB keyboard.

Simplifying the multiplexing of keys, i've been using the keypad library from the playground (http://arduino.cc/playground/Code/Keypad). After some fiddling with the keyboard itself and working around some dead pins, I have it working, mostly. It's a big matrix - 14 columns by 10 rows, which uses up almost all of the inputs on the teensy.

My sketch works in detecting one key at a time, so I can type with it, but it's not very useful without modifier keys. I'm not sure if I'm running into a limitation of the keypad library (detecting multiple keys at a time isn't necessarily required on a 3x4 keypad) or if my implementation is lacking.

So... is it possible to detect multiple, simultaneous keypresses in the keypad library? If so, can someone point me to an example sketch I can look at for guidance? If not, is there a better way to attempt what i'm doing - a matrix keyboard library I haven't found?

Logged

Phillipsburg, NJ
Offline Offline
Full Member
***
Karma: 6
Posts: 124
Author: Matrix Keypad Library
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
My sketch works in detecting one key at a time, so I can type with it, but it's not very useful without modifier keys. I'm not sure if I'm running into a limitation of the keypad library or if my implementation is lacking.

I can tell you with certainty that it's definitely the library.  I was one of the people who wrote it. smiley-wink  In fact I made absolutely sure that it would only return one key press at a time.  Give me a little time (no later than this weekend) to think about it and I'll see what I can do with the library.

Can you tell me what kind of modifiers you'd like to have/use?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

modifiers? the usual - shift, control, apple key...

this is an old-school apple II keyboard i'm working on. it still has the apples on it - not the command squiggly. and no alt/option, though that would probably be necessary with a more modern counterpart. the apple keys should map to MODIFIER_GUI, right?

my thought while driving home tonight was that i could do it with two keypad objects, the second one only managing the pins for the modifier keys. luckily, they're separated from the alpha/num keys on the keyboard itself.

any thoughts?

Logged

Phillipsburg, NJ
Offline Offline
Full Member
***
Karma: 6
Posts: 124
Author: Matrix Keypad Library
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
[thought] i could do it with two keypad objects, the second one only managing the pins for the modifier keys. luckily, they're separated from the alpha/num keys on the keyboard itself.

I was thinking the same thing but I haven't been able to test it.  I'm not sure just how well a micro can support separate C++ objects in memory.  Even if it works there would still be the problem that you could only use one modifier at a time. Control+Shift+<Key> wouldn't be available.  Still it would be interesting to see what happens. Are you willing to try?

Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

i'll give it a shot. i'm more interested in being able to type in mixed case and use symbols than anything else - this is a hack, not going to be my daily driver smiley



Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

using the second keypad object doesn't seem to work. i'm not sure what's happening, though, since even when i explicitly set a modifier key, it has no effect.

here's my complete sketch (you can see the IIc matrix map commented at the top:

Code:
#include <Keypad.h>


/*

31 24 22 8 14 10 6 1 4 2 26 16 34 28

12 ESC 1 2 3 4 5 6 7 8 9

3 \ = 0 -

33 TAB Q W E R T Y U I O

5 ` P [ ]

18 A D S H F J G K ; L

20 Z X C V B M N , . /

23 CMD CMD

21 CTL SHFT CAPS

9 DEL DN LA RA

7 RTN UP SPC '



14 columns
10 rows

24 input pins


*/


const byte ROWS = 8; // rows
const byte COLS = 10; // columns
char keys[ROWS][COLS] = {

{ KEY_ESC, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9}  ,

{ 0, 0, 0, 0, 0, KEY_BACKSLASH, 0, KEY_EQUAL, KEY_0, KEY_MINUS} ,

{ KEY_TAB, KEY_Q, KEY_W, KEY_E, KEY_R, KEY_T, KEY_Y, KEY_U, KEY_I, KEY_O},

{ 0, 0, 0, 0, 0, KEY_TILDE, 0, KEY_P, KEY_LEFT_BRACE, KEY_RIGHT_BRACE},

{ KEY_A, KEY_D, KEY_S, KEY_H, KEY_F, KEY_J, KEY_G, KEY_K, KEY_SEMICOLON, KEY_L},

{ KEY_Z ,KEY_X, KEY_C, KEY_V ,KEY_B, KEY_M, KEY_N, KEY_COMMA, KEY_PERIOD, KEY_SLASH},

{ 0 , 0 ,0 ,0, 0, KEY_BACKSPACE, 0 ,KEY_DOWN, KEY_LEFT, KEY_RIGHT},

{ 0, 0, 0, 0, 0 ,KEY_ENTER, 0 ,KEY_UP, KEY_SPACE ,KEY_QUOTE}

};


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

byte colPins[COLS] = {
  10,11,12,13,14,15,16,17,18,19}; //connect to the column pinouts of the keypad

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




const byte ROWS2 = 2; // rows
const byte COLS2 = 4; // columns
char keys2[ROWS2][COLS2] = {
{ 0 , 0 ,MODIFIERKEY_SHIFT ,KEY_CAPS_LOCK },
{MODIFIERKEY_GUI, MODIFIERKEY_GUI,  0 ,0 }
};
byte rowPins2[ROWS2] = {
  7,8}; //connect to the row pinouts of the keypad 

byte colPins2[COLS2] = {
  20,21,22,23}; //connect to the column pinouts of the keypad

Keypad keypad2 = Keypad( makeKeymap(keys2), rowPins2, colPins2, ROWS2, COLS2 );




void setup(){
}

void loop(){
  char key = keypad.getKey(); 
  char key2 = keypad2.getKey();

  if (key){
    Keyboard.set_key1(key);
  } else {
    Keyboard.set_key1(0);
  }

   
  if (key2){
    Keyboard.set_key2(key2);
  } else {
    Keyboard.set_key2(0);
  }

 // Keyboard.set_key3(MODIFIERKEY_SHIFT);

  Keyboard.send_now();

}

Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

i should probably mention that i'm using the Teensy with Teensyduino and sending the keys via the keyboard library - see here:

http://www.pjrc.com/teensy/td_keyboard.html

Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

oops... forgot the syntax for adding a modifier key. my loop is now thus:

Code:
void loop(){
  char key = keypad.getKey(); 
  char key2 = keypad2.getKey();

   
  if (key2){
    Keyboard.set_modifier(key2);
  }

  if (key){
    Keyboard.set_key1(key);
  }

  Keyboard.send_now();
  Keyboard.set_modifier(0);
  Keyboard.set_key1(0);   
   
}
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

okay. i think i have an idea of what's going on.

initially, i thought the modifier keypad (keypad2) wasn't working, but it turns out that it was, only very intermittently.

so i swapped my order of the getKey() lines - now keypad2 is getting updated first. suddenly, my modifiers are working!

but the other keys are all only working intermittently... so i think it's a speed problem. the teensy's not able to update both matrices in one pass of the loop. maybe a delay?

Logged

Phillipsburg, NJ
Offline Offline
Full Member
***
Karma: 6
Posts: 124
Author: Matrix Keypad Library
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
using the second keypad object doesn't seem to work. i'm not sure what's happening, though, since even when i explicitly set a modifier key, it has no effect.

Thanks for the link to the teensy keyboard code.  It was a big help and I can tell you that you are not using the functions to correctly send modifier keys. (Sorry if I sound a bit blunt but I'm racing to post this from work.)

I can go into it more when I get home tonight but just a quick example:

I see that you commented it out but you used
Code:
Keyboard.set_key3(MODIFIERKEY_SHIFT);
to send a modifier key when you should have used
Code:
Keyboard.set_modifier(MODIFIERKEY_SHIFT);

From the teensy link you also need to do:
Quote
Keyboard.send_now()
After you have set the normal and modifier keys, use Keyboard.send_now() to communicate that combination to the PC or Mac.
Logged

Phillipsburg, NJ
Offline Offline
Full Member
***
Karma: 6
Posts: 124
Author: Matrix Keypad Library
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
so i swapped my order of the getKey() lines - now keypad2 is getting updated first. suddenly, my modifiers are working!

but the other keys are all only working intermittently... so i think it's a speed problem. the teensy's not able to update both matrices in one pass of the loop. maybe a delay?

No, the keypad was built to work better without any delay()s in your code.  I think there might be some interference between the keypad objects keypad and keypad2.  I'll take a look and see if I can identify what it might be.
Logged

Central MN, USA
Offline Offline
Faraday Member
**
Karma: 35
Posts: 5941
Phi_prompt, phi_interfaces, phi-2 shields, phi-panels
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

What is the keyboard object? Browsed through your code and didn't find a definition. Is it in keypad.h? Just trying to understand your code to see if I can offer any help.

BTW, do you know if the debounce time in the keypad library is static variable or not?
Logged


Phillipsburg, NJ
Offline Offline
Full Member
***
Karma: 6
Posts: 124
Author: Matrix Keypad Library
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
What is the keyboard object? Browsed through your code and didn't find a definition. Is it in keypad.h? Just trying to understand your code to see if I can offer any help.

Edit:  I should have paid closer attention to your question.  Sorry about the mis-answer.
Yeah, sorry about that, I was using C++ jargon to describe when the 'object' was created in the users code.  For example the keypad2 object is created when he called:
Code:
Keypad keypad2 = Keypad( makeKeymap(keys2), rowPins2, colPins2, ROWS2, COLS2 );


Quote
BTW, do you know if the debounce time in the keypad library is static variable or not?

Debounce time is variable and can be set by the user, for example:
Code:
void setup() {
    Serial.begin(9600);
    keypad.addEventListener(keypadEvent);
    keypad.setDebounceTime(500);
}
Although, I doubt you'll ever need a debounce time as high as 500 milliseconds. smiley-wink
« Last Edit: January 11, 2012, 12:44:29 pm by mstanley » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

What is the keyboard object? Browsed through your code and didn't find a definition. Is it in keypad.h? Just trying to understand your code to see if I can offer any help.

the keyboard object comes from the teensyduino libraries. sorry, i didn't make that clear in the OP.

see:
http://www.pjrc.com/teensy/td_keyboard.html
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

my current and semi-working sketch:

Code:
const byte ROWS = 8; // rows
const byte COLS = 10; // columns
char keys[ROWS][COLS] = {

{ KEY_ESC, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9}  ,

{ 0, 0, 0, 0, 0, KEY_BACKSLASH, 0, KEY_EQUAL, KEY_0, KEY_MINUS} ,

{ KEY_TAB, KEY_Q, KEY_W, KEY_E, KEY_R, KEY_T, KEY_Y, KEY_U, KEY_I, KEY_O},

{ 0, 0, 0, 0, 0, KEY_TILDE, 0, KEY_P, KEY_LEFT_BRACE, KEY_RIGHT_BRACE},

{ KEY_A, KEY_D, KEY_S, KEY_H, KEY_F, KEY_J, KEY_G, KEY_K, KEY_SEMICOLON, KEY_L},

{ KEY_Z ,KEY_X, KEY_C, KEY_V ,KEY_B, KEY_M, KEY_N, KEY_COMMA, KEY_PERIOD, KEY_SLASH},

{ 0 , 0 ,0 ,0, 0, KEY_BACKSPACE, 0 ,KEY_DOWN, KEY_LEFT, KEY_RIGHT},

{ 0, 0, 0, 0, 0 ,KEY_ENTER, 0 ,KEY_UP, KEY_SPACE ,KEY_QUOTE}

};


byte rowPins[ROWS] = {
  0 ,1,2,3,4,5,8,9}; //connect to the row pinouts of the keypad 

byte colPins[COLS] = {
  10,11,12,13,14,15,16,17,18,19}; //connect to the column pinouts of the keypad

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




const byte ROWS2 = 1; // rows
const byte COLS2 = 4; // columns
char keys2[ROWS2][COLS2] = {
{MODIFIERKEY_SHIFT, MODIFIERKEY_SHIFT, 0 ,0 }
//{ 0 , 0 ,MODIFIERKEY_SHIFT, MODIFIERKEY_SHIFT }
};
byte rowPins2[ROWS2] = {
  6}; //connect to the row pinouts of the keypad 

byte colPins2[COLS2] = {
  20,21,22,23}; //connect to the column pinouts of the keypad

Keypad keypad2 = Keypad( makeKeymap(keys2), rowPins2, colPins2, ROWS2, COLS2 );




void setup(){

}

void loop(){
 
 
 
  char key = keypad.getKey(); 
  char key2 = keypad2.getKey();


  KeyState modifier = keypad2.getState(); 

   
  if (key2){
    Keyboard.set_modifier(key2);
  }


  KeyState alpha = keypad.getState();
  if (key){
    Keyboard.set_key1(key);
  }

  Keyboard.send_now();
 
  if(modifier == RELEASED) {
    Keyboard.set_modifier(0);
  }
  if(alpha == RELEASED) {
    Keyboard.set_key1(0);   
  }


}


notice two getKey() lines. the first "alpha" keypad is responsive, and the second "modifier" works only occasionally. if i swap those lines, the opposite is true, which leads me to think that i'm asking too much of the teensy in each pass of the matrix scan.

would it be more likely to work if i used waitForKey() instead, and only read the modifier keypad if there's an alpha key pressed to modify?
Logged

Pages: [1] 2 3 4   Go Up
Print
 
Jump to: