Button box missing button

Hi, i'm using some code i got for button boxes for simulators.
After uploading to the Leonardo without any errors i tested all the buttons but one never works.
8 rows with 4 columns, 24 momentary push buttons and 4 lever switches (2 momentary). The problem is one of the lever switches only shows in 1 input on the controller tester in windows.

It's not the switch, it works. If i change the number of total buttons on the arduino code it shows on the same place of one of the push buttons. If i define 32 as the maximum number of buttons i never see button 4 light up in the tester window.

Switches can be two position (Vcc and GND) with a common pin leading to your Leonardo input pin or one position (ON/continuity and OFF/open) needing pull-up or pull-down resistor for stability.

Would you share your wiring schematic and code sketch to help provide a better answer? Thank you.

You could also simulate your setup in Wokwi.com

Always show us a good schematic of your proposed circuit.

Show us a good image(s) of your ‘actual’ wiring. Give links to components.


In the Arduino IDE, use Ctrl T or CMD T to format your code then copy the complete sketch.

Use the < CODE / > icon from the ‘posting menu’ to attach the copied sketch.

#include <HID.h>

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

//DEFINITIONS
#define ENABLE_PULLUPS
#define NUMROTARIES 0  //replace "?" with number of rotary encoders you are using
#define NUMBUTTONS 32  //replace "?"with number of buttong you are using
#define NUMROWS 8      //replace "?" with number of rows you have
#define NUMCOLS 4      //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, 4 },
  { 5, 6, 7, 8 },
  { 9, 10, 11, 12 },
  { 13, 14, 15, 16 },
  { 17, 18, 19, 20 },
  { 21, 22, 23, 24 },
  { 25, 26, 27, 28 },
  { 29, 30, 31, 32 }

};

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

//ROTARY ENCODERS
//each line controls a different rotary encoder
//the first two numbers refer to the pins the encoder is connected to
//the second two are the buttons each click of the encoder wil press
//do NOT exceed 31 for the final button number
rotariesdef rotaries[NUMROTARIES]{
  // {0,1,26,27,0}, //rotary 1
  // {2,3,28,29,0}, //rotary 2
  // {4,5,23,24,0} //rotary 3


};

#define DIR_CCW 0x5
#define DIR_CW 0x10
#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

//BUTTON MATRIX PART 2
byte rowPins[NUMROWS] = { 13, 12, 11, 10, 9, 8, 7, 6 };  //change "?" to the pins the rows of your button matrix are connected to
byte colPins[NUMCOLS] = { 4, 2, 3, 5 };                  //change "?" to the pins the rows of your button matrix are connected to trocar a4 e a5

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
                   true,    // y axis
                   true,    // x axis
                   true,    // z axis
                   true,    // rx axis
                   false,   // ry axis
                   false,   // rz axis
                   false,   // rudder
                   false,   // tot
                   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;

//POTENTIOMETERS PART 1
//add all the axis' which are enabled above
int yAxis_ = 0;  //posso mudar para o eixo q quiser, tipo xy para procurar alvo numa caixa
int xAxis_ = 0;
int zAxis_ = 0;
int rxAxis_ = 0;

//POTENTIOMETERS  PART 2
//Which pins are your potentiometers connected to?
int potentiometerPin1 = A0;  //Change "?" to the pin your potentiometer is connected to (acho q é o 4)

int potentiometerPin2 = A1;  //Change "?" to the pin your potentiometer is connected to (acho q é o 4)

int potentiometerPin3 = A2;  //Change "?" to the pin your potentiometer is connected to (acho q é o 4)

int potentiometerPin4 = A3;  //Change "?" to the pin your potentiometer is connected to (acho q é o 4)


const bool initAutoSendState = true;




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

void loop() {

  CheckAllEncoders();
  CheckAllButtons();
  CheckAllPotentiometers();
}

