Programming 5 buttons and 2 encoders

Hey guys I hope this topic finds everyone well.

I am trying to do something that seems simple but I am stumped as to how to code it.

I am looking to make a button box with 5 momentary buttons and 2 rotary encoders.

I have seen someone do this with a lot more buttons and encoders and I even have the sketch but it was done on a micro board and I would like to do a simpler version on a Nano board? Is this possible?

In the video he does a matrix but as I am going to be using only 5 buttons and 2 encoders I could just do the first row of buttons?

The sketch for the 32 buttons has this code -

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

#define ENABLE_PULLUPS
#define NUMROTARIES 4
#define NUMBUTTONS 24
#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},
};

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

So I was thinking that my code just needs to read like below?

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

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

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

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

rotariesdef rotaries[NUMROTARIES] {
{0,1}
};

I was planning on wiring physically to A3 for the first part of the chain to all 5 momentary buttons then D14,16,10,9,8 for the other side of the button.

For the 2 Encoders I was thinking of going into pin 15 for push function then D14 and 16 for the opposite side of that circuit,

For the rotational function I was going to go TX, RX on the first one and then D2 and 3 on the second one?

I hope this makes sense and any help would be appreciated.

Many thanks
Darren

The Micro is a microcontroller board based on the ATmega32U4 which allows the Micro to appear to a connected computer as a mouse and keyboard, in addition to a virtual (CDC) serial / COM port.

The Nano does not have that capability

if your code depends on this, then that won't do.

J-M-L:
The Micro is a microcontroller board based on the ATmega32U4 which allows the Micro to appear to a connected computer as a mouse and keyboard, in addition to a virtual (CDC) serial / COM port.

The Nano does not have that capability

if your code depends on this, then that won't do.

Ahh thanks for the reply that clears up something I was wondering as to how people make button boxes work on Consoles too, I shall get a Micro on order !

The other question then is will my code and placement on a micro board work for the 5 buttons and 2 rotaries?

Many thanks again

i'm using an esp32 to monitor 16 buttons, 2 encoders, several pots and a OLED display.

the 16 buttons are monitored using 8 pins as a matrix

i developed encoder code on an arduino using 2 interrupts. i don't believe the arduino had more than 2 interrupts (but has multiple change interrupts ???). any gpio on an esp32 can be used as an interrupt. you would need 4 for 2 encoders

there is no code, just array definitions and I don't know those types

but just as C++ stands, this is not correct

#define NUMROWS 1
#define NUMCOLS 1


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

NUMCOLS as you define it should be 5

also this (comparing to the other def) feels incorrect too

rotariesdef rotaries[NUMROTARIES] {
  {0,1}
};

Please correct your post above and add code tags around code segments:
[code]`` [color=blue]// your code is here[/color] ``[/code].

It should look like this:// your code is here
(Also press ctrl-T (PC) or cmd-T (Mac) in the IDE before copying to indent your code properly)

J-M-L:
there is no code, just array definitions and I don't know those types

but just as C++ stands, this is not correct

#define NUMROWS 1

#define NUMCOLS 1

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


NUMCOLS as you define it should be 5

also this (comparing to the other def) feels incorrect too

rotariesdef rotaries[NUMROTARIES] {
  {0,1}
};




----

Please correct your post above and add **code tags** around code segments:
`[code]`` [color=blue]// your code is here[/color] ``[/code]`.

It should look like this:`// your code is here`
(Also press ctrl-T (PC) or cmd-T (Mac) in the IDE before copying to indent your code properly)

Sorry first time adding code or asking for help on here, I shall update the post now with the full code at the top

See that’s the rotariesdef type definition

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

you can’t have just 2 values to describe yours.

@daz1987

Other post/duplicate DELETED
Please do NOT cross post / duplicate as it wastes peoples time and efforts to have more than one post for a single topic.

Continued cross posting could result in a time out from the forum.

Could you also take a few moments to Learn How To Use The Forum.
It will help you get the best out of the forum in the future.
Other general help and troubleshooting advice can be found here.