View previous topic :: View next topic |
Author |
Message |
ernest
Joined: 11 Feb 2004 Posts: 51
|
LED dot matrix blinking... |
Posted: Fri Dec 03, 2004 3:39 am |
|
|
Hi,
I have built a prototype of 80 columns LED dot matrix display and it is working alright. However, the message (chars.) that are being displayed are not bright enough and the LEDs blink. Why?
How can I solve this problem?
I have tried changing my drive time delay between 600us to 75us but it still doesn't work well.
Sample of my main code is shown below.
Thank You.
ernest
Code: |
delaycount=5; // is this the correct values
while (delaycount)
{
index = startposition;
for (i=0;i<80;i++) // we've 80columns to
{
// store our mask in an array. we need to do this because
// the call to write_expanded_outputs will destroy the value
// passed in.
data[0] = mask[0]; // store which column we are driving
data[1] = mask[1]; // in an array
data[2] = mask[2]; data[3] = mask[3];
data[4] = mask[4]; data[5] = mask[5];
data[6] = mask[6];
data[7]=mask[7]; data[8] = mask[8];
data[9] = mask[9];
(long)index = (long)i + (long)startposition; // point to the next pattern to display
if (index >= ((long)(6*s1_char_size))) ) // ensure that we don't exceed the array
index -= ((long)(6*s1_char_size));
port_d=0;
write_expanded_outputs(data); // enable our column driver
x = s1[index/6];
if((index%6)==0) // if index MODULUS 6 == 0
port_d = 0;
else if( x < 64) // check if s1[] is inside ascii1[] array
{ port_d = ascii1[x-32][(index%6)-1]; }
else if( x > 95) // check if s1[] is inside ascii3[] array
{ port_d = ascii3[x-96][(index%6)-1]; }
else if( x>63 && x<96 ) // check if s1[] is inside ascii2[] array
{ port_d = ascii2[x-64][(index%6)-1]; }
if (shift_left(mask,10,0))
mask[0] = 0x01;
delay_us(100); // WHAT IS THE CORRECT VALUE to control the LED drive time
} // END for-loop
--delaycount; // decrement our delay loop counter
}
++startposition; // Point to the next data pattern
|
|
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Fri Dec 03, 2004 8:10 am |
|
|
The LEDīs bright depends of the driving current and the time you enable
the column. You can get the same brightnes driving the LEDīs column
with 1500mA -a few microseconds with a short duty cycle- or
with 30mA -a few miliseconds with a high duty cycle-.
We havenīt any hardware description, nor the full code but the ovbious
stuff to play with are the delays involved in the different tasks and the
LEDīs current limit resistor.
Once you get the right brightness, you need to work around "tunning"
the display appearance with the tradeoff between brightness and the
undesirable blinking
Best wishes,
Humberto |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Fri Dec 03, 2004 8:35 am |
|
|
The human eye notices flicker at anything below 100Hz. Therefore you have to turn the LED on at least every 10ms. So you have 80 columns to turn on/off in 10ms. So that means that they can only be on 125us. The longer they are on, the brighter they get until they are full on. So if you are driving them longer than 125us, that is the problem. Note the time to copy data, shift out, blah, blah, blah all goes into this time. It is NOT just some delay after you turn them on. The time required to setup the current column is added to the "ON" time of the previous column. Make sense? |
|
|
ernest
Joined: 11 Feb 2004 Posts: 51
|
|
Posted: Fri Dec 03, 2004 12:11 pm |
|
|
Yup, definitely make sense. Thanks.
I'll work on it right away. I think I realize my problem right now is not having current limit resistor to the LED. Initially, I put a 150 Ohm resistor to drive each LED column but found that the display is not bright enough. Hence, I remove all the resistor and drive the LED directly and they seem to be brighter. Must say this is not a proper way though.
So, could this be the reason why my LED are not bright enough even though I've tried with delay (drive time) from 75us to 150us.
I am using 74HC595 (CMOS IC) to carry out column shift. So, I use a transistor for each '595 output to drive the column. Not sure if this is a proper way too.
Thanks.
ernest |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Fri Dec 03, 2004 12:18 pm |
|
|
Not having the resistor will make them bright for a while up until they start to overheat and then become damaged. Driving them for a short period will probably not hurt them but I would definitely put a current limiter in there. The real problem is probably just the physical limitations of the hardware. The LEDs are just not on long enough for them to be bright. |
|
|
ernest
Joined: 11 Feb 2004 Posts: 51
|
|
Posted: Mon Dec 06, 2004 2:35 am |
|
|
Mark wrote: | Not having the resistor will make them bright for a while up until they start to overheat and then become damaged. Driving them for a short period will probably not hurt them but I would definitely put a current limiter in there. The real problem is probably just the physical limitations of the hardware. The LEDs are just not on long enough for them to be bright. |
I have put in a current limiting resistor of 3.3ohm with supply of 5V to the LED. I have tried changing the delay from 250us down to 1 cycle and also 0 delay (without delay) but the LEDs still blink. Is it too fast or too slow? From 250us to 1us delay, the display is very faint (not bright) but when the delay was taken out or reduced to delay_cycles(2), the whole display becomes much brighter and clearer to read. However, the blinking problem is still there.
I've been trying very hard to change the delay value but the blinking problem remains unsolved.
Please recommend what else can I do.
Shall I use a higher clock speed say 40MHz with PIC18F452?
Thank You.
ernest |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Mon Dec 06, 2004 3:59 am |
|
|
Quote: | I have put in a current limiting resistor of 3.3ohm with supply of 5V to the LED. |
3.3 ohm is too low for protection !! Check your led datasheet for maximum allowed current.
Can you describe the 'blinking' in more detail? What frequency? Is the whole picture blinking or are all rows blinking in random patterns, etc.
Are you using interrupts in your program? |
|
|
ernest
Joined: 11 Feb 2004 Posts: 51
|
|
Posted: Mon Dec 06, 2004 4:18 am |
|
|
ernest wrote: | I have put in a current limiting resistor of 3.3ohm with supply of 5V to the LED. I have tried changing the delay from 250us down to 1 cycle and also 0 delay (without delay) but the LEDs still blink. Is it too fast or too slow? From 250us to 1us delay, the display is very faint (not bright) but when the delay was taken out or reduced to delay_cycles(2), the whole display becomes much brighter and clearer to read. However, the blinking problem is still there.
I've been trying very hard to change the delay value but the blinking problem remains unsolved.
Please recommend what else can I do.
Shall I use a higher clock speed say 40MHz with PIC18F452?
|
ckielstra wrote: | 3.3 ohm is too low for protection !! Check your led datasheet for maximum allowed current.
Can you describe the 'blinking' in more detail? What frequency? Is the whole picture blinking or are all rows blinking in random patterns, etc.
Are you using interrupts in your program?
|
3.3ohm is obtained from the following calculation:
5V/1500mA = 3.333 ohm
The 1500mA of current is needed to be supplied to the LED to light up within microsec.
Blinking problem: The LEDs form a matrix for displaying char./message & the matrix is driven by column scanning/shifting using 595 IC. Hence, correct and proper switching & timing of the LEDs are required to form a string of char.(msg) without any flicker/blinking. This is where I got stuck.
The blinking happens to almost all the 80columns of LED.
Hope you could lend some advice. Thank You.
ernest |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Mon Dec 06, 2004 11:05 am |
|
|
Do you have a scope to measure the time the LEDs are actually being driven? |
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Mon Dec 06, 2004 1:07 pm |
|
|
Driving Leds in a matrix array become a complex task proportional to the
number of rows/columns to drive, because the brightness and flikering is
a trade-off with the maximum rate at wich electronics can distribute and
process data.
- There are some improvement that I suggest:
- Change your driving voltage to a higher one (12V - 24V).
- For a good Led brightness consistency, the driving side (rows) must be a
constant current source, in the range of 60-80mA.
You can use TB62705 (Toshiba) - A6275 (Allegro) - TLC5921 (Texas) -
- The rows scan rate must be between 30-50 scan/sec, in an interrupt
driven secuence.
- For every scan, you must sweep pulling down the 80 columns. The
faster the rate the lower the flicker.
If your design have a comercial target, you need to keep in mind all this,
if your design is just a week end hobby, donīt care of this.
Best wishes,
Humberto
PD: Too hot on Buenos Aires (35°C) |
|
|
ernest
Joined: 11 Feb 2004 Posts: 51
|
|
Posted: Mon Dec 06, 2004 6:24 pm |
|
|
Mark wrote: | Do you have a scope to measure the time the LEDs are actually being driven? |
Yes, in fact I have measured the drive time for each LED. From the scope, the period/interval between each LED ON pulse is 65ms but the ON time is only 1ms.
That means, the LED will be driven ON for 1ms, and then OFF for nearly 64ms before it is driven ON the next cycle. The driving sequence seems ok as the 1ms ON time is shifted from one LED to the next and so on..
The above happens even when the delay of the column shift FOR-LOOP is taken out (delay=0).
Does that mean the MCU is not fast enough for 80 columns?
Humberto wrote: | Driving Leds in a matrix array become a complex task proportional to the number of rows/columns to drive, because the brightness and flikering is a trade-off with the maximum rate at wich electronics can distribute and process data.
- There are some improvement that I suggest:
- Change your driving voltage to a higher one (12V - 24V).
- For a good Led brightness consistency, the driving side (rows) must be a
constant current source, in the range of 60-80mA.
You can use TB62705 (Toshiba) - A6275 (Allegro) - TLC5921 (Texas) -
- The rows scan rate must be between 30-50 scan/sec, in an interrupt
driven secuence.
- For every scan, you must sweep pulling down the 80 columns. The
faster the rate the lower the flicker.
|
Wow..it sure is hot in Buenos Aires. But it's gonna be real HOT if I can solve the problems I have now.
-Why would changing to a higher voltage help? I thought the LED is current driven (brightness depends on current and not voltage).
- I'm using a UCN2004 for the row LEDs and the LEDs are common-anode.
- I have tried to cut down on all the unnecessary codes and have done all I can to shorten the length of codes to make it faster, but the flicker (blinking) is still there even though I have not put in any delay for each column scan/shift.
TQ.
ernest |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Mon Dec 06, 2004 6:56 pm |
|
|
Mark wrote: | The human eye notices flicker at anything below 100Hz. Therefore you have to turn the LED on at least every 10ms. So you have 80 columns to turn on/off in 10ms. So that means that they can only be on 125us. The longer they are on, the brighter they get until they are full on. So if you are driving them longer than 125us, that is the problem. Note the time to copy data, shift out, blah, blah, blah all goes into this time. It is NOT just some delay after you turn them on. The time required to setup the current column is added to the "ON" time of the previous column. Make sense? |
65ms is way too slow. That's only about 15Hz. I bet they are blinking! You have to get that time down to 10ms or less to stop the flickering. So now you probably want some ideas on speeding things up. Well here's a biggie. Throw all that copying and writing to the shift register out! All you are doing is rotating a bit through the registers. All you need to do is something like this
Code: | // Start with some known states
output_low(EXP_OUT_CLOCK);
output_low(EXP_OUT_ENABLE);
// The first bit is a 1, so put it there
output_high(EXP_OUT_DO);
output_high(EXP_OUT_CLOCK);
output_low(EXP_OUT_CLOCK);
output_low(EXP_OUT_DO);
for (i=0;i<80;i++) // we've 80columns to
{
// point to the next pattern to display
index = (long)i + (long)startposition;
// ensure that we don't exceed the array
if (index >= ((long)(6*s1_char_size))))
index -= ((long)(6*s1_char_size));
port_d=0;
// put the shift register values on the outputs
output_high(EXP_OUT_ENABLE);
output_low(EXP_OUT_ENABLE);
// rotate the 1 through the 595's
output_high(EXP_OUT_CLOCK);
output_low(EXP_OUT_CLOCK);
x = s1[index/6];
if((index%6)==0) // if index MODULUS 6 == 0
port_d = 0;
else if( x < 64) // check if s1[] is inside ascii1[] array
port_d = ascii1[x-32][(index%6)-1];
else if( x > 95) // check if s1[] is inside ascii3[] array
port_d = ascii3[x-96][(index%6)-1];
else if( x>63 && x<96 ) // check if s1[] is inside ascii2[] array
port_d = ascii2[x-64][(index%6)-1];
} // END for-loop
|
|
|
|
ernest
Joined: 11 Feb 2004 Posts: 51
|
|
Posted: Mon Dec 06, 2004 10:05 pm |
|
|
Not sure if the following way of coding is correct but I couldn't get the LED to display. It remains blank..
Anyway pardon me for asking but I would appreciate it very much if you could briefly explain what those codes do. I'm trying to understand them well.
I believe you are replacing the shift_left of the mask[] array with manual control of the EXP_OUT_CLOCK and EXP_OUT_ENABLE.
Code: |
do{
delaycount=3;
while (delaycount)
{
// Start with some known states
output_low(EXP_OUT_CLOCK);
output_low(EXP_OUT_ENABLE);
// The first bit is a 1, so put it there
output_high(EXP_OUT_DO);
output_high(EXP_OUT_CLOCK);
output_low(EXP_OUT_CLOCK);
output_low(EXP_OUT_DO);
for (i=0;i<80;i++) // we've 80columns to
{
// point to the next pattern to display
index = (long)i + (long)startposition;
// ensure that we don't exceed the array
if (index >= ((long)(6*s1_char_size)))
index -= ((long)(6*s1_char_size));
port_d=0;
// put the shift register values on the outputs
output_high(EXP_OUT_ENABLE);
output_low(EXP_OUT_ENABLE);
// rotate the 1 through the 595's
output_high(EXP_OUT_CLOCK);
output_low(EXP_OUT_CLOCK);
x = s1[index/6];
if((index%6)==0) // if index MODULUS 6 == 0
port_d = 0;
else if( x < 64) // check if s1[] is inside ascii1[] array
port_d = ascii1[x-32][(index%6)-1];
else if( x > 95) // check if s1[] is inside ascii3[] array
port_d = ascii3[x-96][(index%6)-1];
else if( x>63 && x<96 ) // check if s1[] is inside ascii2[] array
port_d = ascii2[x-64][(index%6)-1];
delay_us(50); // adjust this value to control the drive time
} // END for-loop
--delaycount; // decrement our delay loop counter
}
++startposition; // Point to the next data pattern
if (startposition >= (6*s1_char_size)) //make sure that we don't exceed the array
startposition = 0;
} while(1); //End of do-while
|
Thank You.
ernest |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Mon Dec 06, 2004 10:41 pm |
|
|
The first thing is that EXP_OUT_ENABLE is not actually the Enable on the chip. That is what it is labeled in the CCS driver file but is actually RCLK line. The orginal code would write the 10 bytes through each time of the for loop. All it is doing is really shifting a 1 through the registers. Well you don't really need to rewrite the entire 10 bytes. The mask can be shifted directly in the 595's by just clocking the SRCLK line.
First we set the lines low
Code: |
output_low(EXP_OUT_CLOCK);
output_low(EXP_OUT_ENABLE);
|
Next we clock in the 1
Code: |
output_high(EXP_OUT_DO);
output_high(EXP_OUT_CLOCK);
output_low(EXP_OUT_CLOCK);
output_low(EXP_OUT_DO);
|
Now your for loop
Code: |
for (i=0;i<80;i++) // we've 80columns to
{
// point to the next pattern to display
index = (long)i + (long)startposition;
// ensure that we don't exceed the array
if (index >= ((long)(6*s1_char_size)))
index -= ((long)(6*s1_char_size));
port_d=0;
|
Now the values get latched to the outputs
Code: |
// put the shift register values on the outputs
output_high(EXP_OUT_ENABLE);
output_low(EXP_OUT_ENABLE);
|
Now shift the mask
Code: |
// rotate the 1 through the 595's
output_high(EXP_OUT_CLOCK);
output_low(EXP_OUT_CLOCK);
|
And the rest is your code.
Are the 595's outputing anything. Can you look at them with a scope? |
|
|
ernest
Joined: 11 Feb 2004 Posts: 51
|
|
Posted: Tue Dec 07, 2004 12:09 am |
|
|
Yes, I managed to get it to work..Thanks a lot. I mistakenly assigned EXP_OUT_ENABLE as SRCLK of '595 and EXP_OUT_CLOCK as RCLK of '595. However, I notice that certain columns are not able to light up.
For example, I try to display the following msg:
"Welcome to SDTC"
However, I notice that the LEDs skip/overshifted certain char.for example:
- 2nd column of the char.'W' is blanked and resumed with column 3,4,5,6
- 3rd column of char.'l' is blanked and resumed with column 4
- 3rd column of char."t' is blanked and resumed with column 4,5
- 3rd column of char."D"is blanked and resumed with column 4,5,6
Why is that so? I believe it's caused by the column shift.
Thank You.
ernest |
|
|
|