//POTENTIOMETERS PART 3
//change the details to match teh details above for each potentiometer you are using
void CheckAllPotentiometers() {

  //potentiometer 1
  currentOutputLevel = getAverageOutput(potentiometerPin1);
  yAxis_ = map(currentOutputLevel, 0, 1920, 0, 1920);
  Joystick.setYAxis(yAxis_);

  //potentiometer 2
  currentOutputLevel = getAverageOutput(potentiometerPin2);
  xAxis_ = map(currentOutputLevel, 0, 1023, 0, 255);
  Joystick.setXAxis(xAxis_);


  //potentiometer 3
  currentOutputLevel = getAverageOutput(potentiometerPin3);
  zAxis_ = map(currentOutputLevel, 0, 1920, 0, 1920);
  Joystick.setZAxis(zAxis_);

  //potentiometer 4
  currentOutputLevel = getAverageOutput(potentiometerPin4);
  rxAxis_ = map(currentOutputLevel, 0, 1023, 0, 255);
  Joystick.setRxAxis(rxAxis_);
}

int getAverageOutput(int pinToRead) {
  index = 0;
  total = 0;

  while (index < numReadings) {
    readings[index] = analogRead(pinToRead);
    total = total + readings[index];
    index = index + 1;
    //delay (1);
  }
  return total / numReadings;
}


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) {
  //Serial.print("Processing rotary: ");
  //Serial.println(_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) {
  Serial.println("Checking rotaries");
  for (int i = 0; i < NUMROTARIES; i++) {
    unsigned char result = rotary_process(i);
    if (result == DIR_CCW) {
      Serial.print("Rotary ");
      Serial.print(i);
      Serial.println(" <<< Going CCW");
      Joystick.setButton(rotaries[i].ccwchar, 1);
      delay(50);
      Joystick.setButton(rotaries[i].ccwchar, 0);
    };
    if (result == DIR_CW) {
      Serial.print("Rotary ");
      Serial.print(i);
      Serial.println(" >>> Going CW");
      Joystick.setButton(rotaries[i].cwchar, 1);
      delay(50);
      Joystick.setButton(rotaries[i].cwchar, 0);
    };
  }
  Serial.println("Done checking");
}

the code is not mine.
Also the switches are on-off-on, 3 stable positions.
One works.

the bottom rectangles are the toggle switches. Both ends go to separate rows and the middle part (wich is off) go to columns
I have diodes connected to the toggle switches, i'm able to keep them in the on position without affecting any other switches

https://www.tinkercad.com/things/0PBQzg6HXFk

tried it there but there's an error somewhere

Where did you get your library files? I can not find the right versions.

The error is looking for the library files... Would you post them here, or a link to the originals?

I put // before any mentions to joystick. I got that from github or something.
The simulation works in tinkercad but i don't know how to simulate the button presses like in the windows tester.
The best i could do was connect several multimeters do the buttons and see what happens. They all work.
Maybe i made some wiring mistake even though i was following my schematic

I think I found your source and the source of your problems...

And the reason Joystick_ is giving errors

And an instructables with the correct library...

The library you need (NOT the Arduino library)

Here is your code in a simulation I tried to make... but your drawing is too much for me.

... and the mentioned library wants to overwrite the old Joystick library...

overwrite

... and if you do overwrite the old Joystick library, but do not have the right board...

#error The Joystick library can only be used with a USB MCU (e.g. Arduino Leonardo, Arduino Micro, etc.).

So... I can not help any more... I do not have the hardware. Try that Instructables...

the Joystick thing explains why one switch doesn't show?
Also i only got an error mentioning Joystick on Tinkercad simulation. Home, when i test the code for error in the arduino programme it compiles without any errors

thanks anyway but since i get no errors about Joystick at home i don't think the problem resides there. I'll check my wiring again


//#include <HID.h>

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

//DEFINITIONS
#define ENABLE_PULLUPS
#define NUMROTARIES 0  //replace "?" with number of rotary encoders you are using
#define NUMBUTTONS 32  //replace "?"with number of buttong you are using
#define NUMROWS 8      //replace "?" with number of rows you have
#define NUMCOLS 4      //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, 4 },
  { 5, 6, 7, 8 },
  { 9, 10, 11, 12 },
  { 13, 14, 15, 16 },
  { 17, 18, 19, 20 },
  { 21, 22, 23, 24 },
  { 25, 26, 27, 28 },
  { 29, 30, 31, 32 }

};

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

