Electronic – arduino – Multiplexing two 7-Segment displays (Ghosting issues)

arduinodisplaymultiplexer

I am currently working on a simple scoreboard using two 7 segment displays, a shift register (74HC595N), two PNP transistors (2N3906) and an arduino uno.

Each 7 segment display is common anode, however one display is Blue with a forward voltage of ~3.3V, the other display is Red and has a forward voltage of ~2V.

I am using 220 Ohm current limiting resistors in series with the shift register and the cathodes of the LEDs. (I suspect this might be part of my problem as each display has a different voltage drop across the LEDs.)

I am attempting to multiplex the displays however I am experiencing issues with ghosting. I am using timer1 on the arduino in order to facilitate this behavior.

I have set up the timer with the following code:

// Setup TIMER2
/* First disable the timer overflow interrupt while we're configuring */
TIMSK2 &= ~(1<<TOIE2);

/* Configure timer2 in normal mode (pure counting, no PWM etc.) */
TCCR2A &= ~((1<<WGM21) | (1<<WGM20));
TCCR2B &= ~(1<<WGM22);

/* Select clock source: internal I/O clock */
ASSR &= ~(1<<AS2);

/* Disable Compare Match A interrupt enable (only want overflow) */
TIMSK2 &= ~(1<<OCIE2A);

/* Now configure the prescaler to CPU clock divided by 128 */
TCCR2B |= (1<<CS22)  | (1<<CS20); // Set bits
TCCR2B &= ~(1<<CS21);             // Clear bit

/* We need to calculate a proper value to load the timer counter.
 * The following loads the value 131 into the Timer 2 counter register
 * The math behind this is:
 * (CPU frequency) / (prescaler value) = 125000 Hz = 8us.
 * (desired period) / 8us = 125.
 * MAX(uint8) + 1 - 125 = 131;
 */
/* Save value globally for later reload in ISR */
tcnt2 = 5; 

/* Finally load end enable the timer */
TCNT2 = tcnt2;
TIMSK2 |= (1<<TOIE2);

On timer overflow the following function executes:

ISR(TIMER2_OVF_vect){

 // Turn off the active display
  if(active_display == 0){
    digitalWrite(BLUETRANS, LOW);
  }
  else{
    digitalWrite(REDTRANS, LOW);
  }

  delayMicroseconds(1000);

  // Toggle Display
  active_display ^= 1;

  // Shift out screen bits
  if(active_display == 0){
    displayDigit(blueByte);
  }
  else{
    displayDigit(redByte);
  }

  // Turn display back on
  if(active_display == 0){
    digitalWrite(BLUETRANS, HIGH);
  }
  else{
    digitalWrite(REDTRANS, HIGH);
  }
  // Reload the timer
  TCNT2 = tcnt2;
}

I do not fully understand the use of Timer2, so any help there would be appreciated as well. I understand that the timer counts up until the specified overflow value and then executes the ISR. However, my attempts at reducing the refresh rate of the two displays seems to make my program un responsive.

I believe I am correctly multiplexing the display:

  1. Turn off active display
  2. Shift bits into the shift register for other display
  3. Turn on other display

Unfortunately I cannot seem to reduce the ghosting in the red display (the ghosting does not seem to occur in the blue display).

Any help would be greatly appreciated!

I understand that I may not have included all relevant information, so ask and you shall receive!

Thanks!

EDIT 1

Thanks to Justing I now have a much better grasp on how Timer2 works on the Arduino. Thank you for that.

Unfortunately even at 60 Hz I can see a significant ghosting effect, along with a nasty, noticeable flashing as it alternates between the displays. With my new knowledge of Timer1 I was able to successfully increase the refresh rate up to 244Hz. My current circuit follows this basic design:

My basic circuit design

As stated previously my current limiting resistors are 220 Ohms. Could the differing forward voltages between the BLUE 7-seg display and the RED 7-seg display be causing this ghosting issue? Again, the only digit experiencing this issue is the RED display, the display with the lower forward voltage (2V [red] vs 3V [blue]). If this is indeed the cause would using an additional 8 resistors for the second display fix this issue? I was hoping I could get away with fewer resistors to save myself some soldering in the future but if it fixes this display issue then it would be worth it.

Any more ideas guys? Thanks!

EDIT 2

I am posting my displayDigit function:

void displayDigit(byte screen){
    // Shift data into the shift register
    digitalWrite(latchPin, 0); // LATCH LOW TO SHIFT
    shiftOut(dataPin, clockPin, MSBFIRST, screen);  
    digitalWrite(latchPin, 1); // ENABLE SHIFTED BITS
}

EDIT 3

Could my 2N3906 PNP transistors be to blame? It seems to me that while the transistors allow the display to turn on very quickly, turning them off occurs much slower. Allowing the red digit to "see" the previous digits value. However, this does not explain why there is no ghosting on the Blue display. Can I easily "pull-up" the anode of the display with a resistor to aid the transistor in its "off" state? "Off" here is technically Vcc (5V) because of the Common Anode design. The display operates when the anode is pulled to ground.

FINAL EDIT

My thanks go out to Myforwik for providing the most succinct and also the most helpful answer to my question. My ISR now looks like this:

ISR(TIMER2_OVF_vect){

 // Turn off the active display
  if(active_display == 0){
    digitalWrite(BLUETRANS, HIGH);
  }
  else{
    digitalWrite(REDTRANS, HIGH);
  }

  delayMicroseconds(1000);

  // Toggle Display
  active_display ^= 1;

  // Shift out screen bits
  if(active_display == 0){
    displayDigit(blueByte);
  }
  else{
    displayDigit(redByte);
  }

  // Turn display back on
  if(active_display == 0){
    digitalWrite(BLUETRANS, LOW);
  }
  else{
    digitalWrite(REDTRANS, LOW);
  }
  // Reload the timer
  TCNT2 = tcnt2;
}

It turns out that I was overlooking some of the most fundamental parts of my code. Both screens were on at any given instant, plaguing me with this ghosting issue which wasn't really a ghosting issue at all.

Many thanks to justing who provided possibly the best explanation I have ever seen on how to set up the timer on the Arduino. Mike DeSimone and Oli Glaser also helped a great deal when it came to troubleshooting my circuit. I cannot express to you guys how much I appreciate your help!

While my actual issue was extremely basic, I hope all of the responses found on this page can be of use to someone, somewhere in the future!

Thanks again!

Best Answer

The problem is you have on and off mixed up.

The pnp transistor will be at cutoff when the output is high, not low.

So you are turning both of your displays on during the 1000us wait.