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 CCS Technical Support

5x7 Led Dot Matrix Flickering Problem

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
veerabahu



Joined: 20 Aug 2013
Posts: 16

View user's profile Send private message

5x7 Led Dot Matrix Flickering Problem
PostPosted: Thu Jan 21, 2016 1:10 am     Reply with quote

Hi Experts

I am developing code for 5(Column)x7(row) Led dot matrix display,I am using 18f4520 IC. My aim is to receive the 16 characters through UART and display it in 16 digits, 5(Column)x7(row) Led Dot matrix. As a first step of this project i developed the code for displaying the fixed character like "A,B,C,D,E,F,G,H" in first 8 digit 5x7 led dot matrix. So for 8 characters i want to control 40 columns via shift register (74hc595). The rows are connected with B port IO's.
At first I tried to execute the code with 10MHZ Clock speed. I got the output but i faced the flickering problem. To avoid the flickering problem I reduced the delays in between the each LED'S switching. Result, I got flickering arrested but brightness decreased.
So I planned to increase the clock speed to 40 MHz with the help of configuration H4 in fuses. But i didnt see any change in the speed of the crystal. I didn't see any change in the Display.

Please help me to solve this problem. I attached my code below.
Code:

#include <18F4520.h>
#include <stdio.h>
#fuses H4,NOWDT,BROWNOUT,PROTECT,PUT
#use delay(clock=40000000)

#define SDATA_PIN  PIN_C2   // SER (pin 14 of first 74HC595)
#define SCLK_PIN   PIN_C0   // SRCLK  (pin 11 of all 74HC595)
#define RCLK_PIN   PIN_C1   // RCLK    (pin 12 of all 74HC595)

//LED bit assignment.
#define LED_1      0x01
#define LED_2      0x02
#define LED_3      0x04
#define LED_4      0x08
#define LED_5      0x10
#define LED_6      0x20
#define LED_7      0x40 //Temp
#define LED_8      0x80

#define NO_LED     0x0000
#define ALL_LED    0x7EFE
unsigned int8 ui8alphabet=0;
unsigned int8 ui8Character=0;
const unsigned int8 Alphabets[130]={0x7E, 0x09, 0x09, 0x09, 0x7E, // A
                               0x7f, 0x49, 0x49, 0x49, 0x36,  // B
                               0x3e, 0x41, 0x41, 0x41, 0x00,
                               0x7f, 0x41, 0x41, 0x24, 0x1A,
                               0x7f, 0x49, 0x49, 0x49, 0x00,
                               0x7f, 0x09, 0x09, 0x09, 0x01,
                               0x3e, 0x41, 0x41, 0x49, 0x7a,
                               0x7f, 0x08, 0x08, 0x08, 0x7f,
                               0x00, 0x41, 0x7f, 0x41, 0x00,  // I
                               0x20, 0x40, 0x41, 0x3f, 0x01,
                               0x7f, 0x08, 0x12, 0x24, 0x41,
                               0x7f, 0x40, 0x40, 0x40, 0x60,
                               0x7f, 0x02, 0x04, 0x02, 0x7f,
                               0x7f, 0x04, 0x08, 0x10, 0x7f,
                               0x3e, 0x41, 0x41, 0x41, 0x3e,
                               0x7f, 0x09, 0x09, 0x09, 0x06,
                               0x3e, 0x41, 0x51, 0x21, 0x5e,
                               0x7f, 0x09, 0x19, 0x29, 0x46,
                               0x46, 0x49, 0x49, 0x49, 0x31,  // S
                               0x01, 0x01, 0x7f, 0x01, 0x01
                               0x3f, 0x40, 0x40, 0x40, 0x3f,
                               0x1f, 0x20, 0x40, 0x20, 0x1f,
                               0x3f, 0x40, 0x30, 0x40, 0x3f,
                               0x63, 0x14, 0x08, 0x14, 0x63,
                               0x07, 0x08, 0x70, 0x08, 0x07,
                               0x61, 0x51, 0x49, 0x45, 0x43 // Z*/
                               };
//LED control for Sequence
const unsigned int8 gui8ledCtrl[8] = { 
                                           LED_1,   
                                           LED_2,     
                                           LED_3,     
                                           LED_4,     
                                           LED_5,     
                                           LED_6,     
                                           LED_7,   
                                           LED_8}; 

void load_reg(void)
{
output_high(RCLK_PIN);     // Make a positive clock pulse
output_low(RCLK_PIN);
}

void io_init(void)
{
   set_tris_b(0x00);
   set_tris_a(0x00);
   set_tris_c(0x00);
   
}

//-------------------------------------
// This function sends one byte to the chain of
// 74HC595 shift registers.

