Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 14 of 14

Thread: rotary encoder matrix and push-buttons

  1. #1

    rotary encoder matrix and push-buttons

    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?

  2. #2
    Senior Member
    Join Date
    Apr 2019
    Posts
    111
    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.

  3. #3
    Senior Member
    Join Date
    Mar 2016
    Posts
    242
    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.

  4. #4
    Quote Originally Posted by PhilB View Post
    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?
    Attached Files Attached Files

  5. #5
    Click image for larger version. 

Name:	111114944_3426357730732043_8178685667626709334_n.jpg 
Views:	25 
Size:	97.0 KB 
ID:	21102this 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

  6. #6
    Senior Member
    Join Date
    Mar 2016
    Posts
    242
    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.

  7. #7
    Quote Originally Posted by PhilB View Post
    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..

  8. #8
    Senior Member
    Join Date
    Mar 2016
    Posts
    242
    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 by PhilB; 07-23-2020 at 10:05 PM.

  9. #9
    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)

  10. #10
    Senior Member
    Join Date
    Apr 2019
    Posts
    111
    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 by UHF; 07-24-2020 at 03:18 AM.

  11. #11
    Senior Member
    Join Date
    Mar 2016
    Posts
    242
    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.

  12. #12
    Senior Member
    Join Date
    Apr 2019
    Posts
    111
    Yes, GND as one would expect.

  13. #13
    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.

  14. #14
    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.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •