Hi guys,
I am designing a USB keyboard for my flight sim with x4 columns and x7 rows and x24 buttons in total.
Arduino Pro Micro is used as the main controller device.
All x4 columns are tied to VCC via 10k resistors. Each key has a diode placed in COL to ROW direction. The circuit diagram is shown on the screengrab below:
Cols and rows are connected to the Arduino as per following table:
| COL1 | COL2 | COL3 | COL4 | ||
|---|---|---|---|---|---|
| D4 | D5 | D6 | D7 | ||
| ROW1 | A3 | ECS | 1 | 2, A, B, C | 3, D, E, F |
| ROW2 | A2 | # | 4, G, H, I | 5, J, K, L | 6, M, N, O |
| ROW3 | A1 | * | 7, P, Q, R, S | 8, T, U, V | 9, W, X, Y, Z |
| ROW4 | A0 | / | - | 0 | + |
| ROW5 | D8 | ENTER | CLEAR | . | SPACE |
| ROW6 | D9 | ARR. UP | |||
| ROW7 | D10 | ARR. LEFT | ARR. DOWN | ARR. RIGHT |
Overall keypad layout looks as follows:
Using nice library and examples created and prepared by Nick Gammon ( Gammon Forum : Electronics : Microprocessors : Using a keypad matrix ) and default keyboard.h library I have managed to make it working as a normal USB keyboard no problem.
Here is the code for a reference (works flawlessly):
#include <Keypad_Matrix.h>
#include "Keyboard.h"
const byte ROWS = 7;
const byte COLS = 4;
// Map the buttons to an array for the Keymap instance
const char keys[ROWS][COLS] =
// 4x7 matrix
{
{'E', '1', '2', '3'},
{'#', '4', '5', '6'},
{'*', '7', '8', '9'},
{'/', '-', '0', '+'},
{'R', 'C', '.', 'S'},
{'x', 'x', 'u', 'x'},
{'x', 'l', 'd', 'r'}
};
const byte rowPins[ROWS] = {A3, A2, A1, A0, 8, 9, 10}; //connect to the row pinouts of the keypad
const byte colPins[COLS] = {4, 5, 6, 7}; //connect to the column pinouts of the keypad
// Initialise the Keypad
Keypad_Matrix kpd = Keypad_Matrix( makeKeymap (keys), rowPins, colPins, ROWS, COLS );
void keyDown (const char which)
{
//Serial.print (F("Key down: "));
//Serial.println (which);
switch (which)
{
// -------------- ROW 1 -------------------
case 'E':
{
Serial.println ("ESC BUTTON IS PRESSED");
Keyboard.press(KEY_ESC);
delay(100);
Keyboard.releaseAll();
}
break;
case '1':
{
Serial.println ("1 BUTTON IS PRESSED");
Keyboard.write('1');
delay(100);
Keyboard.releaseAll();
}
break;
case '2':
{
Serial.println ("2 BUTTON IS PRESSED");
Keyboard.write('2');
delay(100);
Keyboard.releaseAll();
}
break;
case '3':
{
Serial.println ("3 BUTTON IS PRESSED");
Keyboard.write('3');
delay(100);
Keyboard.releaseAll();
}
break;
// -------------- ROW 2 -------------------
case '#':
{
Serial.println ("# BUTTON IS PRESSED");
Keyboard.write('#');
delay(100);
Keyboard.releaseAll();
}
break;
case '4':
{
Serial.println ("4 BUTTON IS PRESSED");
Keyboard.write('4');
delay(100);
Keyboard.releaseAll();
}
break;
case '5':
{
Serial.println ("5 BUTTON IS PRESSED");
Keyboard.write('5');
delay(100);
Keyboard.releaseAll();
}
break;
case '6':
{
Serial.println ("6 BUTTON IS PRESSED");
Keyboard.write('6');
delay(100);
Keyboard.releaseAll();
}
break;
// -------------- ROW 3 -------------------
case '*':
{
Serial.println ("* BUTTON IS PRESSED");
Keyboard.write('*');
delay(100);
Keyboard.releaseAll();
}
break;
case '7':
{
Serial.println ("7 BUTTON IS PRESSED");
Keyboard.write('7');
delay(100);
Keyboard.releaseAll();
}
break;
case '8':
{
Serial.println ("8 BUTTON IS PRESSED");
Keyboard.write('8');
delay(100);
Keyboard.releaseAll();
}
break;
case '9':
{
Serial.println ("9 BUTTON IS PRESSED");
Keyboard.write('9');
delay(100);
Keyboard.releaseAll();
}
break;
// -------------- ROW 4 -------------------
case '/':
{
Serial.println ("/ BUTTON IS PRESSED");
Keyboard.write('/');
delay(100);
Keyboard.releaseAll();
}
break;
case '-':
{
Serial.println ("- BUTTON IS PRESSED");
Keyboard.write('-');
delay(100);
Keyboard.releaseAll();
}
break;
case '0':
{
Serial.println ("0 BUTTON IS PRESSED");
Keyboard.write('0');
delay(100);
Keyboard.releaseAll();
}
break;
case '+':
{
Serial.println ("+ BUTTON IS PRESSED");
Keyboard.write('+');
delay(100);
Keyboard.releaseAll();
}
break;
// -------------- ROW 5 -------------------
case 'R':
{
Serial.println ("ENTER BUTTON IS PRESSED");
Keyboard.press(KEY_RETURN);
delay(100);
Keyboard.releaseAll();
}
break;
case 'C':
{
Serial.println ("CLEAR BUTTON IS PRESSED");
Keyboard.press(KEY_BACKSPACE);
delay(100);
Keyboard.releaseAll();
}
break;
case '.':
{
Serial.println (". BUTTON IS PRESSED");
Keyboard.write('.');
delay(100);
Keyboard.releaseAll();
}
break;
case 'S':
{
Serial.println ("SPACE BUTTON IS PRESSED");
Keyboard.write(' ');
delay(100);
Keyboard.releaseAll();
}
break;
// -------------- ROW 6 -------------------
case 'u':
{
Serial.println ("ARROW UP BUTTON IS PRESSED");
Keyboard.press(KEY_UP_ARROW);
delay(100);
Keyboard.releaseAll();
}
break;
// -------------- ROW 7 -------------------
case 'l':
{
Serial.println ("ARROW LEFT BUTTON IS PRESSED");
Keyboard.press(KEY_LEFT_ARROW);
delay(100);
Keyboard.releaseAll();
}
break;
case 'd':
{
Serial.println ("ARROW DOWN BUTTON IS PRESSED");
Keyboard.press(KEY_DOWN_ARROW);
delay(100);
Keyboard.releaseAll();
}
break;
case 'r':
{
Serial.println ("ARROW RIGHT BUTTON IS PRESSED");
Keyboard.press(KEY_RIGHT_ARROW);
delay(100);
Keyboard.releaseAll();
}
break;
}
}
void setup()
{
Serial.begin(9600); // Initialise the serial monitor
Serial.println ("Starting.");
// initialize control over the keyboard:
Keyboard.begin();
kpd.begin ();
kpd.setKeyDownHandler (keyDown);
}
void loop()
{
kpd.scan ();
// do other stuff here
}
The only one thing is left to implement is Multi Tap keys ( 2 thru 9) to be able to type letters..
I have tried a library created by ZulNs ( GitHub - ZulNs/MultitapKeypad: Arduino Library which allows to interface with matrix 4 x 3 phone's keypad as well as 4 x 4. ) but had no luck even when I kept just 4 col x 4 rows arrangement for testing...
I assume the main culprit is that I use COLs pulled high, and he used Rows pulled high (inverted logic) ?
Is there a way to manipulate the library to change switching logic? Or is there another multytap library I have missed?
Appreciate any help and thanks in advance.
Regards,
Phil.


