Joystick or Keypad library causing HID button #1 to stick, and disables buttons.

Breakdown:
I’m making a button box, it’s a 5x5 matrix, which uses toggle switches and momentary pushbuttons. I’ve got the hardware working fine, and I’ve got the code mostly there, but I’m having an issue with the libraries (Keypad library and Joystick library). The code turns switches and buttons into an HID gamepad on Windows.

The issues:
HID button #1 is causing a ton of issues.

  1. Despite being on different lines in the matrix, when button #2 OR button #1 & #2 are pressed, the pushbuttons don’t work in the matrix, despite every other toggle switch and HID button being fine.
  2. Button #1 (switch up) will stay on even when depressed (switch down, button #2), making state 1 & 2 (button #1 and #2) simultaneously active.
  3. If I don’t set an HID button #1, none of the pushbuttons work at all, no matter which toggle switches are toggled.

What I know:
For the sake of explanation, let’s call the problematic switch the ‘master switch’.

I determined the issue what not hardware by trying the following:

  • I switched the physical arduino pins in use.
  • I switched which pins connected to which parts of the matrix.
  • I switched which columns/rows are connected to which physical pins on the arduino.

Every time, the master switch changed which toggle switch it belonged to, always sticking to whichever toggle switch was HID button #1. In every case, the outcome was the same; the master switch disabled the pushbuttons when in state #2 (HID button #2).

I also know the issue is not the pushbutton row connection, as I originally had the matrix in a 7 x 4 configuration, where some pushbuttons didn’t share the same ROW or COLUMN, but still, all the pushbuttons were disabled when HID button #2 was active.

What I DON’T know:
I don’t know if bug is caused by the Keypad Library, or the Joystick Library, since the Keypad Library assigns the matrix (‘seating’ HID button #1), but the Joystick Library assigns the HID buttons (Setting the HID buttons to their matrix positions.

Here’s an image of the circuit.

Here is the code:

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

//DEFINITIONS


#define ENABLE_PULLUPS
#define NUMROTARIES 0 //replace "?" with number of rotary encoders you are using
#define NUMBUTTONS 31 //replace "?"with number of button you are using
#define NUMROWS 5 //replace "?" with number of rows you have
#define NUMCOLS 5 //replace "?" with number of columns you have

//BUTTON MATRIX
//first change number of rows and columns to match your button matrix, 
//then replace all "?" with numbers (starting from 0)
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,24}
                                 

//BUTTON MATRIX PART 2
byte rowPins[NUMROWS] = {5,6,7,8,A2}; //change "?" to the pins the rows of your button matrix are connected to
byte colPins[NUMCOLS] = {A1,A0,15,14,16}; //change "?" to the pins the rows of your button matrix are connected to

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

//JOYSTICK SETTINGS
Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID,
  JOYSTICK_TYPE_JOYSTICK,
  32, //number of buttons
  0, //number of hat switches
  //Set as many axis to "true" as you have potentiometers for
  false, // y axis
  false, // x axis
  false, // z axis
  false, // rx axis
  false, // ry axis
  false, // rz axis
  false, // rudder
  false, // throttle
  false, // accelerator
  false, // brake
  false); // steering wheel

const int numReadings = 20;
 
int readings[numReadings];      // the readings from the analog input
int index = 0;              // the index of the current reading
int total = 0;                  // the running total
int currentOutputLevel = 0;


void setup() {
  Joystick.begin();
  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }
}

void loop() {
  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;
            }
           }   
         }
     }
}

There’s your problem:

byte buttons[NUMROWS][NUMCOLS] = {
  {0,1,2,3,4},

The value 0 is reserved for “NO_KEY”. You can’t use it for a key value.

johnwasser:
There's your problem:

byte buttons[NUMROWS][NUMCOLS] = {

{0,1,2,3,4},



The value 0 is reserved for "NO_KEY". You can't use it for a key value.

I've tried NOT using value 0 before, and I just tried again to be sure, but when I do this, none of the pushbuttons work :confused:

Any ideas?

What did you use in place of the zero?

Note: It might be prudent to get the keyboard working first and THEN add the Joystick library. You could use Serial.print() to display on Serial Monitor the state changes:

          Serial.print("Key char: ");
          Serial.print((int)buttbx.key[i].kchar);
          Serial.print("  Key code: ");
          Serial.print((int)buttbx.key[i].kcode);
          Serial.print("  New state: ");
          switch (buttbx.key[i].kstate)
          {
            case PRESSED: Serial.println("PRESSED"); break;
            case HOLD: Serial.println("HOLD"); break;
            case RELEASED: Serial.println("RELEASED"); break;
            case IDLE: Serial.println("IDLE"); break;
            default: Serial.println("<<<INVALID>>>"); break;
          }

johnwasser:
What did you use in place of the zero?

Note: It might be prudent to get the keyboard working first and THEN add the Joystick library. You could use Serial.print() to display on Serial Monitor the state changes:

When I didn't start the matrix with '0', I would use '1', which is what I'm doing now, and I'm still getting the same results as in my original post; none of the pushbuttons functions at all, no matter the state of any of the switches.

I monitored the serial monitor with the code you gave, and the switches work fine, albeit the 'Key Code' and 'Key Char' do NOT line up with the HID buttons (HID button numbers are Key Char + 4, so Key Char 18 = HID button 22).

None of the pushbuttons do anything in the serial monitor, nor do they appear to show up in there either.

If the keypad is not working alone then the problem is in your use of the Keypad library, either the wiring or a conflict with the pins you use.

Your schematic shows all of the columns shorted to the bottom row. That would short out all five buttons. Are you sure you skipped that part of the schematic?

The 'kchar' values come straight out of your keypad array. If you want them to be 4 higher then you can make them 4 higher in the array (as long as you don't use 0 for any of them).

byte colPins[NUMCOLS] = {A1,A0,15,14,16};

A0 = 14 and A1 = 15 on smaller Arduinos. Which Arduino do you use?

Whandall:

byte colPins[NUMCOLS] = {A1,A0,15,14,16};

A0 = 14 and A1 = 15 on smaller Arduinos. Which Arduino do you use?

The Joystick library requires a USB-capable processor so Leonardo or Micro. The Leonardo pins_arduino.h says:

	PB,	// D14 - MISO - PB3
	PB,	// D15 - SCK - PB1
	PB,	// D16 - MOSI - PB2
	PB,	// D17 - SS - PB0

At least MISO, SCK, and MOSI (D14, D15, and D16) are available on the ICSP header. I’m not sure if D17 is reachable anywhere. On the Micro, PB0 is used for the RX LED.

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