Which direction to put the diodes in a matrix?

Status
Not open for further replies.

auch_enne

Member
Looking at the cicruit drawings I find online, in most of them they point away from the button. But on https://learn.sparkfun.com/tutorials/button-pad-hookup-guide/background they point towards the button.

I did my head in yesterday try to get a joystickbutton matrix going with Bounce.h, but could not get it to work. Now I switched to https://forum.pjrc.com/threads/53015-Joystick-using-key-matrix?highlight=keypad+button+matrix and the buttons work. But if I put in the diodes it only works when I face them toward the button, from the row toward the column.

Is this because some circuits work with a HIGH signal on button closed, and with the pullup resistor the work with a LOW signal when the button is closed?


Ow the matter of build in pullup resistor, I ordered some resistors, but I guess I don't need them? Is there and advantage for using the build in or external resistors?



My apologize for the n00b questions, did my best to google and search before I even ordered the parts but even a simple project as a button matrix is busting my spherical objects..

(dreading the next step, incorporating the encoders)
 
Here is the full code, it's for a button box for iRacing. Supports 6 encoders, the click function of the encoders is counted as a button. With 14 other switches, some doublethrow, you get a total of 20 buttons.

So that is the max of 32 button inputs on the teensy lc default joystick. But iRacing can read the hat function of the teensy joystick as a button also, so 4 more buttons there :) For a total of 36 game inputs on 25 pins needed of the teensy. Not using pin 13 (LED Pin), pin 17 (5v output only) and 26. The encoders have both their pins connected to an interrupt pin for maximum performance. And I replaced the delay's in the code I found for milli sec timers to not stop the program on each "delay".

If you test the encoders with joy.cpl you might not see the them light up because they respond so quick, but the work perfectly fine. (With a delay there you can see them clearly light up, wonder why my milli sec solution doesn't properly show them working, but they do respond quicker now.)

If you do use the code be sure to check the pin numbers are change them to what you want. If there is trouble ask me I can add more comments. I can't take credit for the code though, it's just hacked together from sources on the forum.

Ow and I have no clue how to put the diodes to prevent ghosting yet, nor how to get windows10 to forget the USB device name so it will take my own name added in usb_private.h :D

(if any one has improvements on the code I'll be glad to hear them, just a noob willing to learn)

Code:
  #include <Keypad.h>
  #include <Encoder.h>

  int period1 = 10;
  int period2 = 35;
  unsigned long time_now1 = 0;
  unsigned long time_now2 = 0;
  unsigned long time_now3 = 0;
  unsigned long time_now4 = 0;
  unsigned long time_now5 = 0;
  unsigned long time_now6 = 0;
  unsigned long time_now7 = 0;
  unsigned long time_now8 = 0;
  unsigned long time_now9 = 0;
  unsigned long time_now10 = 0;
  unsigned long time_now11 = 0;
  unsigned long time_now12 = 0;
  unsigned long time_now13 = 0;
  

  const byte ROWS = 5; //five rows
  const byte COLS = 4; //four columns

  byte rowPins[ROWS] = {15, 16, 17, 18, 19}; //connect to the row pinouts of the keypad
  byte colPins[COLS] = {20, 21, 22, 23}; //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},
    {17,18,19,20}
  };

  Keypad kpd = Keypad( makeKeymap(keyMap), rowPins, colPins, ROWS, COLS);
  
  Encoder volumeEncoder   (2, 3);
  Encoder fuelmapEncoder  (4, 5);
  Encoder brakebiasEncoder(6, 7);
  Encoder absEncoder      (8, 9);
  Encoder front_arbEncoder(10, 11);
  Encoder rear_arbEncoder (12, 14);

  long positionVolume     = -999;
  long positionFuelmap    = -999;
  long positionBrakebias  = -999;
  long positionAbs        = -999;
  long positionFront_arb  = -999;
  long positionRear_arb   = -999;



void setup() {
      // Hat switch buttons
  pinMode(0, INPUT_PULLUP);
  pinMode(1, INPUT_PULLUP);
  pinMode(24, INPUT_PULLUP);
  pinMode(25, INPUT_PULLUP);
}

void loop() {

  if(millis() >= time_now1 + period1){
        time_now1 += period1;
    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();
        }
      }
    }
  

  
      long newVolume = volumeEncoder.read();
      if (newVolume > positionVolume) {
        positionVolume = newVolume;
        Joystick.button(21, 1);
        if(millis() >= time_now2 + period2){
          time_now2 += period2;
          Joystick.button(21, 0);
        }
      }
      if (newVolume < positionVolume) {
        positionVolume = newVolume;
        Joystick.button(22, 1);
          if(millis() >= time_now3 + period2){
          time_now3 += period2;
          Joystick.button(22, 0);
          }
      }
   
   
      long newFuelmap = fuelmapEncoder.read();
      if (newFuelmap > positionFuelmap) {
        positionFuelmap = newFuelmap;
        Joystick.button(23, 1);
        if(millis() >= time_now4 + period2){
          time_now4 += period2;
          Joystick.button(23, 0);
        }
      }
      if (newFuelmap < positionFuelmap) {
        positionFuelmap = newFuelmap;
        Joystick.button(24, 1);
          if(millis() >= time_now5 + period2){
          time_now5 += period2;
          Joystick.button(24, 0);
          }
      }
   
      long newBrakebias = brakebiasEncoder.read();
      if (newBrakebias > positionBrakebias) {
        positionBrakebias = newBrakebias;
        Joystick.button(25, 1);
        if(millis() >= time_now6 + period2){
          time_now6 += period2;
          Joystick.button(25, 0);
        }
      }
      if (newBrakebias < positionBrakebias) {
        positionBrakebias = newBrakebias;
        Joystick.button(26, 1);
          if(millis() >= time_now7 + period2){
          time_now7 += period2;
          Joystick.button(26, 0);
          }
      }
   
      long newAbs = absEncoder.read();
      if (newAbs > positionAbs) {
        positionAbs = newAbs;
        Joystick.button(27, 1);
        if(millis() >= time_now8 + period2){
          time_now8 += period2;
          Joystick.button(27, 0);
        }
      }
      if (newAbs < positionAbs) {
        positionAbs = newAbs;
        Joystick.button(28, 1);
          if(millis() >= time_now9 + period2){
          time_now9 += period2;
          Joystick.button(28, 0);
          }
      }
   
      long newFront_arb = front_arbEncoder.read();
      if (newFront_arb > positionFront_arb) {
        positionFront_arb = newFront_arb;
        Joystick.button(29, 1);
        if(millis() >= time_now10 + period2){
          time_now10 += period2;
          Joystick.button(29, 0);
        }
      }
      if (newFront_arb < positionFront_arb) {
        positionFront_arb = newFront_arb;
        Joystick.button(30, 1);
          if(millis() >= time_now11 + period2){
          time_now12 += period2;
          Joystick.button(30, 0);
          }
      }

      long newRear_arb = rear_arbEncoder.read();
      if (newRear_arb > positionRear_arb) {
        positionRear_arb = newRear_arb;
        Joystick.button(31, 1);
        if(millis() >= time_now12 + period2){
          time_now12 += period2;
          Joystick.button(31, 0);
        }
      }
      if (newRear_arb < positionRear_arb) {
        positionRear_arb = newRear_arb;
        Joystick.button(32, 1);
          if(millis() >= time_now13 + period2){
          time_now13 += period2;
          Joystick.button(32, 0);
          }
      
      }

        int angle =-1;//no angle input
        if (digitalRead(0)==LOW) angle =0;
        if (digitalRead(1)==LOW) angle =90;
        if (digitalRead(24)==LOW) angle =180;
        if (digitalRead(25)==LOW) angle =270;
        Joystick.hat(angle);
  }                      
}
 
