Arduino Buttons Matrix
This is a simple example to use 6 or 15 momentary push buttons on Arduino Leonardo or Pro Micro.
The final goal is to build a simple button box for Star Citizen, here is my referal code: STAR-DR6Q-GLS9
So far the plan is to provide 15 buttons & switches (Didn’t test the switches yet). Inspiration : https://www.reddit.com/r/starcitizen/comments/i3ps2y/custom_control_board_design_button_box/
The Setup
Wiring Guide
For a step-by-step guide on wiring, refer to this YouTube tutorial: link.
The Code
I didn’t code that myself, I started from this post : https://forum.arduino.cc/t/need-help-with-sketch-for-button-box/887220/11
Dependencies
- Download and import this library: https://github.com/MHeironimus/ArduinoJoystickLibrary
- Install
keypad
library by Mark Stanley, Alexander Brevig (Version 3.1.1) - Install
keyboard
library (in case you want to use the keyboard approach.)
Option Gamepad
If you want to have the arduino as a gamepad, do as follow,
In my case I wasn’t able to make it properly work with Star Citizen, I have the dual Thrustmaster T.16000M and the binding was mixed up. But using
Joytokey
, you should be able to map each button to a keyboard shortcut or use it as is.
Arduino C (6 Buttons simplified)
you can uncomment the #define DEBUG
to see the events on your serial console, but it won’t work on Windows (in the game controllers window), so before going to production, uncomment or remove that line.
#include <Joystick.h>
#include <Keypad.h>
// #define DEBUG
const byte ROWS = 3; // define how many rows
const byte COLS = 2; // define how many cols
char Keys[ROWS][COLS] = { // describe the matrix
{'1','2'},
{'3','4'},
{'5','6'},
};
byte rowPins[ROWS] = {9, 10, 12}; // Arduino Pins for each rows
byte colPins[COLS] = {A1, A2}; // Arduino Pins for each cols
char customKey = 0;
Keypad customKeypad = Keypad( makeKeymap(Keys), rowPins, colPins, ROWS, COLS);
// See the documentation for details (https://github.com/MHeironimus/ArduinoJoystickLibrary)
// 0x03 = Indicates the joystick's HID report ID.
// 0x05 = Gamepad
// 6 = Quantity of buttons
// 0 = quantity of hat switches
// All false are because there is no joystick (no axis)
Joystick_ Buttons(0x03, 0x05, 6, 0,false,false,false,false,false,false,false,false,false,false,false);
// Handle buttons events
void CheckAllButtons(void)
{
if (customKeypad.getKeys())
{
for (int i = 0; i < LIST_MAX; i++)
{
if ( customKeypad.key[i].stateChanged )
{
switch (customKeypad.key[i].kstate)
{
case PRESSED:
#ifdef DEBUG
Serial.println("PRESSED");
#endif
Buttons.setButton(customKeypad.key[i].kcode, 1);
break;
case RELEASED:
#ifdef DEBUG
Serial.println("RELEASED");
#endif
Buttons.setButton(customKeypad.key[i].kcode, 0);
break;
case IDLE:
case HOLD:
#ifdef DEBUG
Serial.println("HOLD");
#endif
break;
default:
break;
}
}
}
}
}
void setup(){
#ifdef DEBUG
Serial.begin(9600);
#endif
Buttons.begin();
}
void loop(){
CheckAllButtons();
}
Arduino C (15 Buttons)
The final prototype.
#include <Joystick.h>
#include <Keypad.h>
// #define DEBUG
const byte ROWS = 5;
const byte COLS = 3;
char Keys[ROWS][COLS] = {
{'1','2', '3'},
{'4','5', '6'},
{'7','8', '9'},
{'A','B', 'C'},
{'D','E', 'F'},
};
byte rowPins[ROWS] = {3, 4, 5, 6, 7};
byte colPins[COLS] = {A1, A2, A3};
char customKey = 0;
Keypad customKeypad = Keypad( makeKeymap(Keys), rowPins, colPins, ROWS, COLS);
Joystick_ Buttons(0x03,0x05,15, 0,false,false,false,false,false,false,false,false,false,false,false);
void CheckAllButtons(void)
{
if (customKeypad.getKeys())
{
for (int i = 0; i < LIST_MAX; i++)
{
if ( customKeypad.key[i].stateChanged )
{
switch (customKeypad.key[i].kstate)
{
case PRESSED:
#ifdef DEBUG
Serial.println("PRESSED");
#endif
Buttons.setButton(customKeypad.key[i].kcode, 1);
break;
case RELEASED:
#ifdef DEBUG
Serial.println("RELEASED");
#endif
Buttons.setButton(customKeypad.key[i].kcode, 0);
break;
case IDLE:
case HOLD:
#ifdef DEBUG
Serial.println("HOLD");
#endif
break;
default:
break;
}
}
}
}
}
void setup(){
#ifdef DEBUG
Serial.begin(9600);
#endif
Buttons.begin();
}
void loop(){
CheckAllButtons();
}
Option Keyboard
This option works seamlessly with Star citizen, the arduino will be seen as a keyboard, so nothing fancy.
The downside is that you need to flash the chip everytime you want to change the key binding.
Arduino C (15 buttons)
#include <Keypad.h>
#include <Keyboard.h>
const byte ROWS = 5;
const byte COLS = 3;
char Keys[ROWS][COLS] = {
{ '1', '2', '3' },
{ '4', '5', '6' },
{ '7', '8', '9' },
{ 'A', 'B', 'C' },
{ 'D', 'E', 'F' },
};
byte rowPins[ROWS] = { 3, 4, 5, 6, 7 };
byte colPins[COLS] = { A1, A2, A3 };
char customKey = 0;
void pressIt(char key) {
switch (key) {
case '1':
Keyboard.press(KEY_RIGHT_ALT);
Keyboard.press('r');
break;
case '2':
Keyboard.press('b');
break;
case '3':
Keyboard.press(KEY_RIGHT_ALT);
Keyboard.press(KEY_F9);
break;
case '4':
Keyboard.press('i');
break;
case '5':
Keyboard.press('v');
break;
case '6':
Keyboard.press(KEY_RIGHT_ALT);
Keyboard.press(KEY_F8);
break;
case '7':
Keyboard.press('p');
break;
case '8':
Keyboard.press('m');
break;
case '9':
Keyboard.press('l');
break;
case 'A':
Keyboard.press('o');
break;
case 'B':
Keyboard.press(KEY_LEFT_ALT);
Keyboard.press('n');
break;
case 'C':
Keyboard.press(KEY_F2);
break;
case 'D':
Keyboard.press('u');
break;
case 'E':
Keyboard.press('n');
break;
case 'F':
Keyboard.press(KEY_F4);
break;
default:
break;
}
}
Keypad customKeypad = Keypad(makeKeymap(Keys), rowPins, colPins, ROWS, COLS);
void CheckAllButtons(void) {
if (customKeypad.getKeys()) {
for (int i = 0; i < LIST_MAX; i++) {
if (customKeypad.key[i].stateChanged) {
switch (customKeypad.key[i].kstate) {
case PRESSED:
pressIt(customKeypad.key[i].kchar);
break;
case RELEASED:
Keyboard.releaseAll();
break;
case IDLE:
case HOLD:
default:
break;
}
}
}
}
}
void setup() {
Keyboard.begin();
}
void loop() {
CheckAllButtons();
}
Prototype Alpha V0
It works great in Star Citizen !