![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
veerabahu
Joined: 20 Aug 2013 Posts: 16
|
5x7 Led Dot Matrix Flickering Problem |
Posted: Thu Jan 21, 2016 1:10 am |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9170 Location: Greensville,Ontario
|
|
Posted: Thu Jan 21, 2016 6:34 am |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Thu Jan 21, 2016 6:44 am |
|
|
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. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19359
|
|
Posted: Thu Jan 21, 2016 8:15 am |
|
|
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..... |
|
![](templates/subSilver/images/spacer.gif) |
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Fri Jan 22, 2016 3:54 am |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|