Pro Micro Button Box with Matrix - Code Help

Hi,
I have made a button box using a matrix for the wiring. I have watched a video on Youtube that made things look easy (MAKE THIS BUTTON BOX | 32 FUNCTION w ENCODERS - YouTube) but I am confused with the code that is supplied (GitHub - AM-STUDIO/32-FUNCTION-BUTTON-BOX) as I don't have rotary encoders (didnt want them), I just have a mix of buttons and toggles.

Rewind a little.....

I have been using Simhub (https://www.simhubdash.com/) with an Arduino Uno R3 using the built in Arduino programming tool and it registered all the button presses and toggle switches fine. I decided I wanted to change the Uno for a Pro Micro board so that I could use the button box with my Xbox or PS4 but thats where I am stuck.

Back to now....

Ive got everything wired up and if I use the Simhub way of programming then all is good...except it requires you to programme what each button press is in its 'Keyboard Emulation' section. This obviously doesnt help with using the button box on my consoles as the Micro isnt actually programmed to give the key commands, its just being emulated by Simhub.
I have tried using the Sketch mentioned at the top of the post but its for a different layout so when I start changing things like a complete noob with zero coding experience I get errors when veryfing.

I would be eternally greatful if anyone could lead me down the path to sorting this out myself.

This is how I have the board programmed through Simhub (I assume this will help you guys see how things are set up):

I have used Fritzing for the first time and drawn out what I have wired up:

Code mentioned above:

//BUTTON BOX 
//USE w ProMicro
//Tested in WIN10 + Assetto Corsa
//AMSTUDIO
//20.8.17

#include <Keypad.h>
#include <Joystick.h>

#define ENABLE_PULLUPS
#define NUMBUTTONS 23
#define NUMROWS 4
#define NUMCOLS 6


byte buttons[NUMROWS][NUMCOLS] = {
  {0,1,2,3,4,5},
  {6,7,8,9,10,11},
  {12,13,14,15,16,17},
  {18,19,20,21,22,23},
};


#define DIR_CCW 0x10
#define DIR_CW 0x20
#define R_START 0x0

#ifdef HALF_STEP
#define R_CCW_BEGIN 0x1
#define R_CW_BEGIN 0x2
#define R_START_M 0x3
#define R_CW_BEGIN_M 0x4
#define R_CCW_BEGIN_M 0x5
const unsigned char ttable[6][4] = {
  // R_START (00)
  {R_START_M,            R_CW_BEGIN,     R_CCW_BEGIN,  R_START},
  // R_CCW_BEGIN
  {R_START_M | DIR_CCW, R_START,        R_CCW_BEGIN,  R_START},
  // R_CW_BEGIN
  {R_START_M | DIR_CW,  R_CW_BEGIN,     R_START,      R_START},
  // R_START_M (11)
  {R_START_M,            R_CCW_BEGIN_M,  R_CW_BEGIN_M, R_START},
  // R_CW_BEGIN_M
  {R_START_M,            R_START_M,      R_CW_BEGIN_M, R_START | DIR_CW},
  // R_CCW_BEGIN_M
  {R_START_M,            R_CCW_BEGIN_M,  R_START_M,    R_START | DIR_CCW},
};
#else
#define R_CW_FINAL 0x1
#define R_CW_BEGIN 0x2
#define R_CW_NEXT 0x3
#define R_CCW_BEGIN 0x4
#define R_CCW_FINAL 0x5
#define R_CCW_NEXT 0x6

const unsigned char ttable[7][4] = {
  // R_START
  {R_START,    R_CW_BEGIN,  R_CCW_BEGIN, R_START},
  // R_CW_FINAL
  {R_CW_NEXT,  R_START,     R_CW_FINAL,  R_START | DIR_CW},
  // R_CW_BEGIN
  {R_CW_NEXT,  R_CW_BEGIN,  R_START,     R_START},
  // R_CW_NEXT
  {R_CW_NEXT,  R_CW_BEGIN,  R_CW_FINAL,  R_START},
  // R_CCW_BEGIN
  {R_CCW_NEXT, R_START,     R_CCW_BEGIN, R_START},
  // R_CCW_FINAL
  {R_CCW_NEXT, R_CCW_FINAL, R_START,     R_START | DIR_CCW},
  // R_CCW_NEXT
  {R_CCW_NEXT, R_CCW_FINAL, R_CCW_BEGIN, R_START},
};
#endif

byte rowPins[NUMROWS] = {21,20,19,18}; 
byte colPins[NUMCOLS] = {7,6,5,4,3,2}; 

Keypad buttbx = Keypad( makeKeymap(buttons), rowPins, colPins, NUMROWS, NUMCOLS); 

Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID, 
  JOYSTICK_TYPE_JOYSTICK, 32, 0,
  false, false, false, false, false, false,
  false, false, false, false, false);