void send_byte(unsigned int8 data)
{
 char i;

 for(i = 0; i < 8; i++)           // Send 8 bits
    {
     if(data & 0x80)
       {     
        output_high(SDATA_PIN);
       }
     else
       {
        output_low(SDATA_PIN);
       }

     output_high(SCLK_PIN);     // Make a positive clock pulse
     output_low(SCLK_PIN);
 
     data <<= 1;                // Get next bit into MSB position       
   }
}   

//================================
void main()
{
unsigned int8 ui8Cnt=0;   

io_init();
 
// Initialize the 74HC595 control pins.
output_low(SDATA_PIN);
output_low(SCLK_PIN);
output_low(RCLK_PIN);

while(1)
{
      for(ui8alphabet=0;ui8alphabet<40;ui8alphabet++)
      {
            switch(ui8alphabet)
            {
               case 0:
               case 1:
               case 2:
               case 3:
               case 4:
               case 5:
               case 6:
               case 7:
                     send_byte(NO_LED);
                     send_byte(NO_LED);
                     send_byte(NO_LED);
                     send_byte(NO_LED);
                     send_byte(NO_LED);
                     send_byte(NO_LED);
                     send_byte(NO_LED);
                     send_byte(NO_LED);
                     send_byte(NO_LED);
                     send_byte(gui8ledCtrl[ui8alphabet]);
                     load_reg();
                   
                     for( ui8Cnt=0; ui8Cnt<7; ui8Cnt++ )
                     {
                        if( Alphabets[ui8alphabet] & ( ((unsigned int8)0x01) << ui8Cnt ) )
                        {
                            output_b(gui8ledCtrl[ui8Cnt]);
                            delay_us(200);
                       
                        }
                     }
                 
                   
               break;   
               case 8:
               case 9:
               case 10:
               case 11:
               case 12:
               case 13:
               case 14:
               case 15:
                     send_byte(NO_LED);
                     send_byte(NO_LED);
                     send_byte(NO_LED);
                     send_byte(NO_LED);
                     send_byte(NO_LED);
                     send_byte(NO_LED);
                     send_byte(NO_LED);
                     send_byte(NO_LED);                 
                     send_byte(gui8ledCtrl[ui8alphabet-8]);
                     send_byte(NO_LED);
                     load_reg();
                     for( ui8Cnt=0; ui8Cnt<7; ui8Cnt++ )
                     {
                        if( Alphabets[ui8alphabet] &  ( ((unsigned int8)0x01) << ui8Cnt ) )
                        {
                            output_b(gui8ledCtrl[ui8Cnt]);
                            delay_us(200);
                         
                        }
                     }
               break;
               case 16:
               case 17:
               case 18:
               case 19:
               case 20:
               case 21:
               case 22:
               case 23:
                     send_byte(NO_LED);
                     send_byte(NO_LED);
                     send_byte(NO_LED);
                     send_byte(NO_LED);
                     send_byte(NO_LED);
                     send_byte(NO_LED);
                     send_byte(NO_LED);
                     send_byte(gui8ledCtrl[ui8alphabet-16]);                 
                     send_byte(NO_LED);
                     send_byte(NO_LED);
                     load_reg();

                    for( ui8Cnt=0; ui8Cnt<7; ui8Cnt++ )
                     {
                        if( Alphabets[ui8alphabet] &  ( ((unsigned int8)0x01) << ui8Cnt ) )
                        {
                            output_b(gui8ledCtrl[ui8Cnt]);
                            delay_us(200);
                           
                        }
                     }
               break;
               case 24:
               case 25:
               case 26:
               case 27:
               case 28:
               case 29:
               case 30:
               case 31:
                     send_byte(NO_LED);
                     send_byte(NO_LED);
                     send_byte(NO_LED);
                     send_byte(NO_LED);
                     send_byte(NO_LED);
                     send_byte(NO_LED);
                     send_byte(gui8ledCtrl[ui8alphabet-24]);
                     send_byte(NO_LED);                 
                     send_byte(NO_LED);
                     send_byte(NO_LED);
                     load_reg();
                    for( ui8Cnt=0; ui8Cnt<7; ui8Cnt++ )
                     {
                        if( Alphabets[ui8alphabet] &  ( ((unsigned int8)0x01) << ui8Cnt ) )
                        {
                            output_b(gui8ledCtrl[ui8Cnt]);
                            delay_us(200);
                           
                        }
                     }
               break;
               case 32:
               case 33:
               case 34:
               case 35:
               case 36:
               case 37:
               case 38:
               case 39:
                     send_byte(NO_LED);
                     send_byte(NO_LED);
                     send_byte(NO_LED);
                     send_byte(NO_LED);
                     send_byte(NO_LED);
                     send_byte(gui8ledCtrl[ui8alphabet-32]);
                     send_byte(NO_LED);
                     send_byte(NO_LED);                 
                     send_byte(NO_LED);
                     send_byte(NO_LED);
                     load_reg();
                     for( ui8Cnt=0; ui8Cnt<7; ui8Cnt++ )
                     {
                        if( Alphabets[ui8alphabet] &  ( ((unsigned int8)0x01) << ui8Cnt ) )
                        {
                            output_b(gui8ledCtrl[ui8Cnt]);
                            delay_us(200);
                           
                        }
                     }
               break;
             
            }
      }
   }
}

