8 Replies Latest reply on Nov 1, 2017 7:55 PM by obulorn

    Help with Scan code for 4x4 Multiplex keypad with 74hc595/74hc165 Shift Register

    obulorn

      Helo,

      My final aim is to do an 8x8 keypad, presently I have 4x4 keypad available,so am trying out with that. Am using Arduino Uno R3 compatible. My setup is as in the attached: My problem is how to detect the column that went low on key press as to determined the key. Presently any key on Col 0 returns 240; Col1 returns 232; etc (dont know if that is ok. )Please help.

      4X4 matrix Keypad with 74hc595 and 74hc165 shift Register

      Am coding with visual studio 2015 cSharp +Visual Micro My code is as follow:

      const int kbdRows = 4;

      const int kbdCols = 4;

       

      int LatchIn = 3; //165 pin1

      int ClockPin = 5; // 595 pin11 & 165 pin2

      int DataIn = 2; //165 pin9

      int LatchOut = 6; // 595 pin12

      int DataOut = 7; //595 pin14

       

      int led = 7;

      byte mask = 0x80;

      byte lastmask = 0x10;

      byte  incoming=0 ;

      byte dataOuttest;

      byte dataIntest;

       

      int PinState = 0;

       

      char keys[kbdRows][kbdCols] =

      {

          { '1','2','3','4' },

          { '5','6','7','8' },

          { '9','0','A','B' },

          { 'C','D','E','F' }

      };

       

       

      byte KeyDown()

      {

          //595 Here

         

          for (int row  = 0; row < kbdRows; row++)

          {

             

                      digitalWrite(ClockPin, LOW);

                      delayMicroseconds(5);

                      digitalWrite(LatchOut, LOW);//

       

                      shiftOut(DataOut, ClockPin, LSBFIRST, mask);

                      digitalWrite(LatchOut, HIGH);//

                      digitalWrite(ClockPin, HIGH);

                     

                      delay(100);

       

                      Serial.println("  ");

                      Serial.print("Row: "); // here was to test for Data Shift Out

                      Serial.print(row);

       

                      Serial.print(" ");

       

                      Serial.print("Mask: ");

                      Serial.println(mask);

                      Serial.println("  ");

                      Serial.println(" ");

                      delay(100);

       

         

          //165 Here

             

                                      

          for (int col = 0; col < kbdCols; col++)

       

          {

                   digitalWrite(ClockPin, LOW);

             

                      digitalWrite(LatchIn, LOW);

                      delayMicroseconds(5);

                      digitalWrite(LatchIn, HIGH);

             

                      incoming = shiftIn(DataIn, ClockPin, LSBFIRST);

                     digitalWrite(ClockPin, HIGH);

       

       

              Serial.print("Col: ");

              Serial.println(col);

              Serial.print("InComing: ");

              Serial.println(incoming);

       

             

          /////if(incoming & mask)/////////////////

          ///{

              /// byte keypress = keys[row][col];

              /// Serial.print("KeyPRESS: ");

          ///    Serial.println(keypress); ////////////// here is my probs, dont know how to return the pressed key with my setup

       

       

          /// }// end of if

             

             

              delay(600);

       

          } // end of col

          if (mask == lastmask)

              mask = 0x80;

          else

          mask = mask >> 1;

       

          } // row end

       

      }

       

       

       

       

      void setup()

      {

       

        /* add setup code here */

          pinMode(ClockPin, OUTPUT);

          pinMode(DataOut, OUTPUT);

          pinMode(DataIn, INPUT);

          pinMode(LatchOut, OUTPUT);

          pinMode(LatchIn, OUTPUT);

       

          digitalWrite(LatchOut, LOW);

         

          digitalWrite(ClockPin, LOW);

          Serial.begin(9600);

       

          digitalWrite(led, HIGH);

         

      }

       

      void loop()

      {

       

        /* add main program code here */

       

      void setup()

      {

       

        /* add setup code here */

          pinMode(ClockPin, OUTPUT);

          pinMode(DataOut, OUTPUT);

          pinMode(DataIn, INPUT);

          pinMode(LatchOut, OUTPUT);

          pinMode(LatchIn, OUTPUT);

       

          digitalWrite(LatchOut, LOW);

         

          digitalWrite(ClockPin, LOW);

          Serial.begin(9600);

       

          digitalWrite(led, HIGH);

         

      }

       

       

      void loop()

      {

       

        /* add main program code here */

       

       

        KeyDown();

        delay(300);

       

      }

        • Re: Help with Scan code for 4x4 Multiplex keypad with 74hc595/74hc165 Shift Register
          shabaz

          Hi Obulor,

           

          Assuming the rest of the code is functioning, then in your KeyDown function you should have a line somewhere that says

          return(keypress);

          That line will make the function complete, and return control back to your function that called it in the first place, i.e. loop() function.

           

          Your loop() function is currently just calling KeyDown, but not making use of any result.

          It should declare a variable of some name, e.g. pressed_char, and the put the return value into it:

          byte pressed_char;
          pressed_char=KeyDown();

           

          To learn such things, this is described in books on C. It is highly recommended to read up on this, or try some online resources on C programming.

          C is simple (in principle) that you can learn a lot just by spending a couple of days reading a book.  Functions and return values will be covered in any book on C.

          1 of 1 people found this helpful
            • Re: Help with Scan code for 4x4 Multiplex keypad with 74hc595/74hc165 Shift Register
              obulorn

              Hi shabaz,

              Many thanks for your time. I understand the point you raised, if you look through the code, the area I commented out, should handle that, but for now, the function is displaying it on the screen. The way  it run now is that, it display (or returns) all the keys in the array, one after another even without any keypress. I believe there should be an if condition that will make the condition display (or return) ONLY the pressed key. The IF condition is what I think should solve my problem. Please help.

                • Re: Help with Scan code for 4x4 Multiplex keypad with 74hc595/74hc165 Shift Register
                  shabaz

                  Hi Obulor,

                   

                  The line

                  /////if(incoming & mask)

                  should not have /// at the beginning, this is commenting it out.

                  Nor should the subsequent lines have the //.

                  Anyway that line

                  if(incoming & mask)

                  (i.e. without the //) means that you're checking for the signal to be high.

                  But, your circuit pulls all the columns to logic high by default.

                   

                  You need the opposite logic, i.e. the row lines to all be high except one, and

                  then test for low.

                  To do that, change:

                  shiftOut(DataOut, ClockPin, LSBFIRST, mask);

                  to

                  shiftOut(DataOut, ClockPin, LSBFIRST, mask^255);

                   

                  and change

                  if(incoming & mask)

                  to

                  if((incoming & mask)==0)

                   

                  It might work then. I've not examined it in detail due to time availability. But to troubleshoot, closely examine what you're setting on the rows and what you're expecting to read in as a result.

                  2 of 2 people found this helpful
              • Re: Help with Scan code for 4x4 Multiplex keypad with 74hc595/74hc165 Shift Register
                obulorn

                Hi shabaz,

                 

                I understand the commenting part, I did that in the post to emphasize the area I suspect the error was coming from .I will try your suggestion out and get back. Thanks again.

                  • Re: Help with Scan code for 4x4 Multiplex keypad with 74hc595/74hc165 Shift Register
                    obulorn

                    Hi shabaz,

                    Ok, i made the corrections you pointed out, but here is what i don't understand, assuming :

                     

                    incoming =240 (ie 11110000) and mask = 127(ie 01111111); my understanding of  bitmask  is that:

                    11110000

                    and

                    01111111

                    equals

                    01110000 (ie 112) ===> how does this translate or equals zero?

                    meanwhile from your earlier post i now modified my code; my mask is now in array like so:

                     

                    byte Mymask[4] = { 0x7f,0xbf,0xdf,0xef };

                    byte Mymask[4] = { 0x7f,0xbf,0xdf,0xef };
                      • Re: Help with Scan code for 4x4 Multiplex keypad with 74hc595/74hc165 Shift Register
                        shabaz

                        obulorn  wrote:

                         

                        Hi shabaz,

                        Ok, i made the corrections you pointed out, but here is what i don't understand, assuming :

                         

                        incoming =240 (ie 11110000) and mask = 127(ie 01111111);...

                        byte Mymask[4] = { 0x7f,0xbf,0xdf,0xef };

                        Where did you get this from though? It isn't in your code.

                        You've got mask initially set to 0x80 hex, which is 128 decimal, not 127. And 128 decimal is 1000 0000 binary, not 0111 1111

                        At no point in your code does it equal 127 either.

                        So, I had to perform the inversion. There are many ways of achieving the desired outcome of course.

                         

                        Now if you change the existing code in different ways (e.g. decide to set mask to 0x7f instead of 0x80) then other bits of code would need to change too, because your right-shift operation further down the code

                        (the line that is "mask = mask >> 1;") is not going to pad the left side of the bits in the mask with '1'. It will pad with zero.

                        The inversion operation that I did would have correctly handled the situation and did not require setting the mask to 0x7f.

                        Anyway, it really is up to you how you wish to achieve the result, there are many ways to skin the cat.

                          • Re: Help with Scan code for 4x4 Multiplex keypad with 74hc595/74hc165 Shift Register
                            obulorn

                            Hi shabaz,

                            Again many thanks. Yes I modified my code, the portions that handle the mask; here is the modified version:

                             

                            const int kbdRows = 4;
                            const int kbdCols = 4;
                            
                            int LatchIn = 3; //165 pin1
                            int ClockPin = 5; // 595 pin11 & 165 pin2
                            int DataIn = 2; //165 pin9
                            int LatchOut = 6; // 595 pin12
                            int DataOut = 7; //595 pin14
                            
                            
                            
                            byte Mymask[4] = { 0x7f,0xbf,0xdf,0xef };
                            
                            byte  incoming=0 ;
                            byte dataOuttest;
                            byte dataIntest;
                            
                            char keys[kbdRows][kbdCols] =
                            {
                                { '1','2','3','4' },
                                { '5','6','7','8' },
                                { '9','0','A','B' },
                                { 'C','D','E','F' }
                            };
                            
                            
                            byte KeyDown()
                            {
                                //595 Here
                                
                                for (int row  = 0; row < kbdRows; row++)
                                {
                                    
                                            digitalWrite(ClockPin, HIGH);
                                            delayMicroseconds(5);
                                            digitalWrite(LatchOut, LOW);//
                            
                                            shiftOut(DataOut, ClockPin, LSBFIRST, Mymask[row]);
                                            digitalWrite(LatchOut, HIGH);//
                                            digitalWrite(ClockPin, LOW);
                                            
                                            delayMicroseconds(200);
                            
                                            Serial.println("  ");
                                            Serial.print("Row: "); // here was to test for Data Shift Out
                                            Serial.print(row);
                            
                                            Serial.print(" ");
                            
                                            Serial.print("MyMask: "); 
                                            Serial.println(Mymask[row]);
                                            Serial.println("  ");
                                            Serial.println(" ");
                                            delayMicroseconds(200);
                            
                                
                                //165 Here
                                    
                                                             
                                for (int col = 0; col < kbdCols; col++)
                            
                                {
                                         digitalWrite(ClockPin, LOW);
                                    
                                            digitalWrite(LatchIn, LOW);
                                            delayMicroseconds(5);
                                            digitalWrite(LatchIn, HIGH);
                                    
                                            incoming = shiftIn(DataIn, ClockPin, LSBFIRST);
                                           digitalWrite(ClockPin, HIGH);
                                           delay(80);
                            
                                    Serial.print("Col: ");
                                    Serial.println(col);
                                    Serial.print("InComing: ");
                                    Serial.println(incoming);
                                    
                            if((incoming & Mymask[row])==0)
                                {
                                byte keypress= keys[row][col];
                                 Serial.print("KeyPRESS: ");
                                Serial.println(keypress);
                            
                            }// end of if
                                    
                                    
                                    delayMicroseconds(200);
                            
                                } 
                            
                                } // row end
                            
                            }
                            
                            
                            
                            
                            void setup()
                            {
                            
                              /* add setup code here */
                                pinMode(ClockPin, OUTPUT);
                                pinMode(DataOut, OUTPUT);
                                pinMode(DataIn, INPUT);
                                pinMode(LatchOut, OUTPUT);
                                pinMode(LatchIn, OUTPUT);
                            
                                digitalWrite(LatchOut, LOW);
                                
                                digitalWrite(ClockPin, LOW);
                                Serial.begin(9600);
                            
                            }
                            
                            void loop()
                            {
                            
                              /* add main program code here */
                            
                              
                              KeyDown();
                              delayMicroseconds(200);
                            
                            }
                            
                            
                            
                            
                            
                            
                            
                            
                            
                            
                            
                            
                            
                            
                            
                            
                            
                            
                            
                            
                            
                            
                            
                            
                            
                            
                            
                            
                            
                            
                            
                            
                            
                            
                            
                            
                            
                            
                            
                            

                            As a test I attached a led to Row0 /Col0 and when I pressed the corresponding key to Row0/Col0; the led turns up , but the IF condition at line 78 is not display(or returning) the corresponding keypad character (that is my problem). Can you please look at that IF condition again.

                            Many thanks for your time.

                              • Re: Help with Scan code for 4x4 Multiplex keypad with 74hc595/74hc165 Shift Register
                                obulorn

                                Many thanks shabaz, i was able to sort the issue out. I had to include a saperate Column masking and its working now. The only challange is that its not waiting for keypress. I want  to open a new thread for that. Here is the working code for anyone that may need.

                                 

                                const int kbdRows = 4;
                                const int kbdCols = 4;
                                int row, col;
                                int LatchIn = 3; //165 pin1
                                int ClockPin = 5; // 595 pin11 & 165 pin2
                                int DataIn = 2; //165 pin9
                                int LatchOut = 6; // 595 pin12
                                int DataOut = 7; //595 pin14
                                
                                int mask = 0x80;
                                int lastmask = 0x10;
                                int ColMask = 0x80;
                                int lastColMask = 0x10;
                                char keypress;
                                char Keycode;
                                int result = 0;
                                int incoming = 0;
                                int RtnIncoming = 0;
                                char mykeys[kbdRows][kbdCols] =
                                {
                                    { '1','2','3','4' },
                                    { '5','6','7','8' },
                                    { '9','0','A','B' },
                                    { 'C','D','E','F' }
                                };
                                char ScanCode()
                                {
                                    if (incoming & ColMask)
                                    {
                                
                                        keypress = mykeys[row][col];
                                        
                                        return keypress;
                                        
                                    } // end if
                                }
                                int ReadInput()
                                {
                                    //165 Here
                                    digitalWrite(ClockPin, HIGH);
                                    digitalWrite(LatchIn, LOW);
                                    delayMicroseconds(5);
                                    digitalWrite(LatchIn, HIGH);
                                    delayMicroseconds(5);
                                        incoming = shiftIn(DataIn, ClockPin, LSBFIRST);
                                        delayMicroseconds(200);
                                
                                    return incoming;
                                
                                }
                                int KeyDown()
                                {
                                    
                                        //595 Here
                                
                                    for (row = 0; row < kbdRows; row++)
                                    {
                                        digitalWrite(LatchOut, LOW);//
                                        shiftOut(DataOut, ClockPin, LSBFIRST, mask);
                                        digitalWrite(LatchOut, HIGH);//
                                     
                                        delay(50);
                                        //165 Here
                                
                                        RtnIncoming = ReadInput();
                                        
                                        delayMicroseconds(200);
                                        ///delay(150);
                                        
                                
                                        for (col = 0; col < kbdCols; col++)
                                
                                        {
                                            if (RtnIncoming != 0)
                                            {
                                                switch (col)
                                                {
                                                case 0:
                                
                                                    ColMask = 0x40;
                                
                                                    if (RtnIncoming & ColMask)
                                                    {
                                
                                                     Keycode=ScanCode();
                                                    
                                                    } // end if
                                
                                                    break;
                                
                                                case 1:
                                
                                                    ColMask = 0x20;
                                
                                                    if (RtnIncoming & ColMask)
                                                    {
                                                         Keycode = ScanCode();
                                                        
                                                    } // end if
                                                    break;
                                                case 2:
                                
                                                    ColMask = 0x10;
                                
                                                    if (RtnIncoming & ColMask)
                                                    {
                                
                                                     Keycode = ScanCode();
                                                    
                                                    } // end if
                                                    break;
                                                case 3:
                                
                                                    ColMask = 0x80;
                                
                                                    if (RtnIncoming & ColMask)
                                                    {
                                
                                                     Keycode = ScanCode();
                                                    
                                
                                                    } // end if
                                                    break;
                                
                                                //default:
                                                    
                                                    
                                                //    break;
                                
                                
                                                } // end switch
                                
                                            } // end not zero
                                
                                
                                        }    //end col for
                                    
                                            if (mask == lastmask)
                                             {
                                                 mask = 0x80;
                                
                                                }
                                              else
                                           {
                                               mask = mask >> 1;
                                           }
                                               
                                  } // row end
                                  
                                  return Keycode;
                                        
                                }
                                
                                
                                
                                
                                
                                
                                
                                
                                
                                
                                
                                
                                
                                
                                
                                
                                
                                
                                
                                
                                
                                
                                
                                
                                
                                
                                
                                
                                
                                
                                @