void setup() {
  Joystick.begin();

void loop() { 

  CheckAllEncoders();

  CheckAllButtons();

}

I have been messing around and have got slightly closer but no doubt still miles away.

#include <Keypad.h>
const byte ROWS = 4; //four rows
const byte COLS = 6; //four columns
//define the cymbols on the buttons of the keypads
char hexaKeys[ROWS][COLS] = {
  {'A','B','C','D','E','F'},
  {'G','H','I','J','K','L'},
  {'M','N','O','O','Q','R'},
  {'S','T','U','V','W','X'},
};
byte rowPins[ROWS] = {15, 14, 16, 10}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {7, 6, 5, 4, 3, 2}; //connect to the column pinouts of the keypad
 
//initialize an instance of class NewKeypad
Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS); 
 
void setup(){
  Serial.begin(9600);
}
  
void loop(){
  char customKey = customKeypad.getKey();
  
  if (customKey){
    Serial.println(customKey);
  }
}

This code outputs the letters assigned to the buttons/toggles in the Arduino Serial Monitor but obviously its still seen as a pro micro and not a USB keyboard.
Is it possible to insert something into the code that will get the board to show as a USB keyboard or am I way off the mark with the code Im using?

Sure. Just consult the documentation on the Pro Micro USB interface.

Thats where I need the help as I have zero idea what I am doing :confused:
The code that I got to work in the serial monitor is something I saw on a blog post for a smaller matrix and I figured out how to expand it to what I need.
I have looked at that paged you linked to so many times and tried to figure stuff out but I have no idea.

Then try simpler projects until you get up to speed. It's progressive learning, like math.

Gee thanks.
I had hoped that following the guide I could make the DIY button box and figure out the changes in code myself but alas I cant.
Im merely looking for some hints as to what I should be doing.
I thought this place was supposed to be somewhere to come for help not snarky comments.

I could no doubt get it sorted myself if I followed one of the guides that shows how to do it using individual buttons connected via resistor to each pin but as I have gone with a matrix to get more available buttons I dont know how to convert the matrix coding to work resitive values coding.

1 Like

correct me if I'm wrong but your current code works as it should except that it prints characters to serial monitor rather than using them to emulate key presses?
If so the solution should be as simple as including the keyboard library and sending key presses in place of your Serial.prints.

Try this and let us know if it works or not

#include <Keypad.h>
#include <Keyboard.h>
const byte ROWS = 4; //four rows
const byte COLS = 6; //four columns
//define the cymbols on the buttons of the keypads
char hexaKeys[ROWS][COLS] =
{
    {'A','B','C','D','E','F'},
    {'G','H','I','J','K','L'},
    {'M','N','O','O','Q','R'},
    {'S','T','U','V','W','X'},
};
byte rowPins[ROWS] = {15, 14, 16, 10}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {7, 6, 5, 4, 3, 2}; //connect to the column pinouts of the keypad

//initialize an instance of class NewKeypad
Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);

void setup()
{
    Serial.begin(9600);
    Keyboard.begin();
}

void loop()
{
    char customKey = customKeypad.getKey();

    if (customKey)
    {
//    Serial.println(customKey);
        Keyboard.write( customKey );
    }
}
1 Like

Perfect!
Works as I was hoping, THANK YOU!!!!

I thought it was going to be simple, I just didnt know that if I added those few bits of Keyboard.x that it would do what I want, I assumed it would take a lot more messing about than what it actually was.

1 Like