Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

bi-directional led matrix

Status
Not open for further replies.

elecgirl88

New Member
hi guys

I'm doing a final year project which requires me to create an led matrix to be used as a touch pad. Basically it will be used as an access control system and a password will be entered via finger swipes on the surface.
Currently, I'm only able to sense with the whole matrix. I cannot get individual leds to sense on their own. I'm not sure why I cant isolate each led since I'm scanning through each led in the matrix and then checking light levels using the ADC.

I'm using an Arduino pro mini and testing on a 4x4 matrix.
The code is below:

Code:
// A technique to make analogRead faster
// See http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1208715493/11
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif


#define num 4

int rows[4]={6,7,8,9};           //PORTS PD6, PD7, PB0, PB1
int cols[5] ={14,15,16,17,14};      //PORTS PC0, PC1, PC2, PC3
//int thresh[4]={0,0,0,0};
//int led[4]={2,3,4,5};

void setup(){
 
  //Serial.begin(9600);
  // Adjust prescaler to make analogReadFaster
  sbi(ADCSRA,ADPS2) ;
  cbi(ADCSRA,ADPS1) ;
  cbi(ADCSRA,ADPS0) ;
  
  //turn on each column of leds

 for(int i=0; i<num; i++){
  pinMode(cols[i],INPUT);
  digitalWrite(rows[i],LOW);
  pinMode(rows[i],OUTPUT);
 }

 for(int i=0; i<num; i++){
  pinMode(cols[i],OUTPUT);
  digitalWrite(cols[i],HIGH);
  delay(1000);
  digitalWrite(cols[i],LOW);
 }

}

void loop(){
 unsigned int level=0;         //light intensity level variable
 
 for(int i=0; i<num; i++){
   digitalWrite(cols[i],LOW);       //anodes o/p and low
   pinMode(cols[i],OUTPUT);
   
   digitalWrite(rows[i],HIGH);      //cathodes o/p and low
   pinMode(rows[i],OUTPUT);
 }
 
  //delayMicroseconds(10);
 
 for(int i=0; i<num; i++){
   digitalWrite(rows[i],LOW);
   
   delayMicroseconds(10);
   
   for(int j=0; j<num; j++){
     pinMode(cols[j],INPUT);
     delayMicroseconds(200);


   while(1){
    level = analogRead(cols[j]);    //read ADC
  // Serial.print(level[i][j]);
   //Serial.print(",");
    if (level > 50){                             
     
      pinMode(cols[j+1],OUTPUT);
      digitalWrite(cols[j+1],HIGH);
      delayMicroseconds(100);
      digitalWrite(cols[j+1],LOW);
      break;
      }

  
    else if (level < 49){
      pinMode(cols[j+1],OUTPUT);
      digitalWrite(cols[j+1],LOW);
      delayMicroseconds(100);
      break;
     } 
     
   }
  } 
   digitalWrite(rows[i],HIGH);
   //Serial.println();
 }
 
}


i cant figure out what I'm doing wrong!Please help
thanx in advance
 
Last edited:
Hey, I've done this! The problem I had was the charge bleeding off the LED's, they took f-o-r-e-v-e-r to bleed down to a point where you could read light levels. Each LED is actually like a little capacitor and stores a charge longer than you might think. Scanning the entire matrix quickly will redistribute those tiny charges from the hardware's pin capacitances.

Try reading them more slowly. You can use lower value "pull down" resistors to improve the response time, but the cost is sensitivity.
 
You can use lower value "pull down" resistors to improve the response time, but the cost is sensitivity.

I'm using 100ohm resistors per column so thats pretty small already.

Basically I was scanning through each led and using it to detect light levels, and using the led in the next column as an output. so when a finger swipe occurs on led[j] then led[j+1] should light up.The results I was getting from this code were quite scattered.

I've now adapted some code I found on the net by Eiji Hayashi for a game called laser command. The results are better, however I'm still unable to isolate each led. When i move my had over the matrix, entire columns light up. I'm not sure how to fix this.


Code:
// A technique to make analogRead faster
// See http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1208715493/11
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif


#define num 4

int rows[4] = {6,7,8,9};           //PORTS PD6, PD7, PB0, PB1
int cols[5] = {14,15,16,17};       //PORTS PC0, PC1, PC2, PC3
int thresh[4] = {0,0,0,0};
//****************************************************************************//
void setup(){
 
  //Serial.begin(9600);
  // Adjust prescaler to make analogReadFaster
  sbi(ADCSRA,ADPS2) ;
  cbi(ADCSRA,ADPS1) ;
  cbi(ADCSRA,ADPS0) ;
  
  adjustThreshCol();
   
 for(int i=0; i<num; i++){
  pinMode(cols[i],INPUT);
  digitalWrite(rows[i],LOW);
  pinMode(rows[i],OUTPUT);
 }

 for(int i=0; i<num; i++){
  pinMode(cols[i],OUTPUT);
  digitalWrite(cols[i],HIGH);
  delay(1000);
  digitalWrite(cols[i],LOW);
 }

} 

//******************************  MAIN LOOP  *********************************//
void loop(){
  
  int row = checkRow();
  int col = checkCol();
  
  if(row != 4 && col != 4){
    pinMode(rows[row],OUTPUT);
    pinMode(cols[col],OUTPUT);
    digitalWrite(rows[row],LOW);
    digitalWrite(cols[col],HIGH);
    delayMicroseconds(100);
    pinMode(rows[row],INPUT);
    digitalWrite(cols[col],LOW);
  }
}

//********************************   END  ************************************//



