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