One of the LEDs on my seven segment display lights up brighter than the others

I am using 6 digits in multiplexing of 7 Segment Displays. I edited this code earlier for 3 Digit display which was working fine all thanks to the help from this forum. But I seem to be stuck at 6 digits the one digit keeps on lighting brighter than the others. I have tried to change the values in the startDisplay() function of the program but doesn't seem to have any effect.
Following is the code:`

#define F_CPU 16000000UL
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdio.h>


/* TIMER0_PRELOAD_VAL=255-((F_CPU/Prescaler)*Time - 1).
  For F_CPU 16 MHz, Time 1 msec is 6. */
#define TIMER0_PRELOAD_VAL 6

void startcounter(uint16_t);
volatile float frequency;
volatile float freq; 
volatile uint16_t gate_time;               // The time in msec that the gate will remain open.
volatile uint16_t timer0_ticks;   // The number of Timer0 ticks.
uint8_t counter1_overflows;       // The number of Timer / Counter1 overflows.
volatile uint8_t ready_flag;      // Flag of completion of the measurement.
volatile uint32_t counter_val;    // The total value of the measurement.

uint8_t digit[3] ;  // these are the digits to be displayed

int main()
{
  DDRD = (1<<2) | (1<<3) | (1<<4) | (1<<6) | (1<<7);
  DDRB = (1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<4) | (1<<5);
  DDRC = (1<<1) | (1<<2) ||(1<<3) | (1<<4);

  
  
  sei();
  //Serial.begin(9600);
  uint16_t gate=1000; // Se milliseconds.
  uint8_t i; // A little trick to not "clog"
             // the UART when we have a short gate time.
    
  while(1) 
  {
    i++;
    startcounter(gate);
    while(!ready_flag){};
    frequency = counter_val*(1000/gate);
    if (i>=1000/gate)
    {
    freq = frequency;
    }
    
    i=0;
  }
  return 0;
}



ISR (TIMER2_COMP_vect)
{
  //Function to run display...  
  displayNumber();
  
}

void startDisplay()
{
  
   OCR2 = 125;
  TCCR2 |= (1 << WGM21);
  TIMSK |= (1 << OCIE2);
  TCCR2 |= (1 << CS22);   // prescaler /256
  TCCR2 |= (1 << CS21);   // prescaler /256
  
  
}

void startcounter(uint16_t msecs)
{
  gate_time=msecs;
  counter1_overflows=0;
  timer0_ticks=0;
  ready_flag=0;
  
  
  TIMSK |= (1<<TOIE1);  // Enable Overflow Interrupt for Timer / Counter1.
  TIMSK |= (1<<TOIE0);  // Enable Overflow Interrupt for Timer0.
 
  // Initialize Timer0. Causes Interrupt each msec.
 
  TCNT0 = TIMER0_PRELOAD_VAL;   // Preload with the price for a time of 1 msec.
  TCCR0 |= (1<<CS01)|(1<<CS00);  // Activation with Prescaler 64.
 
  // Reset TCNT1?
  TCNT1=0;
  // Increase TCNT1 by applying pulse to PD5.
  TCCR1B |= (1<<CS10)|(1<<CS11)|(1<<CS12);
  
 
}
 
 
ISR(TIMER1_OVF_vect){
 
    counter1_overflows++;
    
    
}
 
 
ISR(TIMER0_OVF_vect){
 
    uint16_t counter1_ticks;
 
    // Counter value of Counter1.
    counter1_ticks = TCNT1;
 
    TCNT0 += TIMER0_PRELOAD_VAL;  // Preload TCNT0 for 1 msec.
 
    timer0_ticks++;
 
    // Check if gate_time has been completed. If not ISR exit?
    if (timer0_ticks < gate_time) 
    {
      startDisplay();
      return;
    }
 
    // If we lost a Timer / Counter1 interrupt increase the meter.
    if (bit_is_set(TIFR,TOV1)) counter1_overflows++;
 
    TIMSK &= ~((1<<TOIE1)|(1<<TOIE0)); // Disable Interrupt overflow for Timer0, Timer / counter1.
 
    TCCR1B &= ~((1<<CS10)|(1<<CS11)|(1<<CS12)); // Stop Timer / Counter1.
 
    TCCR0 &= ~( (1<<CS01)|(1<<CS00)); // Stop Timer0.
 
    counter_val = (counter1_overflows*65536)+counter1_ticks;
    
    ready_flag = 1;
    
}
 
void displayNumber()
{
 
    // on each call, calculates and displays the number at the next digit position 
    // call every 4 ms by a timer
    
    
    static int i = 6 ;   // static variables are initialised once only
    pickDigit (i) ;

    // calculate the number  to be displayed at postion 'i' based on the frequency.

    // note: the calculations here are quite slow and would be better done once when 
    // frequency is newly determined and not each time.
    switch( i )
    {
    case 6:
      pickNumber((int)freq %10);
      break;
    case 5:
      pickNumber(((int)freq/10)%10);
      break;
    case 4:
      pickNumber(((int)freq / 100)%10);
      break;
    case 3:
      pickNumber(((unsigned long)freq / 1000)%10);
      break;
    case 2:
      pickNumber(((unsigned long)freq / 10000)%10);
      break;
    case 1:
      pickNumber(((unsigned long)freq / 100000)%10);
      break;
    }
  
    if ( --i<=0 ) i = 7 ;  // 3 digit display ?
}




void pickDigit(int x)
{
  // Initially turn _all_ lines off to avoid ghosting
  clearLEDs();
  PORTC = (0<<5) | (0<<4) | (0<<3) | (0<<2) | (0<<1) | (0<<0);
  
  

  // select digit (still dark)
  switch(x)
    {
    case 1:
      PORTC = (1<<5) | (0<<4) | (0<<3) | (0<<2) | (0<<1) | (0<<0);
      break;
    case 2:
      PORTC = (0<<5) | (1<<4) | (0<<3) | (0<<2) | (0<<1) | (0<<0);
      break;
    case 3:
      PORTC = (0<<5) | (0<<4) | (1<<3) | (0<<2) | (0<<1) | (0<<0);
      break;
    case 4:
      PORTC = (0<<5) | (0<<4) | (0<<3) | (1<<2) | (0<<1) | (0<<0);
      break;
    case 5:
      PORTC = (0<<5) | (0<<4) | (0<<3) | (0<<2) | (1<<1) | (0<<0);
      break;
    default :
      PORTC = (0<<5) | (0<<4) | (0<<3) | (0<<2) | (0<<1) | (1<<0);
      break;
    
    }
   
}



 //Function to display a integer number:
 void pickNumber(int x)
{
   switch(x)
   {
      default:
      zero();
      break;
      case 1:
      one();
      break;
      case 2:
      two();
      break;
      case 3:
      three();
      break;
      case 4:
      four();
      break;
      case 5:
      five();
      break;
      case 6:
      six();
      break;
      case 7:
      seven();
      break;
      case 8:
      eight();
      break;
      case 9:
      nine();
      break;
   }
}
 
void clearLEDs()
{
   PORTD = (1<<2) | (1<<3) | (1<<4) | (1<<6) | (1<<7);
   PORTB = (1<<0) | (1<<1) | (1<<2);
}

// Number library for integers
void zero()
{
   PORTD = (0<<2) | (0<<3) | (0<<4) | (0<<6) | (0<<7);
   PORTB = (0<<0) | (1<<1) | (1<<2);
}

void one()
{
   PORTD = (1<<2) | (0<<3) | (0<<4) | (1<<6) | (1<<7);
   PORTB = (1<<0) | (1<<1) | (1<<2);
}

void two()
{
   PORTD = (0<<2) | (0<<3) | (1<<4) | (0<<6) | (0<<7);
   PORTB = (1<<0) | (0<<1) | (1<<2);
}

void three()
{
   PORTD = (0<<2) | (0<<3) | (0<<4) | (0<<6) | (1<<7);
   PORTB = (1<<0) | (0<<1) | (1<<2);
}

void four()
{
   PORTD = (1<<2) | (0<<3) | (0<<4) | (1<<6) | (1<<7);
   PORTB = (0<<0) | (0<<1) | (1<<2);
}

void five()
{
   PORTD = (0<<2) | (1<<3) | (0<<4) | (0<<6) | (1<<7);
   PORTB = (0<<0) | (0<<1) | (1<<2);
}

void six()
{
   PORTD = (0<<2) | (1<<3) | (0<<4) | (0<<6) | (0<<7);
   PORTB = (0<<0) | (0<<1) | (1<<2);
}

void seven()
{
   PORTD = (0<<2) | (0<<3) | (0<<4) | (1<<6) | (1<<7);
   PORTB = (1<<0) | (1<<1) | (1<<2);
}

void eight()
{
   PORTD = (0<<2) | (0<<3) | (0<<4) | (0<<6) | (0<<7);
   PORTB = (0<<0) | (0<<1) | (1<<2);
}

void nine()
{
   PORTD = (0<<2) | (0<<3) | (0<<4) | (1<<6) | (1<<7);
   PORTB = (0<<0) | (0<<1) | (1<<2);
}

Here's the thread, if I'm not mistaken. But it looks like the same problem.
https://forum.arduino.cc/t/frequency-counter-using-atmega8a-7-segment-display-keeps-flickering-only-shows-1-out-of-4-digits/985259

You say you previously had a solution. So at what point in your development did things fail? How did you develop the new code? Is it an adaptation of the previous code? What if anything did you do differently?

It doesn't works with 6 digits, I have tried editing the code, changing the OCR2 value to reconfigure the timer. But there was no improvement. Earlier it was giving no display after successfully getting the frequency counts. So I moved the startDisplay() function within the gate timer.

Please explain how it works. Give us an overview of your design.

This is basically a frequency counter, two timers are working simultaneously. One timer evaluates the frequency of the incoming signal on PD5 and the other starts the display. Now with the 6 digits I think it is taking more time and hence there is an error in the display brightness.

It sounds like you have blasted past testing stages and have made a system that can't work without many parts, so you don't know where to look. You should isolate things, like make a sketch to only display "012345" or something like that first.

Also what board/processor is this running on?

I am using Atmega8A

On a custom designed PCB? If so, what testing have you done?

I have tested for the refresh rate of the transistors signal which are driving these leds. Brighter one seem to be at 72 Hz and the others at 530 Hz.

Have you tried a sketch that only lights up all the segments evenly?

For PCB testing, I meant successful simple tests, like loading and running example sketches like "Blink". So you know that the system generally works...

Also, how did you perform the test in reply #9? Did you scope the pins?

Yes I tested this on DSO and also I have tested these displays with arduino sevseg library which works fine.

Well, sevseg is a good start, it confirms the display hardware. Next step should be, a sketch that only displays an arbritrary, fixed number on the display. But, using your timer code. Because that is what you need to verify. Once that works, try adding the frequency measurement code.

By the way, at this point I can see that you have provided important information by way of requests. That wastes a lot of time with guesswork. Please post complete information about any activities that you have performed, and other details before someone has to guess what you've done, item by item.

What you've said in reply #11 should have been mentioned in the first post.

Why 7? Shouldn't that be 6? It looks like pickDigit() will light up the same digit for 6 and 7 so that digit is on twice as long as any other.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.