////////////////////////////////////////////////////////////////////////////////
int checkCol(){
  int val[4];
  
   
 for(int i=0; i<num; i++){
   digitalWrite(cols[i],LOW);       //anodes o/p and low
   pinMode(cols[i],OUTPUT);
   
   digitalWrite(rows[i],LOW);      //cathodes o/p and low
   pinMode(rows[i],OUTPUT);
 }
  
  delayMicroseconds(10); 
  for(int j=0; j<num; j++){
     pinMode(cols[j],INPUT);
  }
  
  delayMicroseconds(200);
  for ( int col=0; col<num; col++ ){          // read analog values at all anodes
    val[col] = analogRead( col );
  }

  for(int col=0; col<num; col++){          // calculate difference between current values and thresholds
    val[col] = val[col] - thresh[col];
  }
  
  int signal = 4;
  for(int col=0; col<num; col++){
   if(val[col] > 25){
     signal = col;
     break;
   }
  } 

return (signal);
}


///////////////////////////////////////////////////////////////////////////////////
// Measure analog values at anodes to calculate threshold values.
// Using the threshold values mitigates effects of ambient light conditions

void adjustThreshCol(){
  for ( int cnt=0; cnt<100; cnt ++ ) {   // measure the values 100 times and take average
  int val[4];
  
  for(int i=0; i<num; i++){
   digitalWrite(cols[i],LOW);       //anodes o/p and low
   pinMode(cols[i],OUTPUT);
   
   pinMode(rows[i],OUTPUT);
   digitalWrite(rows[i],LOW);      //cathodes o/p and low
  }
  
  delayMicroseconds(10);
  for(int j=0; j<num; j++){
    pinMode(cols[j],INPUT);
  }
  
  delayMicroseconds(200);
  for ( int i=0; i<num; i++ ){          // read analog values at all anodes
    val[i] = analogRead(i);
    thresh[i] += val[i];
  }
 }
 

 for ( int i=0; i<num; i++ ){             // take average
   thresh[i] = thresh[i] / 100;
  }  
}
 
////////////////////////////////////////////////////////////////////////////////////

int checkRow(){
 int val[4]={0,0,0,0};
 
 for(int i=0; i<num; i++){
   digitalWrite(cols[i],LOW);       //anodes o/p and low
   pinMode(cols[i],OUTPUT);
   
   pinMode(rows[i],OUTPUT);        //cathodes o/p and low
   digitalWrite(rows[i],HIGH);      
 }
 
 delayMicroseconds(100);
  
 for(int i=0; i<num; i++){        // Isolate the pin 2 end of the diode 
   pinMode(rows[i],INPUT);
   digitalWrite(rows[i],LOW);     // turn off internal pull-up resistor
  }
  
  for (int temp=0; temp < 50; temp++)
  {
    for(int row=0; row<num; row++){ 
        if (digitalRead(rows[row])==0 && val[row] == 0){
            val[row] = temp;
        }   
    } 
    break;
  }
  
  int signal=4;
  for(int i=0; i<num; i++){
    if(val[i] < 30){
      signal = i;
      break;
    }
  }
  return(signal);
}
  
//////////////////////////////////////////////////////////////////////////////////
 
100Ω is pretty low, but I don't see a delay between column element reads or know what your "settling time" is in the analogRead routine. Try putting a delay in here -
Code:
   for ( int col=0; col<num; col++ ){          // read analog values at all anodes
       delayMicroseconds(1000);     
       val[col] = analogRead( col );   }
Yes, a millisecond. Or even more. It's a matrix, all those LED capacitances are in parallel.

Better still - put the delay in the analogRead routine after the ADC pin select, and before the conversion. Do it crazy slow and see if the values will separate, then bring the speed up.

Posting a schematic would help.
 
Last edited:
Hi duffy
put the delay in the analogRead routine after the ADC pin select, and before the conversion

I'm not sure what you mean by this, how do i do that? It may be a really silly question but im new to arduino.

Also my LED matrix is connected as follows:
anodes connected in each column through a limiting resistor to the analog pins
cathodes connected in each row and then to digital pins
 
Try setting the adcPrescaler all the way up to 128. Add those delays I suggested.

The Arduino adc routine does this:
1. Connect the internal mux to an ADC pin (ADC0, ADC1, etc)
2. Wait for the voltage to settle
3. Start the conversion
4. Signal when done

It's step 2 that may be a problem, what you are trying to do requires some finesse. Eiji is using a red laser pointer. A red led has peak sensitivity to the same 640nm wavelength a red laser pointer puts out. This is like hitting the led with the equivalent of a blast of sunlight.
 
Duffy i've tried incresing the prescaler to 128 and I added those delays. but the results are the same. The columns are stil lighting up instead of individual LEDs.

@4pyros: I've done alot of research before starting the project, I've googled every possible combination of using LEDs as sensors but not many people give alot of info on how to do it. Well using a single LED as a sensor is documented and I'm able to do that. Its using an entire matrix of sensors thats the problem
 
A schematic would help, as I said before. Your verbal descriptions are either leaving something out or you don't understand the difference between a "limiting" resistor and a "pull down" resistor.
 
I was scanning through each led and using it to detect light levels, and using the led in the next column as an output.
Why arent you using the same LED for scanning and output.
 
I've now adapted some code I found on the net by Eiji Hayashi for a game called laser command. The results are better, however I'm still unable to isolate each led. When i move my had over the matrix, entire columns light up. I'm not sure how to fix this.

hye did u manage to solve your problem ? i kind of having the same problem here
 
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top