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

Thread: Joystick using key matrix

  1. #1
    Junior Member
    Join Date
    Jul 2018
    Posts
    5

    Joystick using key matrix

    I found another project where someone tried to use a key matrix as joystick buttons, but he wasn't able to clear the keys after the press. I thought the case statement was a little heavy handed as well, so I went with a for loop, and haven't successfully gotten the system to recognize a keypress. I could wire these up to pins, but I've done two, which meant soldering about 150 wires with dupont connectors on the other end, and thought using a 5x8 matrix would be much, much easier this time around...

    Current, non-working code. I'm new to this (despite having bought five 3.6s in the last two weeks to get this project done). Two of the boxen have been built the hard way, three to go.
    Code:
      #include <Keypad.h>
    
      const byte ROWS = 4; //four rows
      const byte COLS = 4; //four columns
    
      byte rowPins[ROWS] = {0, 1, 2, 3}; //connect to the row pinouts of the keypad
      byte colPins[COLS] = {29,30,31,32}; //connect to the column pinouts of the keypad
    
      char keyMap[ROWS][COLS] = {
        {1,2,3,4},
        {5,6,7,8},
        {9,10,11,12},
        {13,14,15,16}
      };
    
      Keypad kpd = Keypad( makeKeymap(keyMap), rowPins, colPins, ROWS, COLS); 
    
    void setup() {
        Joystick.useManualSend(true);
    }
    
    void loop() {
    
      for (int i=0; i<LIST_MAX; i++)
      {
        if ( kpd.key[i].stateChanged )
        {
          if ( kpd.key[i].kstate == PRESSED )
          {
              Joystick.button(i+1, 1);
          } else {
              Joystick.button(i+1, 0);
          }
        }
      }
      Joystick.send_now();
      delay(5);
    }

  2. #2
    Junior Member
    Join Date
    Jul 2018
    Posts
    5
    Bwahaha. Got it. Actually, thanks for leaving this alone until I could take another swing; it's much more satisfying to figure it out. For my next trick...

    <edit>
    Realized the switch would auto-release after a moment, which is not what should happen. Edited the beefy part of the if to account for a HOLD state, and released the button on release. I'm assuming IDLE is not pressed. In any event, the button will stay on as long as it is held now.
    </edit>
    Working code:

    Code:
      #include <Keypad.h>
    
      const byte ROWS = 4; //four rows
      const byte COLS = 4; //four columns
    
      byte rowPins[ROWS] = {0, 1, 2, 3}; //connect to the row pinouts of the keypad
      byte colPins[COLS] = {29,30,31,32}; //connect to the column pinouts of the keypad
    
      char keyMap[ROWS][COLS] = {
        {1,2,3,4},
        {5,6,7,8},
        {9,10,11,12},
        {13,14,15,16}
      };
    
      Keypad kpd = Keypad( makeKeymap(keyMap), rowPins, colPins, ROWS, COLS); 
    
    void setup() {
        Joystick.useManualSend(true);
    }
    
    void loop() {
      if ( kpd.getKeys() )
      {
        for (int i=0; i<LIST_MAX; i++)
        {
          if ( kpd.key[i].stateChanged )
          {
            if ( kpd.key[i].kstate == PRESSED || kpd.key[i].kstate == HOLD)
            {
                Joystick.button(kpd.key[i].kchar, 1);
            } else if ( kpd.key[i].kstate == RELEASED ){
                Joystick.button(kpd.key[i].kchar, 0);
            }
            Joystick.send_now();
          }
        }
      }
      delay(5);
    }
    Last edited by Random; 07-04-2018 at 07:42 PM. Reason: Code change

  3. #3
    Junior Member
    Join Date
    Aug 2019
    Posts
    4

    Joystick using key matrix

    Quote Originally Posted by Random View Post
    Bwahaha. Got it. Actually, thanks for leaving this alone until I could take another swing; it's much more satisfying to figure it out. For my next trick...

    <edit>
    Realized the switch would auto-release after a moment, which is not what should happen. Edited the beefy part of the if to account for a HOLD state, and released the button on release. I'm assuming IDLE is not pressed. In any event, the button will stay on as long as it is held now.
    </edit>
    Working code:

    Code:
      #include <Keypad.h>
    
      const byte ROWS = 4; //four rows
      const byte COLS = 4; //four columns
    
      byte rowPins[ROWS] = {0, 1, 2, 3}; //connect to the row pinouts of the keypad
      byte colPins[COLS] = {29,30,31,32}; //connect to the column pinouts of the keypad
    
      char keyMap[ROWS][COLS] = {
        {1,2,3,4},
        {5,6,7,8},
        {9,10,11,12},
        {13,14,15,16}
      };
    
      Keypad kpd = Keypad( makeKeymap(keyMap), rowPins, colPins, ROWS, COLS); 
    
    void setup() {
        Joystick.useManualSend(true);
    }
    
    void loop() {
      if ( kpd.getKeys() )
      {
        for (int i=0; i<LIST_MAX; i++)
        {
          if ( kpd.key[i].stateChanged )
          {
            if ( kpd.key[i].kstate == PRESSED || kpd.key[i].kstate == HOLD)
            {
                Joystick.button(kpd.key[i].kchar, 1);
            } else if ( kpd.key[i].kstate == RELEASED ){
                Joystick.button(kpd.key[i].kchar, 0);
            }
            Joystick.send_now();
          }
        }
      }
      delay(5);
    }
    Thank you so much for posting this! This is exactly what I was looking for and it worked flawlessly! I was previously using a keyboard matrix to map a key to each button, but that seemed to have issues with multiple buttons being pressed, or single state switches holding in a 'HIGH' state. Now all I've left to do is wire in the potentiometers and find some code for that!

  4. #4
    Junior Member
    Join Date
    Jul 2018
    Posts
    5
    Quote Originally Posted by silco69 View Post
    Thank you so much for posting this! This is exactly what I was looking for and it worked flawlessly! I was previously using a keyboard matrix to map a key to each button, but that seemed to have issues with multiple buttons being pressed, or single state switches holding in a 'HIGH' state. Now all I've left to do is wire in the potentiometers and find some code for that!
    I'm using potentiometers as axis, rotary encoders as switches, mode buttons to allow a switch matrix to be re-used multiple times....you name it. If there's something else you need let me know.

  5. #5
    Junior Member
    Join Date
    Aug 2019
    Posts
    4
    Yeah I'm actually having an issue with either Windows or the program (Warthunder) reading more than 3 of the 8 analogue axis. I can definately get one of them to work at a time but not the minimum of 6 the Teensy Joystick example has laid out. Any advice please?

  6. #6
    Junior Member
    Join Date
    Jul 2018
    Posts
    5
    That's going to be the game. I've gotten something insane to work if you look at the direct input, but never more than 6 in DCS. I get past it by having an obsessively ridiculous amount of inputs, with only 6 axis per controller. Once the full suite is put together there will be 5 3.6s and 2 LCs to handle all of it. That's part of the reason I use rotary encoders; there are functions you can manage with a switch, but not an axis. With a rotary encoder you turn it one way and one switch is pushed discreetly per 'click' of the encoder, you turn it the other way and a different switch is repeatedly pressed. That fakes axis control quite nicely. I sliced this out of some test code; it should be reasonably complete.

    Code:
    #define ENC1 1
    #define ENC2 2
    
    
    Encoder myEnc(ENC1, ENC2);
    
    void setup() {
      pinMode(ENC1,INPUT_PULLUP);
      pinMode(ENC2,INPUT_PULLUP);
    }
    
    void loop() {
      long newPos = myEnc.read();
      if (newPos != position) {
    	if (newPos > position) {
    	  Joystick.button(1,1);
    	} else {
    	  Joystick.button(2,1);
    	}
    	position = newPos;
      } else
      {
    	Joystick.button(1,0);
    	Joystick.button(2,0);
      }
      delay(5);
    }

  7. #7
    Junior Member
    Join Date
    Aug 2019
    Posts
    4

    Joystick using key matrix

    DCS is will be my endgame. How many buttons/axis do you need for that? I've currently got my 38 custom button and 8 axis (6 working) running off the teensy, with a Thrustmaster T1600m + Hotas + Pedals and Saitek Multi Panel/Switch Panel and Radio Panels

  8. #8
    Junior Member
    Join Date
    Jul 2018
    Posts
    5
    Quote Originally Posted by silco69 View Post
    DCS is will be my endgame. How many buttons/axis do you need for that? I've currently got my 38 custom button and 8 axis (6 working) running off the teensy, with a Thrustmaster T1600m + Hotas + Pedals and Saitek Multi Panel/Switch Panel and Radio Panels
    How obsessive are you?

    I have hundreds of switches (probably close to 300), not counting discrete switches in matrices, 40-some axis, rotary encoders, crosswind pedals, Virpil stick and base, TM throttle...did I mention it will take 5 Teensy 3.6 and two Teensy LC controllers to drive it all? Then there's the VFx panel (F-14) in progress...six Teensy 3.6s. When the F-16 comes out I should be able to map everything without any new panels.

    There are multiple aircraft I fly, and the controls don't always map well from one to the other so they all have switches. In a vibrating aircraft it wouldn't work, in my office at home I don't have to look. This is still a work in progress; still have a right console, three MFDs (with LCD backing), UFC, and another panel to do. I have almost as much fun playing with this as flying, so the question then becomes which is the object and which is the solution?

    There are other teensy projects in the wings once this is done, but I had to come up with a sizeable chunk of the code for all this on my own. The boards, at least for this application, aren't necessarily brimming with people eager to help, but that's just as well.

    Every controller has its own name, DCS calls them all the same thing with a UUID. It's a pain in the butt to map things.

Posting Permissions

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