Issues with button box wiring/code

I am very new to electronic projects but I am building a button box from a tutorial on YouTube. It is a 32-function button box for American Truck Simulator's PC game. I will provide pictures of the button layout, the wiring diagram, and the code I used. The problem is I used a different button layout than the tutorial one and therefore had to change the code to accommodate my button layout. All buttons work but when I press the 5 buttons that correspond to the rows they all press the same button. For example, the 5 buttons on row A1 are all pressing button 1 and so on for the rest of the rows but I need them to use all 25 buttons. Also, the buttons in row 16 don't work at all. There is a rotary encoder in with the buttons and surprisingly the turn function works but the button presses the same as the others in the row. If someone can help point me in the right direction that would be fantastic and thanks in advance. If I haven't put the right information please let me know what else is needed.

//BUTTON BOX 
//USE w ProMicro
//BIGGINS
//09-08-2022

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

#define ENABLE_PULLUPS
#define NUMROTARIES 4
#define NUMBUTTONS 24
#define NUMROWS 5
#define NUMCOLS 5


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},
};

struct rotariesdef {
  byte pin1;
  byte pin2;
  int ccwchar;
  int cwchar;
  volatile unsigned char state;
};

rotariesdef rotaries[NUMROTARIES] {
  {0,1,24,25,0},
};

#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] = {19,18,15,14,16}; 
byte colPins[NUMCOLS] = {10,9,8,7,6}; 

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();
  rotary_init();}

void loop() { 

  CheckAllEncoders();

  CheckAllButtons();

}

void CheckAllButtons(void) {
      if (buttbx.getKeys())
    {
       for (int i=0; i<LIST_MAX; i++)   
        {
           if ( buttbx.key[i].stateChanged )   
            {
            switch (buttbx.key[i].kstate) {  
                    case PRESSED:
                    case HOLD:
                              Joystick.setButton(buttbx.key[i].kchar, 1);
                              break;
                    case RELEASED:
                    case IDLE:
                              Joystick.setButton(buttbx.key[i].kchar, 0);
                              break;
            }
           }   
         }
     }
}


void rotary_init() {
  for (int i=0;i<NUMROTARIES;i++) {
    pinMode(rotaries[i].pin1, INPUT);
    pinMode(rotaries[i].pin2, INPUT);
    #ifdef ENABLE_PULLUPS
      digitalWrite(rotaries[i].pin1, HIGH);
      digitalWrite(rotaries[i].pin2, HIGH);
    #endif
  }
}


unsigned char rotary_process(int _i) {
   unsigned char pinstate = (digitalRead(rotaries[_i].pin2) << 1) | digitalRead(rotaries[_i].pin1);
  rotaries[_i].state = ttable[rotaries[_i].state & 0xf][pinstate];
  return (rotaries[_i].state & 0x30);
}

void CheckAllEncoders(void) {
  for (int i=0;i<NUMROTARIES;i++) {
    unsigned char result = rotary_process(i);
    if (result == DIR_CCW) {
      Joystick.setButton(rotaries[i].ccwchar, 1); delay(50); Joystick.setButton(rotaries[i].ccwchar, 0);
    };
    if (result == DIR_CW) {
      Joystick.setButton(rotaries[i].cwchar, 1); delay(50); Joystick.setButton(rotaries[i].cwchar, 0);
    };
  }
}

Well done using code tags, and You tried to show the connections.
Forget the physical part of buttons and circuits. Their positions and the shape of the IC's are irrelevant. Use the logical aspect for schematics.
Try again. The picture is way too cryptic for analysis.

Apologies this is my first post. Is there a better way to show the wiring diagram? I'm not sure if my problem is the code or the wiring diagram.

Yes. Please look around at some threads here. Late here, sorry for the short reply.
The logical part, its connections, is the important piece, not the shape of the components, pin numbers etc.

I'm glad you're replying at all so thank you very much. I think I see what you are saying. Do I need to follow a 5x5 matrix somehow for the wiring?

That would be perfect. It uses a minimum of I/O, 5 + 5 =10.
There are libraries handling such arrangements. Guessing I think keyboard.h might be worth looking at.

I believe I just figured out my problem. I have all the connections wrong in the wiring. Thank you very much for your advice you put me on the right path. If I have any more problems which are likely I'll reach out again. I'll also figure out how to make a proper wiring diagram that is readable. Again thank you I can't say it enough.

That was the issue I had the wiring messed up. I rewired everything and all buttons function properly. I can't thank you enough for putting me on the right path. I have plans to expand the buttons on the box in the near future so I'll probably be back for more assistance. Cheers, you legend!

Nice to hear.
Thanks.

Have a look at free schematic software like kicad and easyeda. It really does help to have a structured overview of a project and I find these ones easy to use and read. I generally sketch things on pen and paper first and then go through everything one at a time when putting on computer. It is useful to write down each components requirements so that you can easily see that things are connected to compatible things

WARNING: You can't use the value zero for a key because the keypad library uses zero to represent NO_KEY.

1 Like

Thanks for the reply. I changed the numbers to letters in the byte buttons section as I saw a reply you made on another post with a similar problem. All buttons work properly and I am very excited to use the box. Again thanks and I appreciate your time.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.