6 digit 16 segment display - LED ghosting

I bought a common anode 6 digit 16 segment display, and i wanted to make a clock with it. I managed to get this to work with 2 74hc595 shift register and 2 uln2803, but i'm experiencing led ghosting and i dont know if its my code, or the circuit that needs to be improved.
I hope someone here can help me.

Similar display: display

The shifter.h library is from here: shifter

The code is similar to these: code

#include <Wire.h>
#include "RTClib.h"

RTC_DS3231 rtc;

#include <Shifter.h>
#define SER_Pin 11 //SER_IN
#define RCLK_Pin 8 //L_CLOCK
#define SRCLK_Pin 12 //CLOCK
#define NUM_REGISTERS 2
Shifter shifter(SER_Pin, RCLK_Pin, SRCLK_Pin, NUM_REGISTERS);

const static byte numeros[10][16] = {
  //a,b,c,d,e,f,g,h,j,k,l,m,n,o,p,q
  {1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0}, // 0
  {1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0}, // 1
  {1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1}, // 2
  {1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1}, // 3
  {0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1}, // 4
  {1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1}, // 5
  {1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1}, // 6
  {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0}, // 7
  {1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1}, // 8
  {1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1}, // 9
};
//*    - -         a    b
//*   |\|/|    h  i  j  k  c
//*    - -         p     l
//*   |/|\|    g o n m d
//*    - -        f     e

int digito1 = 7;
int digito2 = 6;
int digito3 = 5;
int digito4 = 4;
int digito5 = 3;
int digito6 = 2;

void setup() {
#ifndef ESP8266
  while (!Serial); // for Leonardo/Micro/Zero
#endif

  Serial.begin(9600);

  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }

  if (rtc.lostPower()) {
    Serial.println("RTC lost power, lets set the time!");
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
  }
  
  pinMode(digito1, OUTPUT);
  pinMode(digito2, OUTPUT);
  pinMode(digito3, OUTPUT);
  pinMode(digito4, OUTPUT);
  pinMode(digito5, OUTPUT);
  pinMode(digito6, OUTPUT);

}

void loop() {

  DateTime now = rtc.now();


  int su = now.second() - (int(now.second() / 10) * 10);
  int sd = int(now.second() / 10); sd = sd - (int(sd / 10) * 10);
  
  int mu = now.minute() - (int(now.minute() / 10) * 10);
  int md = int(now.minute() / 10); md = md - (int(md / 10) * 10);
  
  int hu = now.hour() - (int(now.hour() / 10) * 10);
  int hd = int(now.hour() / 10); hd = hd - (int(hd / 10) * 10);

  for (int j = 0; j < 16; j++) {
    shifter.setPin(j, HIGH);
    shifter.write();

    digitalWrite(digito1, numeros[hd][j]);
    digitalWrite(digito2, numeros[hu][j]);
    digitalWrite(digito3, numeros[md][j]);
    digitalWrite(digito4, numeros[mu][j]);
    digitalWrite(digito5, numeros[sd][j]);
    digitalWrite(digito6, numeros[su][j]);

    //delay(1);
    shifter.clear();
    shifter.write();
  }
}

Try this:

  for (int j = 0; j < 16; j++) {

    digitalWrite(digito1, numeros[hd][j]);
    digitalWrite(digito2, numeros[hu][j]);
    digitalWrite(digito3, numeros[md][j]);
    digitalWrite(digito4, numeros[mu][j]);
    digitalWrite(digito5, numeros[sd][j]);
    digitalWrite(digito6, numeros[su][j]);

    shifter.setPin(j, HIGH);
    shifter.write();
    delay(1);
    shifter.clear();
    shifter.write();
  }

Thx man, that really worked

The "common anode" takes all the segment currents. You normally use a PNP transistor with no series resistor.

You normally put the series resistors in the segment cathodes. Note that 330R is about 8mA per segment.

With 330R in the "common", you limit the peak segment current to about 0.5mA when all 14 segments are lit.

Common cathode displays are easier with an AVR. You use NPN (or ULN2803) for the common. And the AVR Port pins can drive the segments ok (with series resistors).

David.

Martulas:
Thx man, that really worked

Do you understand why? Do you see how your code was causing the ghosting?

With 330R in the "common", you limit the peak segment current to about 0.5mA when all 14 segments are lit.

But all 14 segments are never lit. In fact only one segment is ever lit at a time because, unusually, the OP has chosen to multiplex by segment rather than by digit. So the full 8mA goes to one segment, but the average current is still low because of the 1:16 multiplex ratio.

