Ghosting Issue on 9x9 Input Matrix with Diodes

Hello!,

I am working on a project that requires 80 inputs. The switches are standard rocker switches. There will be instances where most of them will be ON at the same time. I am using a Mega 2560 for this project. The Mega is powered using an ethernet board with POE. I have the switches wired up as the following:

Row(arduino pin) 22-----[Diode|>]-----Switch -----[Diode|>]-----Column 23 arduino pin
Row(arduino pin) |--Switch -----[Diode|>]-----Column 25 arduino pin
Row(arduino pin) |--Switch -----[Diode|>]-----Column 27 arduino pin
Row(arduino pin) |--Switch -----[Diode|>]-----Column 29 arduino pin
Row(arduino pin) |--Switch -----[Diode|>]-----Column 31 arduino pin
Row(arduino pin) |--Switch -----[Diode|>]-----Column 33 arduino pin
Row(arduino pin) |--Switch -----[Diode|>]-----Column 35 arduino pin
Row(arduino pin) |--Switch -----[Diode|>]-----Column 37 arduino pin
Row(arduino pin) |--Switch -----[Diode|>]-----Column 37 arduino pin

The commons are tied together at each switch after the diode. Each output has a diode between the switch and the column.

When I turn on the switch at row 22 column 23 (switch 22/23 from now on) it indicates ON, the switch at row 22 column 25 (switch 22/25 from now on) will indicate(oscillate actually) ON and OFF. If i turn ON both switches, they will both indicate they are ON. If I turn OFF switch 22/23, 22/25 will indicate it's ON. I have diodes for every switch and every row base which leads me to believe the "ghosting" is maybe from the code.

Here is the code:

//Input matrix 
int intRows = 9;
int intCols = 9;
int InputRowPins[9]={22,24,26,28,30,32,34,36,38}; //,40,42,44,46,48,50,52}; //array of pins used as output for rows of keypad
int InputColPins[9]={23,25,27,29,31,33,35,37,39}; //,41,43,45,47,49,51,53}; //array of pins used as input for columns of keypad
int InputStat[81]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; //array of pins used as input for columnss of keypad





//--------------------------------------------------------------------Check input matrix ----------------------------------------------//

void CheckInputs(int rowPins[],int colPins[],int keyStat[], int totRows, int totCols){ 


//theRowPins      = the array of pins for the rows
//theColPins      = the array of pins for the cols
//totROWS         = the total of rows
//totCOLS         = the total of columns
//theKeyStat      = the saved status of the keys
//thInputStatusID = the ID of this set of inputs. helps distinguish what input set we are using. Not used. maybe i will, maybe i wont. Who knows? i sure dont, right now.

  //Checks the input matrix for changes
    
    // Re-intialize the row pins. Allows sharing these pins with other hardware.
    for (byte r=0; r<totRows; r++) {
      pinMode(rowPins[r],INPUT_PULLUP);
    }

    //Array position for status changes  
    int theInt = 0;
  
    //loop through the columns and rows
    for (byte c=0; c<totCols; c++) {
      pinMode(colPins[c],OUTPUT);
      digitalWrite(colPins[c], LOW);  // Begin column pulse output.
      for (byte r=0; r<totRows; r++) {
        
        // keypress is active low so invert to high.
        boolean theVal = !digitalRead(rowPins[r]);  
        //Serial.println(String(theVal));
        //check if keys have changed status
        if(keyStat[theInt]!=theVal){
          //update key status
          keyStat[theInt]=theVal;
          //send info to server
          //cmd,group,id,value
          //sendToServer2("IN",theGroupID+"|"+String(theInt)+"|"+String(theVal));
          //sendToServer2("IN","0|"+String(theInt)+"|"+String(theVal));
          sendToServer2("IN",String(theInt)+"|"+String(theVal));
        }
        //Increase the array position
        theInt+=1;
      }
      // Set pin to high impedance input. Effectively ends column pulse.
      digitalWrite(colPins[c],HIGH);
      pinMode(colPins[c],INPUT);
    }

  

  
}// end function

I can't find the issue, whether it is with the wiring or the code. Any help would be greatly appreciated!

Thanks,
Jon

Could you post a schematic please? Hand drawn is ok. Can't quite understand your text attempt to describe the circuit. Seems to be extra diodes there? Should only need one in series with each switch. Sounds from your description there may be floating inputs.

Also this

      digitalWrite(colPins[c],HIGH);
      pinMode(colPins[c],INPUT);

may be equivalent to INPUT_PULLUP, I'm not sure. Maybe try not setting the pin HIGH, just INPUT.

PaulRB:
Also this

      digitalWrite(colPins[c],HIGH);

pinMode(colPins[c],INPUT);



*may* be equivalent to INPUT_PULLUP, I'm not sure. Maybe try not setting the pin HIGH, just INPUT.

Well, it should be equivalent, but I am not sure whether the pinMode code has been "bodgied" in the later IDE versions.
Clearly, setting INPUT_PULLUP both sets the pin as an input and writes the output register HIGH, so it affects both registers. Whether setting INPUT should possibly affect the output register is arguable.

In any case, the code is simply wrong because it may if the pin is already set as an output, briefly set it HIGH with "full force" against a possible ground such as from a switch. Obviously it should always be:

     pinMode(colPins[c],INPUT);
      digitalWrite(colPins[c],HIGH);