Just for the sake of somebody else finding this thread on wanting info :

The Diode should face from the Row toward the Column, if the diode faces toward or away from the button doesn't seem to matter. It does matter which pin you connect to it depending on if it face toward or away from the button.

I'm going to solder the diode on to one of the pins of each button. The black ring indicating cathode side will be pointing away from the button, so on the side with the diode attached I will connect the column lines, running to the column pins on the teensy. The other side of the buttons will be connected to the row pins.
 
Hi. Hope you have figured out the diode symbol by now.

You asked - in post #1 - which way around a diode should be soldered. I confess that the symbol is confusing. But there are clues to "which way around" if you look carefully. Take the diagram that you first referenced for Sparkfun. I'm looking at the first "schematic" where it says "OP3116-080".

Notice that the diode symbol is pointing in exactly the same direction as the arrows on two transistors - one for the column (PNP type such as Q23) and one for the row (NPN type such as Q19). What I mean by this is follow the direct of "conventional current" along a wire path (which is from positive to negative). Start at the Vcc point, which is that upward pointing triangle just to the left of the wording "Q23". Thats obviously positive. So to follow conventional (not electrons) current flow, it would flow into the emitter of the Q23 PNP (and in the direction of that emitter arrow), then out of its collector along to the matrix pin number to pin 28 and pin 9, then through the DIODE ARROW, then towards matrix Diode 1 (in the same arrow direction), then out of the matrix through pins 1 and 20, then through R60, then into the collector of Q19, then out through the emitter of Q19, and finally to ground (which is negative with respect to Vcc).

Hope you can see the logic here. Conventional current flow follows the arrows in either a diode symbol or a transistor symbol.

Now, as you point out in post #3, the "bar" in the diode symbol is the CATHODE. And that end is where there is a "ring marking" physically on the diode itself. So that end physically should agree with the "bar" position in the wiring. Then the diode will be conducting.

Hope this explanation helps.

True "electron current" actually flows in the opposite direct to conventional current. But in those early days of experiments on electricity, they had to make a decision on current flow - and they got it a.a.f.
 
Last edited:
(I am not ashamed to admit that I use K to remind me which side is the cathode, and A to remind me which side is the anode, in a diode or a LED.)

(I haven't found a good one for polarity yet. The best I've come up with is "Anode enters, Cathode leaves", chanted in Max Max Thunderdome style. The second-best is drawing a diode symbol.)
 
In dutch, knap, is handsome or smart. Kathode Negative, Anode Positive. Is something I saw somewhere while researching.

Got the code done (I hope), the funky switch gave me some trouble. Encoder + 4 directions + push button in one. Tomorrow gone wire it all up and hope for the best ;)
 
Status
Not open for further replies.
Back
Top