rotary encoder matrix and push-buttons

Status
Not open for further replies.

Sprool

Active member
So Im building a 20-switch button box + 4 rotary encoders for controlling DCS flight sim. The code used is from this excellent tutorial: https://www.youtube.com/watch?v=Z7Sc4MJ8RPM
All works fine up to the point where I wire in the rotary encoder switch terminals, then I get a load of cross-chatter when turning the r/e's and the push-button switch fails to light a button. I've heard I may need diodes in the circuit?
 
Have you de-bounced the push buttons (including on the encoders)? Also what code are you using for the encoders (the link in video wants cash to see the code)? Your saying that if you turn one encoder, others will change values too? The circuit in the video (at 5:08) for the encoders is correct, no diodes are needed for them. If you start pushing more than one of the matrix buttons at a time, you will need diodes.
 
All the non-encoder switches are just in a simple scan matrix. The encoders aren't matrixed but the push switches on the encoders are matrixed. I suspect you have mis-wired the encoders. The 3 pin group is the encoder output and the center pin is common - run it to ground. The two pin group is the switch and should be added to the matrix as shown in the video.

But, without code, it's impossible to say how it should work with any confidence.
 
All the non-encoder switches are just in a simple scan matrix. The encoders aren't matrixed but the push switches on the encoders are matrixed. I suspect you have mis-wired the encoders. The 3 pin group is the encoder output and the center pin is common - run it to ground. The two pin group is the switch and should be added to the matrix as shown in the video.

But, without code, it's impossible to say how it should work with any confidence.
The code is linked on the site and I had no need to pay, but here is my version amended for my setup: (attached)

I did see one thread talking about having to cut the tracks on a rotary so the ground pin was not shared between switch and rotary?
 

Attachments

  • son_of_button_Box_T2_Pins.ino
    4.4 KB · Views: 68
111114944_3426357730732043_8178685667626709334_n.jpgthis seems to be working, cutting the two traces on the back then soldering a jumper to keep the circuit for the switch separate and isolated from the circuit for the rotaries. Bit of a pain though :(
 
That's because you used encoder assemblies rather than just the encoder. Of course you didn't show that in the first post and, indeed, it was miswired.
 
That's because you used encoder assemblies rather than just the encoder. Of course you didn't show that in the first post and, indeed, it was miswired.

Im so stupid, I just went on Amazon and bought rotary encoders. Feel really stupid now. The video tutorial I followed did not point out any difference in the types available, or advise which types to buy..
 
We all stub our toes sometimes. The good news is you got it to work other than maybe spending a little more than you absolutely had to.

But next time you ask for help, including pictures will probably make it go faster.
 
Last edited:
its all part of the learning curve :) Now I have 2 button boxes installed I need to name them differently so I can differentiate them in game when mapping controls - Is that possible? (not really an Arduino/teensy issue but maybe more a Win10 issue)
 
There is nothing wrong with the encoders you've bought (commonly available Keyes KY-040). They have pull-up resistors attached (pull-up to +V) which aren't needed but won't have any detrimental effect as there are internal pulls-up in the Arduino/Teensy. You don't need to make any modifications to use them. You've cut through the +V connection to the resistors, soldered it to one side of the push button and attached the other side of the push button to the centre pin of the toggle switch - why? I assume from the video, they push button on the encoder is not used. Put them back the way they were and have another look at the pin out on the encoders - GND, +V, Switch, DT, CLK - the last two are badly named and are just the connections to each side of the encoder. Ignore the Switch and +V. If you're still confused you can de-solder the encoders from the small PCB and use them as in the video. Your problems are incorrect wiring.
 
Last edited:
It's possible but it looks to me like one side of the switch and the encoder common are connected together. At least a similar one that I have is that way.
 
I can tell you that separating the common gnd has solved the problem since I was getting cross-talk when rotating, and button presses were not registering. Now all buttons & rotations are working properly. The gnd trace was shared between one of the on-off pins and the common for the rotary. Another way as you say would have been to unsolder the whole mechanism from the pcb to use them. The 2 pin sets remain separate then of course.
 
Its all working fine EXCEPT it takes too many revolutions on the rotary to move the knob in the game. Maybe 30:1 ratio at the moment.
Code:
//SON OF BUTTON BOX 
//USE w Teensy2.0
//Tested in WIN10 + DCS World
//AMSTUDIO
//20.8.17

#include <Keypad.h>

#define ENABLE_PULLUPS
#define NUMROTARIES 4
#define NUMBUTTONS 20
#define NUMROWS 4
#define NUMCOLS 5


byte buttons[NUMROWS][NUMCOLS] = {
  {1,2,3,4,5},
  {6,7,8,9,10},
  {11,12,13,14,15},
  {16,17,18,19,20},
};

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

rotariesdef rotaries[NUMROTARIES] {//pins used by rotaries and corresponding button presses activated
  {3,5,21,22,0},
  {4,6,23,24,0},
  {7,9,25,26,0},
  {8,10,27,28 ,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] = {20,19,18,17}; 
byte colPins[NUMCOLS] = {12,13,14,15,16}; 

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

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.button(buttbx.key[i].kchar, 1);
                              break;
                    case RELEASED:
                    case IDLE:
                              Joystick.button(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.button(rotaries[i].ccwchar, 1); delay(30); Joystick.button(rotaries[i].ccwchar, 0);
    };
    if (result == DIR_CW) {
      Joystick.button(rotaries[i].cwchar, 1); delay(30); Joystick.button(rotaries[i].cwchar, 0);
    };
  }
}
Is there a way I can get the resolution down to about 5:1 or 10:1? Im sorry really dont yet have much more than a very basic handle on the programming yet.
 
Status
Not open for further replies.
Back
Top