Go Down

Topic: [Solved]LED Matrix, can't make it bright enought (Read 1 time) previous topic - next topic

swat3d

Jul 23, 2012, 03:49 am Last Edit: Jul 26, 2012, 12:33 am by swat3d Reason: 1
Hi,

I am editing the first post of this thread to summarize the things learned during the investigation and the solution. I've come across some contradictory information while working on this and that made things very difficult when you don't exactly know what you are doing.

The problem:
I was working on a 5x5 matrix, direct drive, not using any ICs.
The brightness of the LEDs was much lower when being Multiplexed than when plugging them to DC directly.
For this application i really need the LEDs to provide their maximum brightness.
LEDs can usually be fed with higher current when being Multiplexed to compensate for this (check datasheet of your LED).

These are the specs for the LEDs:
Forward voltage: 2.2v
Forward current: 20mA
Forward peak current: 50mA (at 10% duty cycle)


Approach:
I was planning to multiplex both Rows and Columns, so only 1 LED would be on at a time. I've done this in the past and it has worked fine, I managed to get consistent brightness on all LEDs and i was able to control the brightness of each LED individually refreshing it at 60Hz. The LEDs were not displaying their full brightness but that wasn't a problem for that application, they were bright enough.

The first problem I was facing was that Arduino can just provide or sink 40mA on each Pin. I needed 50mA to get the full brightness on the LEDs so I needed an extrenal power supply.
The way to switch bigger currents with Arduino on and off is obviously using transistors as switches and in this case I chose to use an NPN transistor, the 2N3904.

The way an NPN transistor works is current flows from the collector to the emitter when a small current is applied to the base.

Transistors can be used as amplifiers or as switches, in this case as i mentioned before, we want to use them as switches.Nowwhat we want to do is to calculate how much current we need to apply to the base, without damaging the transistor, to have it saturated, or fully ON so that the current of the power supply can flow.

There are a few things that you need to take into account when choosing a transistor:
1 - What's the current that you need, to switch the load ON?
In my case, 50mA
2N3904 supports 200mA of collector continuous current
2 - What's the voltage of the power supply that you are intending to use
In my case 9v, 2N3940 supports 40V Collector-Emitter voltage
3 - What's the gain(hFE) of the transistor?
This is basically a factor of the current that needs to be applied to the base in order to let the current pass from collector to emitter. In my case 100.
So if you take the current that you need to switch the LED ON (50mA) and divide it by hFE, 50mA / 100 = 0.5mA is the current that will need to be applied to the base to let 50mA pass through the collector-emitter.
Can the arduino provide that much current (0.5mA)? Yes! not a problem.

So the 2N3904 is a good choice.

Now how do i feed 0.5mA to the transistor from Arduino. Easy, we know the voltage that Arduino provides, we know the current that we need we are just missing the Resistance to apply Ohms Law.
However, the transistors lose 0.7 volts so we need to account for that. And we also want to make sure that the transistor is saturated so instead of 0.5mA we add a 30% to it.

Ib = 0.5 * 1.3 = 0.65

Rb = (5v - 0.7v) / 0.00065 = 6615 ohms (or the closest one available)

If we have done it right, the voltage across the collector and the emitter of the transistor should be < 0.7v, that means that the transistor is in saturation.

Next issue I was facing... Multiplexing.
The LEDs can be fed with 50mA if a duty cycle of 10%. What does this mean?
The duty cycle is the percentage of time that the LED will be ON in a pulse.
If we are using a pulse of 1ms, the LED can be on for 100 microseconds and has to be off for 900 microseconds. A 10% of the pulse.
This presents a problem, if i am planning to light just one LED at a time and i have a 5x5 matrix, this means that each LED can just be ON for 1/25 of the time, so they will be very dim, i need them to be on by 1/10 of the time.
One easy way to do this (I will work on a better solution later) is to split the matrix in sub-matrices of 10 LEDs.
In my case I did 3 groups,(A=Row1, Row2) (B=Row3, Row4) (C=Row5, DummyRow). I added a dummy row to group C just to keep the code consistent and easier.
Now if I want to refresh my matrix 100 times in 1 second
1/100 = 0.01 seconds = 10 miliseconds is the total time of the pulse
So now to achieve a 10% duty cycle, each LED will be ON for 1ms, then we will switch it off and do the same with the rest of the LEDs.
We will do this on the 3 groups at the same time.