Which will safely implement INPUT_PULLUP in any IDE version.

Attached is the schematic. I gave up filling out the rows by row 3 but you get the idea of how this is wired up. Each row/column number corresponds to an arduino pin.

How would I be able to solve any floating input issues?

I will invert the code lines test it out and also comment out the digitalwrite HIGH line and see how it goes.

Thank you guys for taking the time out to take a look at this for me. I greatly appreciate it!

Oh, I am using the glass germanium diodes 1N34A, not sure if that poses an issue or not.

Schematic.pdf (302 KB)

How would I be able to solve any floating input issues?

By not letting them float! Let's take a look at your schematic.

The 1N34A should be fine, but I don't think you've "got it" about where to place them. They should be in series with each switch, not in line with the columns. Like this:


You don't need the pull-up resistors shown because you are using the internal ones.

JonKrzecki:
Oh, I am using the glass germanium diodes 1N34A, not sure if that poses an issue or not.

What a peculiar thing to do ! :astonished:

Probably not an issue, though they have significant reverse leakage - possibly equivalent to about 330k. Not something one would choose without a very specific reason!

I do apologize for the terrible schematic I provided! The schematic you provide is how I have them wired up but replace the the resistors in your schematic with a diode. Probably pointless to have them there.

The diodes are what I had on hand and they seemed popular on a lot of the development sites and they were really easy to get! Not sure if they are causing the issue. Would you recommend any other diode? I'd hate to rewire 80 some ring terminals but if it fixes it, then it would be worth it.

I have flipped the lines of code as suggested and that made matters worse. When I turn on switch 1, it turns on 1 and 2. turning on switch 3 would turn on 3 and 4. I even removed switch 2 from the matrix by physically unwiring it and it still showed ON. So I put it back the way it was and added a delay(2) between the lines of code, which helped.

While I was monkeying around with it, I added a pull up resistor on one of the columns to the 5VDC on the arduino and that made the ghosting go away for that column.

So I have no clue why it is behaving this way or if this is the right way to go or if i should add pull up resistors for all of them or change out the diodes or keep digging into the issue and it's frustrating and thank you guys SO much for all your help!

So at this point, I don't know which way to go with this.

Those extra diodes probably aren't doing anything, as you said, but try removing them anyway. You said adding an external pull-up resistor helped, so try adding those to all columns. Try 10K or 4K7.

If that doesn't fix the problem, post an updated schematic (hand-drawn is ok if drawn accurately this time) and updated code.

So I have added the 10k resistors on the columns and it seems to have stabilized the issue yesterday! Attached is the current schematic.

For the code, I added the delay(2) at the end of the pulsing.

//Input matrix
int intRows = 9;
int intCols = 9;
int InputRowPins[9]={22,24,26,28,30,32,34,36,38}; //,40,42,44,46,48,50,52}; //array of pins used as output for rows of keypad
int InputColPins[9]={23,25,27,29,31,33,35,37,39}; //,41,43,45,47,49,51,53}; //array of pins used as input for columns of keypad
int InputStat[81]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; //array of pins used as input for columnss of keypad





//--------------------------------------------------------------------Check input matrix ----------------------------------------------//

void CheckInputs(int rowPins[],int colPins[],int keyStat[], int totRows, int totCols){


//theRowPins      = the array of pins for the rows
//theColPins      = the array of pins for the cols
//totROWS         = the total of rows
//totCOLS         = the total of columns
//theKeyStat      = the saved status of the keys
//thInputStatusID = the ID of this set of inputs. helps distinguish what input set we are using. Not used. maybe i will, maybe i wont. Who knows? i sure dont, right now.

  //Checks the input matrix for changes
   
    // Re-intialize the row pins. Allows sharing these pins with other hardware.
    for (byte r=0; r<totRows; r++) {
      pinMode(rowPins[r],INPUT_PULLUP);
    }

    //Array position for status changes 
    int theInt = 0;
 
    //loop through the columns and rows
    for (byte c=0; c<totCols; c++) {
      pinMode(colPins[c],OUTPUT);
      digitalWrite(colPins[c], LOW);  // Begin column pulse output.
      for (byte r=0; r<totRows; r++) {
       
        // keypress is active low so invert to high.
        boolean theVal = !digitalRead(rowPins[r]); 
        //Serial.println(String(theVal));
        //check if keys have changed status
        if(keyStat[theInt]!=theVal){
          //update key status
          keyStat[theInt]=theVal;
          //send info to server
          //cmd,group,id,value
          //sendToServer2("IN",theGroupID+"|"+String(theInt)+"|"+String(theVal));
          //sendToServer2("IN","0|"+String(theInt)+"|"+String(theVal));
          sendToServer2("IN",String(theInt)+"|"+String(theVal));
        }
        //Increase the array position
        theInt+=1;
      }
      // Set pin to high impedance input. Effectively ends column pulse.
      digitalWrite(colPins[c],HIGH);
      delay(2);
      pinMode(colPins[c],INPUT);
      delay(2);
    }

 

 
}// end function

Thank you so much for your help! If I have any more issues, I know where to go for helpful assistance.

You need to get rid of the diodes between the 10k resistors and the matrix proper.

They are not too likely to cause harm, but if they did in any way make the matrix work when it did not without them, it means you have made a blunder in the wiring and it is not actually as shown, :astonished: