Problem with button box

Hi all. I just finished this button box, powered by an Arduino Leonardo:


As you can see, it consists of a key switch, two hooded switches, a rotary encoder, 10 2-position switches (ON-OFF), one 3 position, momentary switch (ON-OFF-ON), and 10 push buttons (plus a handheld speaker with one more button).
For ease of coding and wiring, the key, hooded switches, rotary encoder (but not it's push button) and the button in the speaker are individually wired to the Leonardo, and the rest (23 buttons and switches) are wired in a matrix of 5x5.
All 2-position switches have individual diodes in series. It seems to work fine and as expected except in one specific scenario, which is when all switches are on. In that scenario, all the rest of the buttons without a diode (all push buttons + the momentary switch) stop working. I only need to switch one of them back off, regardless of which one, for the buttons to work again.
Is that an expected behaviour? have I done something wrong? I don't think it's a big deal, as it shouldn't be very often that all switches are on at the same time, but it kinda bothers me.

This is the full code, though I believe it's not a code issue:

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

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


byte buttons[NUMROWS][NUMCOLS] = {
  {5, 4, 26, 24, 25},
  {14, 13, 12, 11, 10},
  {20, 19, 18, 17, 16},
  {9, 15, 21, 23},
  {28, 27, 6, 22},
};

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

rotariesdef rotaries[NUMROTARIES] {
  {0, 1, 7, 8, 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] = {15, 18, 19, 20, 21};
byte colPins[NUMCOLS] = {14, 16, 10, 9, 8};

int radio = 2;
int bateria = 4;
int arranque = 5;
int naranja = 6;
int blanco = 7;

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();
  pinMode(radio, INPUT_PULLUP);
  pinMode(bateria, INPUT_PULLUP);
  pinMode(arranque, INPUT_PULLUP);
  pinMode(naranja, INPUT);
  pinMode(blanco, INPUT);
}

void loop() {

  CheckAllEncoders();

  CheckAllButtons();

  CheckIndependentButtons();

}

void CheckIndependentButtons(void) {

    if(digitalRead(radio) == 0) {
    Joystick.setButton(29, 1);
  }
  else {
    Joystick.setButton(29, 0);
  }

      if(digitalRead(bateria) == 0) {
    Joystick.setButton(0, 1);
  }
  else {
    Joystick.setButton(0, 0);
  }

    if(digitalRead(arranque) == 0) {
    Joystick.setButton(1, 1);
  }
  else {
    Joystick.setButton(1, 0);
  }

    if(digitalRead(naranja) == 1) {
    Joystick.setButton(2, 1);
  }
  else {
    Joystick.setButton(2, 0);
  }

    if(digitalRead(blanco) == 1) {
    Joystick.setButton(3, 1);
  }
  else {
    Joystick.setButton(3, 0);
  }
  
}

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

Make Yourself the schematics and look at the connection You get when all swiches are on!

1 Like

Haha, I was going to say post the schematic you used to wire this up, but you probably right - never too late to draw a schematic. :wink:

So, @Assamita, it could be a code problem, but no one is going to dive into the code before seeing a schematic.

Even a celly of a hand-drawn schematic will do, just make sure to show all the wording.

a7

1 Like

Even simple buttons need diodes if several buttons are pressed at the same time.

That's usually not the case with push buttons. However, I do believe that might be the case and I probably need to add a diode to all the elements in the matrix. I'm working on the diagram, it will be ready soon.

Yes of course, every switch, no matter the kind, in a matrix needs the diode.

Which… we would have said immediately we saw the… schematic.

a7

this would be the schematic (with what Tinkercad offers):


I'll try adding the missing diodes, see if that works, though it might not really be needed, as the scenario of having all 10 switches in the ON position is very unlikely.
Nevertheless, I want to do it correctly, so let's see if adding the diodes to the push buttons help with that (I would assume it does).

Nope, that did nothing. I've added a diode to all the push buttons, but the behaviour is still the same.

No, if You only press one at the time. Pressing a certain pair, or three, it will go wrong. I've tested running without diodes and helpers have shown the erroneous way the signals go.

Good. Did You put in down in CAD?.....
Are the diodes connected the proper way? It might depend on the code but I don't have the hole picture available.

There are only 23 entries defined for those 24 buttons ..... Okey?

Courteous Nick Gammon

1 Like

@Assamita nice looking box BTW. :+1:

a7

Yes, I made sure to connect them exactly the same way they are in the switches, which the way I have them, they are exactly as buttons, only they stay pressed, as I only use two of the 3 pins. I made sure to add the diodes in the row "rails" and in my case, all the cathodes are pointing at the button/switch leg, and the anode to the line, they didn't work the other way around. I'm assuming the keypad library works by column pins acting as inputs and rows as outputs, or viceversa, so the current can flow from one to another, right? and in my case, I needed to point the cathode to the columns.

There are actually 23 buttons/switches. I forgot to change the value of NUMBUTTONS. Do you think that could be an issue? After all, it's nowhere else used in the code, so I don't really know what is it defined for.

Yup. that's basically what I did, though the columns are pins instead of 5V and I haven't used resistors, as I believe the keypad library uses the internal pullup resistors.

Thanks, I do think it looks pretty neat too :slight_smile:
This is for a friend of mine. I've explained him that it won't work only if all the switches are on and he's fine with that. It's not intended to have all the pins on at the same time or pressing several buttons at once.
For future projects, I would still want to know what's wrong with it, because I do still want to make it work 100%, but for this project in particular, I think I'll leave it as is.

I have spare buttons and switches, so I think I'll build a temporary device just to keep testing with this, see if we can reach the bottom of it.

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