Hello!
yes...another thread about button box.
First, I read some discussions on this forum about the same topic, but I still have some doubts and I hope to have them all clarified with your help.
I don't have any serious electrical or programming background, but I consider myself able to understand basic things related to this matter.
The project is related to a button box (switches with leds, toggles and rotary encoders with an arduino pro micro board).
The button box is made of:
a) 1x latching toggle switch (on-off positions), named SW1 in the diagram below.
This has a built-in led running at 12V, but I don't plan to connect the led after reading other topics on the matter
b) 4x momentary toggle switches (on-off-on positions), named SW2-3, SW4-5, SW6-7, SW8-9 in the diagram below.
c) 9x momentary push buttons, each with an integrated led (running at 5V), named SW10, SW11, SW12, SW13, SW14, SW15, SW16, SW17, SW18 (switches), L1, L2, L3, L4, L5, L6, L7, L8, L9 in the diagram below.
The leds can be wired independently of the switches (each button have 4 pins, 2 of these for each led).
d) 4x rotary encoders, named SW19, SW20, SW21, SW22 in the diagram below.
e) 5x 10k ohm resistors, named R1 --> R5 in the diagram below.
f) 22x diodes, type 1N4148, named D1--> D22 in the diagram below.
All the switches, encoders and toggles are organized in a matrix, 5x5.
Since I read several discussions about this, I'm planning to use diodes for all the switches to prevent ghosting.
Here you can find the diagram I did (I hope I used the correct symbols):
Question is very simple, do you see any issue with this diagram?
The other question is related to software.
I'm planning to use this code (modified, hopefully correctly, for my needs), found in internet, freely available:
#include <Keypad.h>
#include <Joystick.h>
#define ENABLE_PULLUPS
#define NUMROTARIES 4
#define NUMBUTTONS 22
#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,24}
};
struct rotariesdef {
byte pin1;
byte pin2;
int ccwchar;
int cwchar;
volatile unsigned char state;
};
rotariesdef rotaries[NUMROTARIES] {
{0,1,24,25,0},
{2,3,26,27,0},
{4,5,28,29,0},
{6,7,30,31,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] = {21,20,19,18,15};
byte colPins[NUMCOLS] = {14,16,10,9,8};
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);
};
}
}
If I understood correctly, I'm using 5 pull-up resistors (external resistors), so I should not need defining ENABLE_PULLUPS in the software, is it right?
If this is true, is it right to delete this line?:
#define ENABLE_PULLUPS
and what should I do with this block of code?
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
}
}
Should I delete at all the following lines?
#ifdef ENABLE_PULLUPS
digitalWrite(rotaries[i].pin1, HIGH);
digitalWrite(rotaries[i].pin2, HIGH);
#endif
Or should I put the 2 digitalWrite() instructions outside of the if block like this?
void rotary_init() {
for (int i=0;i<NUMROTARIES;i++) {
pinMode(rotaries[i].pin1, INPUT);
pinMode(rotaries[i].pin2, INPUT);
digitalWrite(rotaries[i].pin1, HIGH);
digitalWrite(rotaries[i].pin2, HIGH);
}
}
Thank you for any feedback, and please be patient... as I'm a total noob on this matter.




