View previous topic :: View next topic |
Author |
Message |
khalis
Joined: 12 Feb 2009 Posts: 54
|
7 x 4 7-Segment Problem |
Posted: Sun Jun 17, 2012 8:09 am |
|
|
Hi Guys,
Need some advises regarding to my project. Currently I'm writing codes for project which is called 7 rows x 4 columns 7-segments (Common Anode) display. I have a problem on the brightness of the display control where I want to increase the brightness. Existing firmware (don't have the source code) able to display the numbers brighter than mine. So I got curious and tried so many things but still unsuccessful.
Basically, every each row has 4bit shift register where it was linked from row 1 to 7. The input is fed from row 1 by PIC16F877A. It is a serial communication technique if i refers in the internet where the data flows from MCU to ROW 1 until ROW 7. So the steps i used to control the display are:
1. Turn off all transistors that are connected to each column.
2. Initialize the data from data row 7 to 1.
3. Turn on only transistor Column 1.
4. Turn off all transistors that are connected to each column.
5. Initialize the data from data row 7 to 1.
6. Turn on only transistor Column 2.
7. Turn off all transistors that are connected to each column.
8. Initialize the data from data row 7 to 1.
9. Turn on only transistor Column 3.
10. Turn off all transistors that are connected to each column.
11. Initialize the data from data row 7 to 1.
12. Turn on only transistor Column 4.
I used Timer2 interrupt for every 4ms and the refresh rate is about 62Hz.
When I tried to reduce the refresh rate, I could see the flickering problem and if I increase the refresh rate, the display became more dimmer.
Hope you guys could give ideas to overcome this problem in programming solution and not hardware. Many thanks in advance. |
|
![](templates/subSilver/images/spacer.gif) |
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Sun Jun 17, 2012 10:42 am |
|
|
Are you saying that the "existing firmware" version gives a brighter display than yours on the SAME hardware?
If so, how do you KNOW?
I'm having some trouble deciphering your description of the hardware. A schematic diagram would help.
Mike |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9174 Location: Greensville,Ontario
|
|
Posted: Sun Jun 17, 2012 1:15 pm |
|
|
IF you're saying that none of the hardware can be changed, then you are out of luck with respect to thinking that a software change will inprove the product.
Odds are real good the original designer optimized the code for the hardware.
The overall system performance cannot be made better by 'adjusting' the code.
It sounds like you've tried...but it won't work. If you alter the current limiting resistors in the matrix that will help, but you say we can't change the hardware, so you're stuck.
There are several solutions but unless you allow hardware modifications, I can't help. |
|
![](templates/subSilver/images/spacer.gif) |
khalis
Joined: 12 Feb 2009 Posts: 54
|
|
Posted: Sun Jun 17, 2012 5:01 pm |
|
|
I am aware that by modifying the hardware, we can have the brightness that we expected. I have an old HEX file that run the PIC and it is obviously the display has brightness higher than mine. I already compared the old with mine.
I have tried many times and has limited references on the techniques regarding to my hardware has in the internet. I started wondering if there's appropriate method to solve my problem.
From my point of view, it is not the optimization cause but the technique that i used may not gives undesirable result. |
|
![](templates/subSilver/images/spacer.gif) |
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Mon Jun 18, 2012 2:44 am |
|
|
All sounds like magic to me.
From what you describe of your software:-
(1) You're getting over 20% duty ratio for driving the LEDs.
(2) Increasing duty ratio will increase brightness.
(3) The maximum you can achieve is just shy of 25%.
(4) As I see it, there's not much more you can do.
(I'm with temtronic on this one.)
If you really are convinced that there's something in the HEX file, disassemble it.
You could also try looking at the drives to the LEDs with a 'scope.
Mike |
|
![](templates/subSilver/images/spacer.gif) |
khalis
Joined: 12 Feb 2009 Posts: 54
|
|
Posted: Mon Jun 18, 2012 4:55 am |
|
|
I am agree with you, Mike.. the max duty ratio only at 25%..i had tried before and i can see the the display start to flickering (slow pulse rate)..i tried to avoid that..yes I have the HEX file but it may takes a longer time to crack it and more over, i am not expert it that particular thing..
Is it the steps that i used to display is not efficient enough? Or is there any well known technique that i can try?
So if i want to increase the brightness, what i really need to author only the resistor that connected every each led in 7 segment, am i right? The board has 4 columns connected in parallel and share 8 resistors 100 Ohm.. |
|
![](templates/subSilver/images/spacer.gif) |
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Mon Jun 18, 2012 6:13 am |
|
|
As far as disassembly is concerned, you only need to work on the display driver part.
Again a 'scope SHOULD let you SEE what's going on.
Also simply measuring either mean LED current, or total supply current, with a DMM ought to be indicative if the brightness difference really is significant.
You're the one with the board in front of you. I'm having to guess.
The technique you outlined should be close to as good as it gets. I don't know of a magic formula for getting much better, unless there's something on the board that either you aren't aware of, or telling us.
Mike |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9174 Location: Greensville,Ontario
|
|
Posted: Mon Jun 18, 2012 6:31 am |
|
|
Unless you're willing to change those 100r resistors, not much can be done.
If you can, replace with say 47r resistors and you should get x2 the current and an increase in brightness. |
|
![](templates/subSilver/images/spacer.gif) |
khalis
Joined: 12 Feb 2009 Posts: 54
|
|
![](templates/subSilver/images/spacer.gif) |
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Tue Jun 19, 2012 3:05 pm |
|
|
Quote: | I don't have scope to do so. | Like I said before you can use a DMM to either measure mean individual segment current or total current. A further alternative is to measure the voltage across one of the 100R resistors, whilst being careful to make measurements under identical conditions. If the brightness difference is as obvious as you suggest then there should be a significant difference in the readings.
Quote: | I have read in Arduino forum and he stated that like we can multiplex digits or segments. What does it mean ? | He means that you can light the display one digit at a time (as I believe you're doing, max duty ratio for 4 digits ~25%), or light all the same segments at a time (max duty ratio ~12.5% for any number of digits). If you think of your display as a matrix with rows and columns, you can either activate either by row or column. Which way round you go is set by whether you fit the current limiting resitors in the row or column leads. You don't have a free choice.
Mike
EDIT
Quote: | I used Timer2 interrupt for every 4ms and the refresh rate is about 62Hz.
When I tried to reduce the refresh rate, I could see the flickering problem and if I increase the refresh rate, the display became more dimmer. | You don't have access to a 'scope, so HOW do you KNOW that your figures are correct?
You've been told that the original designer probably optimsed his code to suit the hardware, and it's unlikely you'll find a magic formula to improve with software. However, it's possible to ruin the performance with poor software. A re-reading some of your statements suggests that you MAY have compromised the system. |
|
![](templates/subSilver/images/spacer.gif) |
khalis
Joined: 12 Feb 2009 Posts: 54
|
|
Posted: Thu Jun 21, 2012 7:37 pm |
|
|
For the individual current measurement by using DMM, i'll try soon. For the Timer2 interrupt for every 4ms, i do not have tool to confirm it. To test the display, i had commented out all in-related subroutines / features that i have to see whether there's in-related subroutines affected the display subroutine and unfortunately, the result still the same.
My 1st intention to issue out my problem is to find out how many possibilities of multiplexing techniques (ex data orientation etc) we could have so that i can try it out to which is suites for my hardware..I just found out that the timing for shift-out data from ROW1 to 7 also contributed to dimmer problem. |
|
![](templates/subSilver/images/spacer.gif) |
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Fri Jun 22, 2012 10:46 am |
|
|
Quote: | if I increase the refresh rate, the display became more dimmer. |
With good code, increasing the refresh rate should only give marginal brightness reduction.
If you want to speed things up (excuse the pun):-
(1) Show us a display drive schematic.
(2) Show us your display driving code.
Mike |
|
![](templates/subSilver/images/spacer.gif) |
khalis
Joined: 12 Feb 2009 Posts: 54
|
|
Posted: Sat Jun 23, 2012 12:44 pm |
|
|
Hi Mike,
The fraction of my source code as follows:
1: Display Control
Code: |
void display_power_control(int8 pin_select)
{
output_low(ENABLE_7SEGMENT_MASTER); //Enable 74ls244 (COL_LATCH_EN)
output_high(ENABLE_7SEGMENT_CLKOUT); //COL_LATCH
switch(pin_select)
{
Case 4:
output_low(DISP1EN_UIEDIT); //D0
output_low(DISP2EN_UIUP); //D1
output_low(DISP3EN_UIDOWN); //D2
output_high(DISP4EN_UISTORE); //D3
break;
Case 3:
output_low(DISP1EN_UIEDIT);
output_low(DISP2EN_UIUP);
output_high(DISP3EN_UIDOWN);
output_low(DISP4EN_UISTORE);
break;
Case 2:
output_low(DISP1EN_UIEDIT);
output_high(DISP2EN_UIUP);
output_low(DISP3EN_UIDOWN);
output_low(DISP4EN_UISTORE);
break;
Case 1:
output_high(DISP1EN_UIEDIT);
output_low(DISP2EN_UIUP);
output_low(DISP3EN_UIDOWN);
output_low(DISP4EN_UISTORE);
break;
Case 5:
output_low(DISP1EN_UIEDIT);
output_low(DISP2EN_UIUP);
output_low(DISP3EN_UIDOWN);
output_low(DISP4EN_UISTORE);
break;
}
output_low(ENABLE_7SEGMENT_CLKOUT);
output_high(ENABLE_7SEGMENT_MASTER);
}
void write_serial_data(int8 no)
{
for(i = 0 ; i <= 7 ; i++)
{
output_low(SCOUTEN_UIZONE); //MCU_CLK_IN
if(bit_test(no,(7 - i)) == TRUE)
{
output_high(SDOUTEN_UIRES); //MCU_DATA_IN
}
else
{
output_low(SDOUTEN_UIRES);
}
output_high(SCOUTEN_UIZONE);
}
}
void display_current_data(int1 mode)
{
int8 i;
if(display_rate_enable == TRUE)
{
display_power_control(5);
switch(display_sequence)
{
case 0:
display_sequence = 1;
output_low(SERIAL_DATA_ENABLE); ////ENABLE 74LS244 (DISP_DATA_EN)
write_serial_data(table[0]);
write_serial_data(table[0]);
write_serial_data(table[0]);
write_serial_data(data_2be_displayed[27]);
write_serial_data(data_2be_displayed[23]);
write_serial_data(data_2be_displayed[19]);
write_serial_data(data_2be_displayed[15]);
write_serial_data(data_2be_displayed[11]);
write_serial_data(data_2be_displayed[7]);
write_serial_data(data_2be_displayed[3]);
output_high(SERIAL_DATA_ENABLE);
display_power_control(1);
break;
case 1:
display_sequence = 2;
output_low(SERIAL_DATA_ENABLE);
write_serial_data(table[0]);
write_serial_data(table[0]);
write_serial_data(table[0]);
write_serial_data(data_2be_displayed[26]);
write_serial_data(data_2be_displayed[22]);
write_serial_data(data_2be_displayed[18]);
write_serial_data(data_2be_displayed[14]);
write_serial_data(data_2be_displayed[10]);
write_serial_data(data_2be_displayed[6]);
write_serial_data(data_2be_displayed[2]);
output_high(SERIAL_DATA_ENABLE);
display_power_control(2);
break;
case 2:
display_sequence = 3;
output_low(SERIAL_DATA_ENABLE);
write_serial_data(table[0]);
write_serial_data(table[0]);
write_serial_data(table[0]);
write_serial_data(data_2be_displayed[25]);
write_serial_data(data_2be_displayed[21]);
write_serial_data(data_2be_displayed[17]);
write_serial_data(data_2be_displayed[13]);
write_serial_data(data_2be_displayed[9]);
write_serial_data(data_2be_displayed[5]);
write_serial_data(data_2be_displayed[1]);
output_high(SERIAL_DATA_ENABLE);
display_power_control(3);
break;
case 3:
display_sequence = 0;
output_low(SERIAL_DATA_ENABLE);
write_serial_data(table[0]);
write_serial_data(table[0]);
write_serial_data(table[0]);
write_serial_data(data_2be_displayed[24]);
write_serial_data(data_2be_displayed[20]);
write_serial_data(data_2be_displayed[16]);
write_serial_data(data_2be_displayed[12]);
write_serial_data(data_2be_displayed[8]);
write_serial_data(data_2be_displayed[4]);
write_serial_data(data_2be_displayed[0]);
output_high(SERIAL_DATA_ENABLE);
display_power_control(4);
break;
}
display_rate_enable = FALSE;
}
}
|
2: Fuses, timers' initialization
Code: |
#include <16F877A.h>
#fuses HS,NOWDT,NOPUT,NOBROWNOUT,NOPROTECT
#use delay(clock = 4M)
//Set-up timer 1
setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1|T1_CLK_OUT);
//Set-up timer 2
setup_timer_2(T2_DIV_BY_4, 250 , 5);
//Set-up port direction input or output 1 = Input 0 = Output
set_tris_a(0x00); //set Port A as an output
output_a(0xFF);
set_tris_b(0xFF); //Set Port B as an input
set_tris_c(0x00); //Set Port C as an output
output_c(0xFF);
set_tris_d(0x00); //Set Port D as an output
output_d(0xFF);
//Set-up interrupt
disable_interrupts(INT_RB);
enable_interrupts(INT_TIMER1);
enable_interrupts(INT_TIMER2);
enable_interrupts(GLOBAL);
|
The schematics that I'm working on as follows:
1.Control Board
https://viewer.zoho.com/docs/oa70o0
2.Display Board
https://viewer.zoho.com/docs/maabaAh
Additional info:
1. Currently I connected CONTROL BOARD to 10 DISPLAY BOARD(s).
2. Power comes from 12v 1.5A adapter.
Many thanks.
![Very Happy](images/smiles/icon_biggrin.gif) |
|
![](templates/subSilver/images/spacer.gif) |
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Sun Jun 24, 2012 3:21 am |
|
|
This is rather like pulling teeth.
You've not supplied enough information to work out exactly what's going on.
(a) I can't tell which pin you're using for each data line, so can't give a complete answer.
(b) I can't see how you set your timing for updating the display.
Some of your code is not as slick as it could be.
However, I can see where your MAJOR problem lies.
Each time you update the display you're
(1) Turning off the display.
(2) Going round this bit of code 80 times Code: |
{
output_low(SCOUTEN_UIZONE); //MCU_CLK_IN
if(bit_test(no,(7 - i)) == TRUE)
{
output_high(SDOUTEN_UIRES); //MCU_DATA_IN
}
else
{
output_low(SDOUTEN_UIRES);
}
output_high(SCOUTEN_UIZONE);
} | (3) Turning the display back on.
The loop is far too slow.
With a 4MHz clock, the loop takes ~430us to go round 8 times.
That's 4.3ms total for all 10 boards, plus the time for other bits and pieces.
You are turning the display on for say 4ms then waiting >4ms for the update.
The display is off for longer than it's on.
No wonder it's dim.
You can speed up the loop by:-
(1) Using fast_io.
(2) replace the bit_test with some thing faster
Something like this goes round about three times faster than yours with fast_io Code: | for(i = 0 ; i <= 7 ; i++)
{
output_low(SCOUTEN_UIZONE); //MCU_CLK_IN
if( no & 0x80 )
{
output_high(SDOUTEN_UIRES); //MCU_DATA_IN
}
else
{
output_low(SDOUTEN_UIRES);
}
no *= 2;
output_high(SCOUTEN_UIZONE);
} |
Convert to inline code goes faster still.
The PIC16F877A has SPI capability.
Using the right pins for your serial transfer you can go even faster with SPI.
The ultimate would be to use something like 4094 rather than 4015 serial registers.
Whilst the display is on you update the internal register for the next digit, then latch in the new data to update the display.
That way you reduce the update time to a few us.
In effect you update the display, with the next segment data, whilst the display is showing the current data.
Mike |
|
![](templates/subSilver/images/spacer.gif) |
khalis
Joined: 12 Feb 2009 Posts: 54
|
|
Posted: Sun Jun 24, 2012 5:53 am |
|
|
Thanks for your explanation but the code that i gave to you was the subroutine to control the display. So every time timer2 interrupt, it updates the flag to refresh it. The interrupt subroutine as shown below:
Code: |
#INT_TIMER2
void isr_timer2()
{
clear_interrupt(int_timer2);
set_timer2(0);
if(display_rate_enable == FALSE)
{
display_rate_enable = TRUE;
}
}
|
Yes, I am aware that i turn off the display every time i want to update each digit but if i exclude it, of course it is more brighter but it will just show DIGIT 8 instead of the digit that i want to display. You also well aware that i use serial to parallel technique to update every digit in rows and if i do not turn off the displays, of course we could see the data flows and because it happens so fast, we just see a NO 8..am i right?
Every pin that i used in the firmware, i commented on the right side so that you can refer it in the schematic that i gave it to you. One more thing, the 4 pins to control 7 segment common anode are shared as input also and i think it is not wise to have fast_io..
I am really have lost idea to increase the brightness.. ![Idea](images/smiles/icon_idea.gif) |
|
![](templates/subSilver/images/spacer.gif) |
|