To achieve more brightness, PNP could be used with lower series resistors as you suggest. For even more brightness, swap to multiplexing by digit to achieve 1:6 multiplex ratio. Then as you say, 16 series resistors would be needed on cathodes instead of anodes. Could use tpic6c595 to replace 74hc595+uln2803 to simplify the circuit.

For a much simpler circuit, an ht16k33 chip/breakout board could be used.

My apologies. I looked at the wiring but not the code! It never crossed my mind that anyone would multiplex segments instead of digits.

Yes, a proper driver chip would be a lot easier. And you can probably dim the display too.

David.

No, i dont see how my code was causing the ghosting.
Before this circuit and code, i tried to multiplex the digits, but with the same problem.

And if i want more brightness i need to put the PNP's in the anodes?

The problem with your previous code was that it changed the anode data before it switched off the cathode. So the anode signals "bled" into the next cathode. You must switch off the cathode before you change the anode signals. Or switch off the anode signals before you change the cathode. It does not matter which you do, but if you switch one while the other is still on you will get bleeding.

Before you add transistors on the anodes, you could try reducing the value of the anode resistors. The lowest value you can use depends on the forward voltage of the led segments and their max current. Assuming they are red, that could be as low as 1.8V. If we also assume that the uln chips drop 0.7V, you could try series resistors of (5 - 0.7 - 1.8 ) / 0.020 ~= 120R

Thx for the help.

I will try, eventually, to multiplex the digits and post here the results.

Now im gonna add some push buttons to show the date and other things

1 Like

Martulas:
Thx for the help.

I will try, eventually, to multiplex the digits and post here the results.

Now im gonna add some push buttons to show the date and other things

I see that your numeros array uses 16 bytes per digit. If you add more characters (letters, for example), you will have to be careful not to run out of RAM.

I also see that your code for extracting digits of a number is much more complicated than it needs to be. I would use something like:

int n = 6789;   // the number whose digits you want to extract 

int thou = (n / 1000);     // int divided by int gives result as an int
int hund = (n / 100) % 10;
int tens = (n / 10) % 10;
int ones = n % 10;         // the symbol % means remainder from division

I changed my code to multiplex the digits instead of the segments using another 74hc595 shift register, changed the resistors to 110ohm, but the brightness isnt what i expected. So i dont know what to do now.

Post your schematic diagram (not a wiring layout) and include all components and their values. Hand drawn is ok.

its equal to the original schematic, but instead of the anode pins going to arduino, they are going to the extra 74hc595. (and new 16 resistores for each cathode)

Well then the extra 595 will not help in any way with the brightness. In fact it will make it worse because the 595 can source less current than the Arduino pins could. The 595 can only source around 70mA in total. The 6 Arduino pins can source as much as 120mA, depending which pins you use. With the lower resistors and the change to multiplexing by digit, the new 595 may be damaged becauise to much current is being drawn from it. You now need a PNP transistor such as bc327 for each common anode, as mentioned by david_prentice.

The 2n3906 PNP transistor can work too? And i can control the pnp's with the 74hc595 (with only the cathode resistors)?

The 2N3906 has a lower hFE. So you must make sure that you provide enough Base current to saturate it.

Life is much easier with a purpose made driver chip e,g. MAX7219.

Of course you can do everything by hand with individual transistors. The basic schematics are simple.
If you want to change components, you must do a few calculations with Ohms Law.

The main consideration with multiplexing is to calculate peak currents, average currents, duty cycles, ...

David.

david_prentice:
The 2N3906 has a lower hFE. So you must make sure that you provide enough Base current to saturate it.

Sorry if it's a dumb question, but how i do that? The Arduino can do that?

The arduino or the 595 can do that. 1K resistors in series with the PNP bases should give enough current to saturate them. If not, you could try 820R.

My main concern now with your circuit design is that you have both high and low side drivers, and both will drop some of your supply voltage. The PNP should only drop around 0.2V, but the uln chips could drop as much as 1.5V (it's a rather old design and not ideal for use with 5V circuits). You have not told us what the forward voltage of led segments is. You need to know all these things to calculate the segment series resistor values to get the maximum safe segment current.

The display is red, i dont know the specific forward voltage.
I have the tpic6b595 on the way, that can improve the problems?
Or i can try to change the code to remove the uln chips.

And one more thing, how do you know the resistors i should put in the PNP base? (I know that i should have googled it before i asked :P)

1 Like