//ROTARY ENCODERS
//each line controls a different rotary encoder
//the first two numbers refer to the pins the encoder is connected to
//the second two are the buttons each click of the encoder wil press
//do NOT exceed 31 for the final button number
rotariesdef rotaries[NUMROTARIES]{
  // {0,1,26,27,0}, //rotary 1
  // {2,3,28,29,0}, //rotary 2
  // {4,5,23,24,0} //rotary 3


};

#define DIR_CCW 0x5
#define DIR_CW 0x10
#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

//BUTTON MATRIX PART 2
byte rowPins[NUMROWS] = { 13, 12, 11, 10, 9, 8, 7, 6 };  //change "?" to the pins the rows of your button matrix are connected to
byte colPins[NUMCOLS] = { 4, 2, 3, 5 };                  //change "?" to the pins the rows of your button matrix are connected to trocar a4 e a5

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

//YSTICK SETTINGS
//ystick 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
          //       true,    // y axis
           //      true,    // x axis
           //      true,    // z axis
           //      true,    // rx axis
            //    false,   // ry axis
          //       false,   // rz axis
            //    false,   // rudder
       //          false,   // tot
            //     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;

//POTENTIOMETERS PART 1
//add all the axis' which are enabled above
int yAxis_ = 0;  //posso mudar para o eixo q quiser, tipo xy para procurar alvo numa caixa
int xAxis_ = 0;
int zAxis_ = 0;
int rxAxis_ = 0;

//POTENTIOMETERS  PART 2
//Which pins are your potentiometers connected to?
int potentiometerPin1 = A0;  //Change "?" to the pin your potentiometer is connected to (acho q é o 4)

int potentiometerPin2 = A1;  //Change "?" to the pin your potentiometer is connected to (acho q é o 4)

int potentiometerPin3 = A2;  //Change "?" to the pin your potentiometer is connected to (acho q é o 4)

int potentiometerPin4 = A3;  //Change "?" to the pin your potentiometer is connected to (acho q é o 4)


const bool initAutoSendState = true;




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

void loop() {

  CheckAllEncoders();
  CheckAllButtons();
  CheckAllPotentiometers();
}

//POTENTIOMETERS PART 3
//change the details to match teh details above for each potentiometer you are using
void CheckAllPotentiometers() {

  //potentiometer 1
  currentOutputLevel = getAverageOutput(potentiometerPin1);
  yAxis_ = map(currentOutputLevel, 0, 1920, 0, 1920);
// Joystick.setYAxis(yAxis_);

  //potentiometer 2
  currentOutputLevel = getAverageOutput(potentiometerPin2);
  xAxis_ = map(currentOutputLevel, 0, 1023, 0, 255);
//  Joystick.setXAxis(xAxis_);


  //potentiometer 3
  currentOutputLevel = getAverageOutput(potentiometerPin3);
  zAxis_ = map(currentOutputLevel, 0, 1920, 0, 1920);
 // Joystick.setZAxis(zAxis_);

  //potentiometer 4
  currentOutputLevel = getAverageOutput(potentiometerPin4);
  rxAxis_ = map(currentOutputLevel, 0, 1023, 0, 255);
//  Joystick.setRxAxis(rxAxis_);
}

int getAverageOutput(int pinToRead) {
  index = 0;
  total = 0;

  while (index < numReadings) {
    readings[index] = analogRead(pinToRead);
    total = total + readings[index];
    index = index + 1;
    //delay (1);
  }
  return total / numReadings;
}


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) {
  //Serial.print("Processing rotary: ");
  //Serial.println(_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) {
  Serial.println("Checking rotaries");
  for (int i = 0; i < NUMROTARIES; i++) {
    unsigned char result = rotary_process(i);
    if (result == DIR_CCW) {
      Serial.print("Rotary ");
      Serial.print(i);
      Serial.println(" <<< Going CCW");
      //Joystick.setButton(rotaries[i].ccwchar, 1);
      delay(50);
   //   Joystick.setButton(rotaries[i].ccwchar, 0);
    };
    if (result == DIR_CW) {
      Serial.print("Rotary ");
      Serial.print(i);
      Serial.println(" >>> Going CW");
//Joystick.setButton(rotaries[i].cwchar, 1);
      delay(50);
   // Joystick.setButton(rotaries[i].cwchar, 0);
    };
  }
  Serial.println("Done checking");
}


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