Are my configuration bits correct for 40 MHz clock frequency ? Or is there any other way for improving the brightness of display and arresting flicker as well ?

Thanks in advance
temtronic



Joined: 01 Jul 2010
Posts: 9243
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Thu Jan 21, 2016 6:34 am     Reply with quote

re: LED brightness

How bright an LED looks is based on two things, 1) time it is on and 2) current it draws.

When you increased the 'loop ' speed to get rid of the flickering, you reduced the time an LED was on...so it got dimmer. The easy way yo compensate for that is to incease the LED current BUT be careful too much current for too much time WILL burn out the LED.
There's actually a fair amount of 'math' you can do to get it to work or just reduce the LED resistors by say 50%. Try that,if not enough, reduce by another 50%. Just be careful.

On a lot of 'multiplexed' displays ( which is what you've made), the mfr allows 10* the normal current for the LEDs. The problem is that if the 'multiplexing' stops, the LEDs will burn out.

Jay
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Thu Jan 21, 2016 6:44 am     Reply with quote

I believe you should have loads of time to handle this with 10MHz clock.
That's working at 2.5 MIPs, or 0.4us per machine cycle.

You need to completely update the display at say 100Hz ie once every 10ms.
Each update requires you to active each of your 8 rows in turn.
That's 1.25ms per row.

So the sequence goes like this:-


1) Turn off all rows. (ie portB drives)
2) Send data to row0. (ie data for the 40 LEDs in row0)
_3) Latch row data.
_4) Activate appropriate row. ( ie row0 at start)
_5) Send data for next row.
_6) Delay.
_7) Turn off all rows.
_8) Loop round to 3.


The biggest time consumer is element 5.
You're sending 40 data bits.
Should take ~10 machine cycles each.
So total for element 5 is 40*4us = 160us.
Leaves about 1ms for delay in element 6.

Mike
EDIT

Jay and I are assuming you do have current limiting resistors.
That's 40 off, ie 1 in each lead, from the matrix to the '595.
And NOT 8 off in the port B connections.

Power considerations also suggest you may need to buffer port B.

Do the maths.
Start from an assumed average current for a reasonably bright LED, say 1mA.
Multiply by 8 for the multiplexing to get your resistor value, now 8mA.
Each '595 port handles this 8mA, should be OK
Multiply by a further 40 for the case where ALL the LEDs in a row are ON, now 320mA.
That current will probably destroy your PIC, hence the buffer.
Check with the PIC data sheet.
You don't tell us which way round your matrix is arranged, so can't help further.
Ttelmah



Joined: 11 Mar 2010
Posts: 19540

View user's profile Send private message

PostPosted: Thu Jan 21, 2016 8:15 am     Reply with quote

The big improvement would be to use the compiler SPI routines, or even better the SPI hardware. Currently the bytes are being clocked out using a software loop. This could be done probably 3* as fast by the compiler routines and perhaps 30* as fast using the hardware.....
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Fri Jan 22, 2016 3:54 am     Reply with quote

In your original post you say you want to drive 16 digits. That's 80 columns.
So your drive requirement per column stays the same but per row is doubled.
It's a simple fact of life for mux displays, one of either row or column drivers have to be able to drive the entire display.
Also bear in mind your display power supply has to be able to handle current which varies rapidly from ~zero to the maximum of (average LED current ) * ( No of LEDs).

With only half your display assembled you can get a feel for the intended whole display by running code as though all 16 digits were there.
(Simply send dummy data to the missing digits.)

As soon as you get your code to do other tasks you will get weird modulations in the display.
To make the display stable you need to accurately control the time each row is lit.
The easiest way is to use a timer interrupt.

The interrupt routine:-
a) Turns off all the row drivers.
b) Latches new data into the '595s.
c) Turns on the next row driver.
d) Sets an display_update_flag to tell main to prepare and send the next row data bits.
(It's important to turn ALL the LEDs off whilst the display updates to prevent ghosting.)

Main polls the display_updated_flag and does the rest.
Using either the CCS supplied '595 driver or the hardware SPI will seriously reduce your software overhead.

Mike
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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