how to get additional current to a multiplexed led matrix

hello all, so i have constructed a multiplexed or “charlieplexed” led matrix 10x9. im using this to visualize audio signals using 10 digital I/O pins to control it. I have a mono jack connected to A0 and gnd and when i plug in a audio source it does work. however the leds are dim which i believe is due to the low current. I have tired hooking up the pins to transistors and using a 9v battery which helped a bit but i lost control of how many led’s in a column light up. So im asking if there is a better way to potentially get these led’s to be brighter. also this is for visual effect only so as long as it moves with the music appropriately ,high accuracy isn’t important. thanks.
the images are only a few pins but i use the same concept for all 10 i’m using

#define A 2
#define B 3
#define C 4
#define D 5
#define E 6
#define Z 7
#define G 8
#define H 9
#define I 10
#define J 11

#define LOG_OUT 1 // use the log output function
#define FFT_N 128 // set to 256 point fft
#include <FFT.h> // include the library

int check[4];
int LEVELS[16];
int count;
int bar;
int AVG;
int c [10][9][2]={
  {{A,B},{A,C},{A,D},{A,E},{A,Z},{A,G},{A,H},{A,I},{A,J},},
  
  {{B,A},{B,C},{B,D},{B,E},{B,Z},{B,G},{B,H},{B,I},{B,J},},
  
  {{C,A},{C,B},{C,D},{C,E},{C,Z},{C,G},{C,H},{C,I},{C,J},},
  
  {{D,A},{D,B},{D,C},{D,E},{D,Z},{D,G},{D,H},{D,I},{D,J},},
  
  {{E,A},{E,B},{E,C},{E,D},{E,Z},{E,G},{E,H},{E,I},{E,J},},
  
  {{Z,A},{Z,B},{Z,C},{Z,D},{Z,E},{Z,G},{Z,H},{Z,I},{Z,J},},
  
  {{G,A},{G,B},{G,C},{G,D},{G,E},{G,Z},{G,H},{G,I},{G,J},},
  
  {{H,A},{H,B},{H,C},{H,D},{H,E},{H,Z},{H,G},{H,I},{H,J},},
  
  {{I,A},{I,B},{I,C},{I,D},{I,E},{I,Z},{I,G},{I,H},{I,J},},
  
  {{J,A},{J,B},{J,C},{J,D},{J,E},{J,Z},{J,G},{J,H},{J,I}}
};

void setup(){
  pinMode( A, INPUT);
  pinMode( B, INPUT);
  pinMode( C, INPUT);
  pinMode( D, INPUT);
  pinMode( E, INPUT);
  pinMode( Z, INPUT);
  pinMode( G, INPUT);
  pinMode( H, INPUT);
  pinMode( I, INPUT);
  pinMode( J, INPUT);
 
  Serial.begin(9600); // use the serial port
  TIMSK0 = 0; // turn off timer0 for lower jitter
  ADCSRA = 0xe5; // set the adc to free running mode
  ADMUX = 0x40; // use adc0
  DIDR0 = 0x01; // turn off the digital input for adc0

}
void loop(){
  while(1) { // reduces jitter
    cli();  // UDRE interrupt slows this way down on arduino1.0
    for (int i = 0 ; i < 256 ; i += 2) { // save 256 samples
      while(!(ADCSRA & 0x10)); // wait for adc to be ready
      ADCSRA = 0xf5; // restart adc
      byte m = ADCL; // fetch adc data
      byte j = ADCH;
      int k = (j << 8) | m; // form into an int
      k -= 0x0200; // form into a signed int
      k <<= 6; // form into a 16b signed int
      fft_input[i] = k; // put real data into even bins
      fft_input[i+1] = 0; // set odd bins to 0
    }
    fft_window(); // window the data for better frequency response
    fft_reorder(); // reorder the data before doing the fft
    fft_run(); // process the data in the fft
    fft_mag_log(); // take the output of the fft
    sei();
    count =0;
    AVG=0;
    bar =0;
    //Serial.println("START");
    for (byte i = 0 ; i < FFT_N/2 ; i++) { 
      
      check[count] = (int)fft_log_out[i];
       
       AVG = AVG + check[count];
       //Serial.println(check[count]);
       count++;
     
      if(count == 4){
        AVG = AVG/4;
        LEVELS[bar] = (AVG);
        bar++;
        //Serial.println("END CYCLE");
        //Serial.print("AVG = ");
        //Serial.println(AVG);
       
       AVG=0;
       count = 0;
      }
    }
      
       if(LEVELS[0] <150){
        continue;
       }
       else{
  
       //Serial.print("LEVELS  ");
         for(int j =0;j<10;j++){
           
        //Serial.println(LEVELS[j+1]);
        //Serial.println(lin(LEVELS[j+1]));
         columns(j,lin(LEVELS[j+2])); 
       }
     
    }
   
    //Serial.println("FINISH");
  }
 
    
}
int lin(int a){
  if(a > 90) return 9;
  if(a > 80) return 8;
  if(a > 70) return 7;
  if(a > 60) return 6;
  if(a > 50) return 5;
  if(a > 40) return 4;
  if(a > 30) return 3;
  if(a > 20) return 2;
  if(a > 10) return 1;
  if(a < 10) return 0;
  
}
void columns(int col, int level){
  
  int i, j;
  for(i = level; i > 0; i--){
    
    if(i <= col){
      j = i - 1;
      light(c[j][col-1]);
    }
    else{
      light(c[i][col]);
    }
  }
}
void light( int pins[2] ){
  
  pinMode( pins[0], OUTPUT );
  digitalWrite( pins[0], HIGH );

  pinMode( pins[1], OUTPUT );
  digitalWrite( pins[1], LOW );
  pinMode( pins[0], INPUT);
  pinMode( pins[1], INPUT);
}

