24 Keys Matrix

yinon

Member
I wrote this code to scan 24 keys matrix, it's work great with Arduino Uno but on teensy 3.2 and 3.6 I got something like "double pulsing".
when I press on the 7th' key I got 6 and 7 reading , allmost same when I pressed the 16th' key then I got 14 and 16 reading.
all the rest of the keys works fine.

thanks for help ,



the code :

Code:
int pressedKey[25]={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};

int k1_row[6]={1,2,3,4,5,6};
int k1_col[4]={7,8,9,10};


void setup() {
    Serial.begin(9600); 
    delay(1000);
     
  for(int i=0;i<=5;i++){
   pinMode(k1_row[i],OUTPUT);
  }
  
  for(int i=0;i<=3;i++){
    pinMode(k1_col[i],INPUT_PULLUP);
    }
  Serial.println("SETUP DONE");
}

void loop() {

      for(int i=0; i<=5; i++){
           digitalWriteFast(k1_row[0],HIGH);
           digitalWriteFast(k1_row[1],HIGH);
           digitalWriteFast(k1_row[2],HIGH);
           digitalWriteFast(k1_row[3],HIGH);
           digitalWriteFast(k1_row[4],HIGH);
           digitalWriteFast(k1_row[5],HIGH);
           digitalWriteFast(k1_row[i],LOW); 
          
          for(int j=0; j<=3; j++){ 
      
            int strokedKey=i*4+j+1;
            bool col_scan=digitalRead(k1_col[j]);
                 
                        
                if(col_scan==LOW){
                    if (pressedKey[strokedKey]==0 ){
                            //playMusic(strokedKey);
                            pressedKey[strokedKey]=1 ;
                            Serial.println(strokedKey);
                    }        
                   delay(10);
               } 
               
               else
                pressedKey[strokedKey]=0;    
      
            }
               delay(10);
}
}


IMG-7107.jpg
 

Attachments

  • IMG-7109.jpg
    IMG-7109.jpg
    142 KB · Views: 53
Last edited:
Thinking about the differences between a UNO and a Teensy:

The Teensy is faster and will fail when the program needs more time between steps. I think that is probably the issue and would suggest an added delay.

Code:
       for(int i=0; i<=5; i++){
           digitalWriteFast(k1_row[0],HIGH);
           digitalWriteFast(k1_row[1],HIGH);
           digitalWriteFast(k1_row[2],HIGH);
           digitalWriteFast(k1_row[3],HIGH);
           digitalWriteFast(k1_row[4],HIGH);
           digitalWriteFast(k1_row[5],HIGH);
           digitalWriteFast(k1_row[i],LOW); 
          
Add a delay here to allow the row signals to stabilize before reading the columns.
          for(int j=0; j<=3; j++){ 
      
            int strokedKey=i*4+j+1;
            bool col_scan=digitalRead(k1_col[j]);

The UNO has 5 volt logic and the Teensy has 3 volt logic. The UNO has more margin for error in determining if the signal is high or low. You have your signals going through a long cable and that can cause issues. Short wires are best for speed.

You are using the internal pullups and they may be different between a UNO and the Teensy. Generally internal pullups are high resistance and the signals will respond slower than if you used external pullups.
 
Hi Rcarr, thanks for the well-detailed answer.

I do some extra tests and set the matrix with short wires and it worked well.
so it's probably a wire length issue. I am trying to figure out if the solution is on the output side mean the matrix lines or maybe on the inputs pins used by the matrix Cullums.

Practically I see two options :

1. shift the logic level to 5V and raise the pulldown resistor
2. stay with the pull-up system using external resistors and looking for the right value
 
Last edited:
last update :

A 5.1k external pull-up resistor had solved the problem :)
thanks for you're help.

Hopefully at least for the T3.6 you are using a PU that uses 3.3v as the T3.6 pins are not tolerant of 5v being applied to them.
 
Hopefully at least for the T3.6 you are using a PU that uses 3.3v as the T3.6 pins are not tolerant of 5v being applied to them.

yes, of course.

I am still dealing with the same issue. the external Pullup don't solve the problem ):
 
Like @houtson mentioned, you might try the keypad library solution.

A long time ago I wrote my own code for a 20 button matrix... which does something similar to what you mentioned.
But there were discussions somewhere (not sure here or Trossen or ...) about concern if multiple buttons were pressed, could I could I short two pins. One digitalWrite HIGH connected to another one digtialWrite LOW...
So changed my digitalWrite(pin, HIGH), to pinMode(pin, INPUT_PULLUP)...

I doubt that would help here...

If it were me, I would try a quick and dirty debounce sort of logic... like:
Code:
    if(col_scan==LOW){
        delay(5); // experiment on how long
        col_scan=digitalRead(k1_col[j]);
        if (col_scan==(LOW) {
            // only if still low process it...
...

And see if that removes the issues.
 
thanks for the help, I don't find an easy solution yet. I keep using both, Teensy and Arduino pro mini together
 
Did you add the delay suggested in msg #2? From msg #3, sounds like you rejected this idea because changes in resistors seemed to help.

If you're still experiencing problems, please reconsider adding that delay. This issue with controlling a mux or keypad is the most common problem when going from slow AVR to fast ARM. We've answered it over and over on this forum. A small delay usually is necessary.

If you have real pullup resistors, even 1 to 2 microseconds is probably enough. Teensy has a delayNanoseconds() function if you want to try even shorter than 1 microsecond. Ideally you would use an oscilloscope to view the actual voltage change time.
 
Hi Paul,

I used 2 delays, inside 'if' and after 'else' (that delay is executed most of the time).
it's not solved the problem, I am still looking for a solution. as I mentioned before on Arduino pro mini it's working great without any treats, use the only internal pullups resistors.
 
From your description of "inside if and after else" it seems you may have the delay in the wrong place in the code. It should be just before the 2nd for loop. Perhaps you should post the new code and get some new input to your issue.
 
It should be just before the 2nd for loop

delay added after : digitalWrite(k1_row,LOW);
that what you mean ?

Code:
      for(int i=0; i<=5; i++){
      digitalWrite(14,HIGH);
      digitalWrite(15,HIGH);
      digitalWrite(16,HIGH);
      digitalWrite(17,HIGH);
      digitalWrite(18,HIGH);
      digitalWrite(19,HIGH);
      
      digitalWrite(k1_row[i],LOW);
      delay(5);
      
      for(j=0; j<=3; j++){
        
             col_scan=digitalRead(k1_col[j]);
             if(i==0&&j==0)
             Serial.println(col_scan);

             strokedKey=i*4+j+1;
        
            if(col_scan==LOW){
                if (pressedKey[strokedKey]==0 ){              
                        playRaw(strokedKey);
                        pressedKey[strokedKey]=1;
                        Serial.print("Stroke:");
                        Serial.println(strokedKey);
                }        
           } 
           
           else{
                      
              if(pressedKey[strokedKey]==1){
                 pressedKey[strokedKey]=0;
                 Serial.print("Relese:");
                 Serial.println(strokedKey);
                 }    
               
            }
      }
            
}

//Serial.println(millis()-lastMillis);
              
}
 
it's a bingo :)

now it's clear, the selected pin takes some time to get low, so if you don't wait for him you got an undefined state on the input pin.
it looks like a solution, works great. thanks,

yinon
 
Back
Top