In each iteration of the loop what you do is:
Switch on A-Row1 B-Row1 C-Row1
Switch on Column1
Delay 1 milisecond
Switch off Column1
Switch on Column2
Delay 1 milisecond
Switch off Column2
...
until Column5
Then:
Switch off A-Row1 B-Row1 C-Row1
Switch on A-Row2 B-Row2 C-Row2
Switch on Column1
Delay 1 milisecond
Switch off Column1
Switch on Column2
Delay 1 milisecond
Switch off Column2
...

The code would look something like this:
Code: [Select]

byte Rows[] = {3,4,5,6,7,-1};
byte Rows1[] = {Rows[0],Rows[1]};
byte Rows2[] = {Rows[2],Rows[3]};
byte Rows2[] = {Rows[4],Rows[5]};
byte Cols[] = {8,9,10,11,12};

void setup()
{
 for(byte i = 0; i < sizeof(Rows); i++)
 {
   pinMode(Rows[i], OUTPUT);
   digitalWrite(Rows[i], LOW);
 }
 for(byte i = 0; i < sizeof(Cols); i++)
 {
   pinMode(Cols[i], OUTPUT);
   digitalWrite(Cols[i], LOW);
 }
}
void loop()
{
 for(byte r = 0; r < 2; r++)
 {
   byte prevRow = !r;
   digitalWrite(Rows1[prevRow], LOW);
   digitalWrite(Rows1[r], HIGH);
   for(byte c = 0; c < sizeof(Cols); c++)
   {
     byte prevCol = c;
     if(prevCol == 0)
       prevCol = sizeOf(Cols) - 1;
     digitalWrite(Cols[prevCol], LOW);
     digitalWrite(Cols[c], HIGH);
     delayMicroseconds(1000);
   }
 }
}


Bear in mind that this code is assuming that we are using transistors for both rows and columns. So when the pins are set HIGH, the transistors are ON.
Also 3 LEDs (maximum) will be ON at the same time so we need will need to modify the formulas to calculate the resistors based on the current needed to feed the LEDs (150mA)

In my test i just had 1 LED and 1 transistor controlling the Row.

Plug everything in, upload the code, and boom! It works.

Thanks, any questions do not hesitate to ask.

swat3d

Ok I have modified the circuit adding 2 NPN transistors this time, which should be more correct.
1 for the Row and 1 for the Column. I am getting the exact same results.

NPN1 has it's base connected to Pin4 (Row) through a 1k resistor. The collector is connected to +9v and the emitter is connected to the LED Anode.
NPN2 the base is connected to Pin13(Column) through a 1k resistor. The collector is connected to the cathode of the LED through a 100ohm resistor and the emitter is connected to 9v ground.

If i don't connect any of the arduino ground pins to the 9v ground, the LED doesn't light up. I don't really get that.

I have also modified the code so it makes the rows and columns LOW to switch them off and HIGH to switch them on.

Code: [Select]

void loop() {
  unsigned int time = millis();
  for(byte r = 0; r < sizeof(rows); r++)
  {
    //switch all rows off
    SwitchRows(LOW);
    //switch on current row
    digitalWrite(rows[r], HIGH);
    for(byte c = 0; c < sizeof(cols); c++)
    {
      //Switch all columns off
      SwitchCols(LOW);
      delayMicroseconds(360); //90% at 100hz
      //switch on current column
      digitalWrite(cols[c],  HIGH);
      delayMicroseconds(40); //10% at 100hz
    }
  }
  Serial.println(millis()-time);
}