Maybe. Post a proper schematic (hand drawn is OK) and your sketch. Read the "please read" post first so you know how post images and code. Make sure the schematic shows exactly how you have connected the audio signal to the analog pin, because if done incorrectly you may be damaging the Arduino.

thank you for the reply. i posted all the information. on the images , i am using the same wiring through all 10 pins and the resistors i am not sure what value will be needed for the additional current.


Sorry, but I'm going to need more complete schematics than those. Your two schematics do not even match each other, and not just because one has 5 lines and the other has 6. There is no Arduino shown! You have not shown any component values. What is the forward voltage and max current of your leds? Also I specifically asked to see the audio input circuit.

Maybe i should say I'm 13 because i dont seem to understand why u need all that. I can't seem to find any software that allows more that 20 components for a diagram but the pattern is pretty simple for the each pin and just repeats itself for 10 pins making a total of 90 leds. The forward voltage for each led is 3.2 with a max current of 20mA the audio input i don't think is the problem it's just a simple mono plug running through a non inverting amplifier and it's readings are fine. The matrix works each column and row light up with music like they are suppose to it's just they are dim. The resistor values I left blank because I'm not even sure how to get this to work with an additional current so idk what those values should be.

Well, I've read through your code and the good news is that I can see why your matrix is so dim. The bad news is that your code will need some major restructuring to fix it. Plus you will need some transistors to avoid overloading the Arduino outputs.

In summary, your matrix is dim because the average current each led receives is very tiny. The perceived brightness of a led in a matrix depends on the average current. While a led is lit, it may be receiving the maximum 20mA. But if it is only lit for, let's say, 0.01% of the time, its average current would only be 0.002mA. I think this is what is happening in your matrix.

There are a few reasons why that time percentage is so low.

  • Only one led is ever lit at any instant in time. With up to 90 leds to cycle through, you can never get much over 1% time lit.
  • Your code, that lights a single led, switches it off again immediately afterwards, so the led is only lit for a few microseconds, the time it takes to execute a single line of code.
  • While the FFT code is running, no leds are lit. I don't know how much time that FFT code takes to run, but it could be 10 times longer than the code that scans the matrix.

So these are the changes I recommend you make. Unfortunately I'm not even sure how I would go about some of them myself!

  • You need to light more than one led at an instant in time. Either a whole row or a whole column. Looking at your schematic, I think it should be a whole row. In practice, you will not want all the leds in the row to be lit, but you need the capability to light all of them. That much current would overload the Arduino pin sourcing current to the row. So you need an npn transistor for each row, connected as an "emitter-follower".
  • You need to light (up to) all the leds in a row and leave them lit for a good length of time, ideally a millisecond or two. You don't want to turn them off again until you are ready to light the next row. The obvious way to achieve this is to use the delay() function. But in your circuit, you cannot afford to do that, because delay() literally wastes processing time. You need to use that time to run the FFT code.
  • You need to find a way to continue to light the led rows while the FFT code is running. I would suggest using a timer interrupt. However, the code you already have seems to be disabling interrupts for some reason. Maybe that is only for short periods and it will not matter.

With these changes, you should be able to get each led in the matrix lit for around 10% of the time, which will be at least 100 X brighter.

The reason I am concerned about your audio input is because audio signals have positive and negative voltages in the waveform. The Arduino analog input will be damaged by the negative parts, unless your input circuit removes that somehow.

I must also say that you have done very well to get this far, given your age and experience. I don't know how much help you have had from adults experienced in electronics (parents/teachers) but if that has been only a little help, then you have the makings of a career as an electronics engineer.

Thanks for the advice. I have some new ideas to try, I didn't even think that the short time the led was lit was a problem. The FFT takes Approx 6.23ms to run but I can cut it down to 1.32 by sacrificing accuracy which isn't a concern just for for visual effects. Ill cut down the FFT time and add a delayMicro to the method that lights the Led and see if that will have an effect. The analog input hasn't shown any sign of damage and I've been running this for awhile. It is never above the 5v limit and I made sure there was no negative voltage. But on a unrelated question, at first I just had direct A0 and gnd with nothing else, getting values between 0-1023 but was able to make code that could make sense of the values despite it normally being inaccurate and jittery, would having that setup damage the analog with such low values? Just wondering.

Less than 2ms for the FFT is great, much less than I expected. This simplifies things a lot. You can light a row and leave it lit while you do the FFT, then light the next row and so on. No need to use timer interrupts. Let me know if you need help wiring the transistors for each row, I would suggest bc337, but there will be many other suitable npn. You won't need a resistor in series with the base because you will be using them as emitter followers.

Damage to an analog input due to negative voltages, or voltages over 5V will not necessarily show up straight away. But the life of the Atmega chip may be reduced as a result. How do you know that no damage has been done? Well, you don't. What did you mean by "such low values"? If you meant a reading of 1023, that's the maximum, and anything over 5V will give 1023, until the moment that the "magic smoke" escapes!

IT WORKED! i just made a reset funtion to return all pins to input and call it every iteration of the forloop that lights the columns . it is still a bit blinky but finding the perfect delay time should fix that. but they are much brighter now that they have more time for current to flow. thank you so much. ill post a picture once i get the delay just right.