CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

LED dot matrix blinking...
Goto page 1, 2, 3, 4  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
ernest



Joined: 11 Feb 2004
Posts: 51

View user's profile Send private message

LED dot matrix blinking...
PostPosted: Fri Dec 03, 2004 3:39 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Dec 03, 2004 8:10 am     Reply with quote

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

View user's profile Send private message Send e-mail

PostPosted: Fri Dec 03, 2004 8:35 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Dec 03, 2004 12:11 pm     Reply with quote

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

View user's profile Send private message Send e-mail

PostPosted: Fri Dec 03, 2004 12:18 pm     Reply with quote

Not having the resistor will make them bright for a while Wink 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

View user's profile Send private message

PostPosted: Mon Dec 06, 2004 2:35 am     Reply with quote

Mark wrote:
Not having the resistor will make them bright for a while Wink 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. Confused

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

View user's profile Send private message

PostPosted: Mon Dec 06, 2004 3:59 am     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Dec 06, 2004 4:18 am     Reply with quote

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. Confused

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

View user's profile Send private message Send e-mail

PostPosted: Mon Dec 06, 2004 11:05 am     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Dec 06, 2004 1:07 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Dec 06, 2004 6:24 pm     Reply with quote

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. Rolling Eyes
-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

View user's profile Send private message Send e-mail

PostPosted: Mon Dec 06, 2004 6:56 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Dec 06, 2004 10:05 pm     Reply with quote

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. Wink
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

View user's profile Send private message Send e-mail

PostPosted: Mon Dec 06, 2004 10:41 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Dec 07, 2004 12:09 am     Reply with quote

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
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2, 3, 4  Next
Page 1 of 4

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group