tmd3

You've got the 100 ohm resistor and the LED connected between the emitter and ground.  That's not the way to use an NPN transistor as a switch.  The load goes between the collector and the positive supply, and the emitter is grounded directly.  As it's wired, the transistor is operating in its linear region, and it's limiting the current that flows through the LED.  The transistor should be in saturation, with the 100 ohm resistor limiting the current.  Recalculate the series resistor before you change it, though - if 50 mA is an absolute maximum rating for your LED, you might exceed it with 100 ohms and 9V.

It looks like you don't fully understand the notion of a duty cycle.  A 10% duty cycle means that the LED is on 10% of the time; you seem to be thinking something else.  It also applies to each LED individually; you seem to think it applies to the whole array.  Check the Wikipedia article here:  http://en.wikipedia.org/wiki/Duty_cycle, and, if that's not clear, googlit.

Quote
If i don't connect any of the arduino ground pins to the 9v ground, the LED doesn't light up. I don't really get that.
To turn on the transistor, current has to flow from the base to the emitter.  That means that current has to flow from the Arduino's output pin into the base, out the emitter, through the LED and resistor, and then back to the ground of the Arduino.  The 9V battery circuit is completely isolated from the Arduino's power supply unless you connect them.  Without that connection, there isn't a complete circuit for the base current to flow through.  No current flows, the transistor stays off, and the LED stays dark.

See how you like the performance with the LED and resistor between the collector and 9V, and the emitter grounded.  There may be some other things you can do, but we won't know until you fix the circuit.

swat3d

#3
Jul 23, 2012, 05:25 pm Last Edit: Jul 23, 2012, 05:28 pm by swat3d Reason: 1
Thanks a lot for the reply tmd3!

Quote
The load goes between the collector and the positive supply, and the emitter is grounded directly

I have updated the circuit accordingly but i see no difference. I have placed the load between the +9v and the collector of NPN1.

9v+ ----- 100ohm ---- LED Anode
                             LED Cathode ------------ NPN1 Collector
Pin4 ---- 1k -------------------------------------- NPN1 Base
                                                              NPN1 Emitter -------- NPN2 Collector
                                                              Pin13---- 1k ---------- NPN2 Base
                                                              -9v & -Arduino ------- NPN2 Emitter

It doesn't let me upload the picture from the office, i will submit it later.

Quote
Recalculate the series resistor before you change it, though - if 50 mA is an absolute maximum rating for your LED, you might exceed it with 100 ohms and 9V.

As for the resistor value: (9 - 2.2 = 6.8)    R=6.8/0.05 R=136ohms

Quote
A 10% duty cycle means that the LED is on 10% of the time; you seem to be thinking something else.  It also applies to each LED individually; you seem to think it applies to the whole array.

I understand that and I though I was applying the concept correctly but I might be wrong! Let me explain to you again what i'm doing to see if i'm doing it right.

1. The entire matrix has to refresh 100 times per second (100hz), which means that it has to refresh every 10ms.
2. There are 25 LEDs in the matrix and I am going to have only 1 on at a time. Which means that each LED has to refresh in 10ms/25 = 0.4ms
3. The LED can be on at 50ma a maximum of 10% duty cycle. 10% of 0.4ms = 40 micro seconds
4. Each LED has to be ON for 40 micro seconds, and off for 360 micro seconds, to have equal cycles in all LEDs therefore consistent brightness.

Is that right?

swat3d

I was thinking about the duty cycle issue that you mentioned tmd3 and yeah it seems like i am mixing concepts here.
I did a graphic representation of the logic and the way i am doing it now, it would look like the image attached.
The LEDs are not OFF for 360 micro seconds, basically they are off until the loop reaches them again and switches them on. That means they remain off for 9960 micro seconds, and on for 40 micro seconds.
I guess the duration of the pulse is 10ms, a duty cycle of 10% should be 1ms.

Does that sound right?

Go Up