Digit Brightness Issue - 7 segment 4 digit display + 2 x 74HC595

Hello Everyone :slight_smile:

I've made a project using Arduino NANO, 7 segment 4 digit display Anode, 2 x 74HC959.

Here are the schematics:

I've got 2 identical displays, all connected to 1 Arduino NANO (in the code, you will see that its 3 display - that for the future, currently just the 2 displays are connected).

The resistor values are 470 [ohm].

Here is the code I'm using.

int clockPin[] = {7,10,13};
int latchPin[] = {6,9,12};
int dataPin[] = {5,8,11};

byte digits[] =   {B00001100, //0
                   B10111101, //1
                   B01101000, //2
                   B00111000, //3
                   B10011001, //4
                   B00011010, //5
                   B00001010, //6
                   B10111100, //7
                   B00001000, //8
                   B00011000  //9
                  };

int digit1, digit2, digit3, digit4;

void setup() {

  pinMode(clockPin[0], OUTPUT);
  pinMode(latchPin[0], OUTPUT);
  pinMode(dataPin[0], OUTPUT);

  pinMode(clockPin[1], OUTPUT);
  pinMode(latchPin[1], OUTPUT);
  pinMode(dataPin[1], OUTPUT);

  pinMode(clockPin[2], OUTPUT);
  pinMode(latchPin[2], OUTPUT);
  pinMode(dataPin[2], OUTPUT);
  
}

void loop() {

  showNumber(756,0);
  showNumber(74,1);

}


void showNumber (int num, int disp) {
  
  digit4 = num % 10;
  digit3 = (num / 10) % 10;
  digit2 = (num / 100) % 10;
  digit1 = (num / 1000) % 10;
 
  digitalWrite(latchPin[disp], LOW);
  shiftOut(dataPin[disp], clockPin[disp], MSBFIRST, B00001000); // X X X NUM
  shiftOut(dataPin[disp], clockPin[disp], MSBFIRST, digits[digit4]);
  digitalWrite(latchPin[disp], HIGH);
  delay(1);

  digitalWrite(latchPin[disp], LOW);
  shiftOut(dataPin[disp], clockPin[disp], MSBFIRST, B00000100); // X X NUM X
  shiftOut(dataPin[disp], clockPin[disp], MSBFIRST, digits[digit3]);
  digitalWrite(latchPin[disp], HIGH);
  delay(1);

  digitalWrite(latchPin[disp], LOW);
  shiftOut(dataPin[disp], clockPin[disp], MSBFIRST, B00000010); // X NUM X X
  shiftOut(dataPin[disp], clockPin[disp], MSBFIRST, digits[digit2]);
  digitalWrite(latchPin[disp], HIGH);
  delay(1);
  
  digitalWrite(latchPin[disp], LOW);
  shiftOut(dataPin[disp], clockPin[disp], MSBFIRST, B00000001); // NUM X X X
  shiftOut(dataPin[disp], clockPin[disp], MSBFIRST, digits[digit1]);
  digitalWrite(latchPin[disp], HIGH);
  delay(1);
    
}

As you can see from the code, I've created a function that receives 2 integers, and light up the corresponding LED display (int disp), with the number (int num).

The number that lights up are correct, and the digit is also correct.

The problem:

The first and last digits (left-to-right) lights up brighter than the rest digits, on display #1.

The first digit (left-to-right) lights up brighter than the rest digits, on display #2.


When connecting the output of the 74HC595 to oscilloscope (before resistors):

format: Display - Digit - active time - voltage

Display 1 - Digit 1 - 2.8 [sec] - 4.5 [V]
Display 1 - Digit 2 - 0.56 [sec] - 4.5 [V]
Display 1 - Digit 3 - 0.56 [sec] - 4.5 [V]
Display 1 - Digit 4 - 0.56 [sec] - 2.5 [V] - (no idea why there is a voltage drop here)

Cycle - 4.48 [sec]

Display 2 - Digit 1 - 2.8 [sec] - 4.5 [V]
Display 2 - Digit 2 - 0.56 [sec] - 4.5 [V]
Display 2 - Digit 3 - 0.56 [sec] - 4.5 [V]
Display 2 - Digit 4 - 0.56 [sec] - 4.5 [V]

Cycle - 4.48 [sec]

I'm guessing the problem is in my code, or the fact that maybe i don't quite understand the working of a shift register when implementing my code.

Any help would be greatly appreciated :))
Thanks in advance.

P.S.: it's my first schematics drawing, so please don't be hating if its a bit messy.
if any information is lacking for you to address the issue, please let me know :slight_smile:

7seg4digit pinout.png

74HC595-IC-Pinout_0.png

+1 karma for posting a schematic and pictures.
-1 karma for posting your code incorrectly. Please fix that. Read the forum guide.

PaulRB:
+1 karma for posting a schematic and pictures.
-1 karma for posting your code incorrectly. Please fix that. Read the forum guide.

done. sorry.

Your current limiting resistors should be in the segment lines. Not in the common-anode lines.
A 1 will appear brighter than an 8.

I am impressed by your effort. Especially since a MAX7219 module from Ebay is so cheap and easy to control.

David.

Lets get the usual advice out of the way before we look at your problem.

Don't use 74hc595 for driving 7 seg displays. It's current capabilities are too low and it makes your code so much more complex. The current limitations can be overcome with transistors, but this makes the circuit much more complex. Use a proper led display driver like max7219 or ht16k33.

Given that you are using 74hc595, my first question would be why are you not chaining all of them? You seem to be chaining them only in pairs for each display. You could chain all 4 (or 6) and save Arduino pins and make your code simpler. Use the SPI pins to control them instead of relying on the much slower shiftOut() function.

Where are your bypass caps? These are mandatory. You need one per chip, 0.1uF, close to the Vcc pin of each chip.

Your led series resistors should be on the segments if you are multiplexing by digit. They should only be on the digit common pins if you are multiplexing by segment.

If your active time for each digit is not the same, you will not get even brightness.

Hey, you fixed the code tags! Thanks, +1 karma.

I can see why the last digit on each display is brighter. It's left switched on while the other display is being updated. For 3 out of 4 digits on each display, your code lights the digit for 1ms, then that gets switched off and the next digit gets switched on. But the 4th digit is left switched on for the whole time the other display is being updated. The longer the digit is switched on, the brighter it will appear. So you could switch off the last digit of the display after 1ms before updating the other display. That would give more even brightness. (As already mentioned, putting your resistors on the segments would also help.)

But the problem with the above idea is that each digit will only be lit for 1ms out of 8ms. When you add the 3rd display, that will be 1ms every 12ms. This will make the display dim and might make flickering noticeable. The display will only be updated 40 times per second. You need to re-think your multiplexing strategy.

david_prentice:
Your current limiting resistors should be in the segment lines. Not in the common-anode lines.
A 1 will appear brighter than an 8.

I am impressed by your effort. Especially since a MAX7219 module from Ebay is so cheap and easy to control.

David.

Thanks David, will try to re-arrange the resistors, and see what comes up.

Can you maybe recommend a MAX7219 type LED module with 4 digits (instead of 8)?

PaulRB:
Lets get the usual advice out of the way before we look at your problem.

Don't use 74hc595 for driving 7 seg displays. It's current capabilities are too low and it makes your code so much more complex. The current limitations can be overcome with transistors, but this makes the circuit much more complex. Use a proper led display driver like max7219 or ht16k33.

Given that you are using 74hc595, my first question would be why are you not chaining all of them? You seem to be chaining them only in pairs for each display. You could chain all 4 (or 6) and save Arduino pins and make your code simpler. Use the SPI pins to control them instead of relying on the much slower shiftOut() function.

Where are your bypass caps? These are mandatory. You need one per chip, 0.1uF, close to the Vcc pin of each chip.

Your led series resistors should be on the segments if you are multiplexing by digit. They should only be on the digit common pins if you are multiplexing by segment.

If your active time for each digit is not the same, you will not get even brightness.

  1. I've chained 2 to each display because I figured it will be easier to write the code, when I'm working by blocks. Meaning - each block is a display, and I send the information to each display individually.

  2. Do you a reference on how to use the SPI pins to control multiple shift regs in series?

  3. I've added the bypass caps (thanks), however no change to the output.

PaulRB:
I can see why the last digit on each display is brighter. It's left switched on while the other display is being updated. For 3 out of 4 digits on each display, your code lights the digit for 1ms, then that gets switched off and the next digit gets switched on. But the 4th digit is left switched on for the whole time the other display is being updated. The longer the digit is switched on, the brighter it will appear. So you could switch off the last digit of the display after 1ms before updating the other display. That would give more even brightness. (As already mentioned, putting your resistors on the segments would also help.)

But the problem with the above idea is that each digit will only be lit for 1ms out of 8ms. When you add the 3rd display, that will be 1ms every 12ms. This will make the display dim and might make flickering noticeable. The display will only be updated 40 times per second. You need to re-think your multiplexing strategy.

What logic would you use? Do you have any code reference for this?
Thanks.

Search for "MAX7219 4-digit" e.g. this

But it is cheaper to buy an 8-digit module and cut off the unwanted displays.

Or just use a better Google-foo e.g. TM1637 module

David.

You already have the displays. Why not just buy a max7219 DIP chip? Or two, for your third display. You will need a 0.1uF cap, a 10uF cap and a 10K resistor for each chip. But you won't need any series resistors for the LEDs.

If you want to continue with the 74hc595 while your max chips are on order...

If you put 470R resistors on each segment, that would overload the pins on the '595 connected to the common anodes. They can only supply 35mA max each, so you would need to increase the resistors to 820R.

Alternatively, do you have 4 x pnp transistors, such as bc237? Connect their collectors to 5V, their emitters to the digit common pins and their bases to '595 pins with ~1K resistors. Then you can continue using 470R resistors on the segments.

If I were driving 3 x 4-digit common anode displays and I had to use 74hx595, I would connect 4 chips in a chain. 3 would drive the segment pins of the 3 displays (using 24 x 470R resistors) and the 4th chip would control the common digit pins using 4 x pnp transistors. The digit common pins of each display would be connected together so that the first digit of all 3 displays would be lit together, then the second digit of all 3 displays lit together and so on. Obviously some changes would be needed to your code to work like that.

If you put 470R resistors on each segment, that would overload the pins on the '595 connected to the common anodes. They can only supply 35mA max each, so you would need to increase the resistors to 820R.

Your math is wrong. Assuming 5V supply and Vf=2.5V per LED segment, (5 - 2.5) / 470R = 5mA.
So 7 segments on would mean 35mA through the common anode.

A bit dim but probably visible in a living room. i.e. with a 595 per display.
If multiplexing 3 displays, the average segment current would be 5mA / 3. Pretty dim.

The segment current is not too much of a drive problem. But the "common" current needs a PNP transistor to cope with all 7 segment on.

Note that MAX7219 or TM1637 is designed to drive high currents. You need a good power supply.

David.

Assuming 5V supply and Vf=2.5V per LED segment

That's a bit high for red, isn't it? I was assuming Vf=1.8V. Yes, maybe I should have stated that, but 1.8~2.0V is quite normal for red, which, from the OP's pictures, is what is being used here.

PaulRB:
I can see why the last digit on each display is brighter. It's left switched on while the other display is being updated. For 3 out of 4 digits on each display, your code lights the digit for 1ms, then that gets switched off and the next digit gets switched on. But the 4th digit is left switched on for the whole time the other display is being updated. The longer the digit is switched on, the brighter it will appear.

The nub of this recent thread also. :grinning:

Round and round in circles. :roll_eyes: Actually, this one also!

PaulRB:
You already have the displays. Why not just buy a max7219 DIP chip? Or two, for your third display.

Arguably because it's just not worth it. :astonished: Usually cheaper to start again with a proper module.

eBay!

But at the moment it could be preferable to wait until normal business resumes and the prices return to the more realistic pre-COVID-19 situation - if that actually happens. :roll_eyes:

You can probably buy MAX7219 or TM1637 modules locally. No need to wait for China.

Oops. I have been replying to 7-seg threads on AvrFreaks and Arduino.cc

Everything is possible. Just that some ways require more effort.

David.

Can you maybe recommend a MAX7219 type LED module with 4 digits (instead of 8)?

most of the Max7219 modules with green pcb have their 4digits modules in sockets, so it is really very easy to just pull out the left LED module, they just cost some cent more than the even cheaper blue ones which come mostly soldered.

If you are looking for larger 4 digit displays, search for Holtek ht16K33 modules as they mostly come with 0.56" LEDs.

Both, the max7219 and the ht16k33 are far easier to use, the max with (soft)spi, the holtek with i2c.

Hello everyone,

Thank you for all your replies.

There are a couple of reasons I'm not using the max7219 (or its relatives) module:

  1. I don't have it, I'm using what I got lying around.

  2. I did order a couple of those modules, however the delivery time is quite long, so for now - what I got is what I'm using.

  3. Furthermore, It's pretty problematic to find the exact module (size of the LED display is very important) that I need.

Regarding the circuit:

I did try to connect the segment pins (and not the digit pins) via resistors, like PaulRB suggested - no change in display.

Regarding the code:

I added a delay in the main loop, and so that the first digit does stay lit, while the rest of the digits are blinking.

I did try to change the order of the digits to be lit, and saw that the order matters. This is what i mean:

void showNumber (int num, int disp) {
  
  digit4 = num % 10;
  digit3 = (num / 10) % 10;
  digit2 = (num / 100) % 10;
  digit1 = (num / 1000) % 10;
 
  digitalWrite(latchPin[disp], LOW);
  shiftOut(dataPin[disp], clockPin[disp], MSBFIRST, B00000001); // NUM X X X
  shiftOut(dataPin[disp], clockPin[disp], MSBFIRST, digits[digit1]);
  digitalWrite(latchPin[disp], HIGH);
//  delay(1);

  digitalWrite(latchPin[disp], LOW);
  shiftOut(dataPin[disp], clockPin[disp], MSBFIRST, B00000010); // X NUM X X
  shiftOut(dataPin[disp], clockPin[disp], MSBFIRST, digits[digit2]);
  digitalWrite(latchPin[disp], HIGH);
//  delay(1);

  digitalWrite(latchPin[disp], LOW);
  shiftOut(dataPin[disp], clockPin[disp], MSBFIRST, B00000100); // X X NUM X
  shiftOut(dataPin[disp], clockPin[disp], MSBFIRST, digits[digit3]);
  digitalWrite(latchPin[disp], HIGH);
//  delay(1);

  digitalWrite(latchPin[disp], LOW);
  shiftOut(dataPin[disp], clockPin[disp], MSBFIRST, B00001000); // X X X NUM
  shiftOut(dataPin[disp], clockPin[disp], MSBFIRST, digits[digit4]);
  digitalWrite(latchPin[disp], HIGH);
//  delay(1);
    
}

The outcome is that the last digit now stayed lit.

I cannot figure out why that is. Maybe I don't understand the basic works of the 74hc595?

PaulRB:
If I were driving 3 x 4-digit common anode displays and I had to use 74hx595, I would connect 4 chips in a chain. 3 would drive the segment pins of the 3 displays (using 24 x 470R resistors) and the 4th chip would control the common digit pins using 4 x pnp transistors. The digit common pins of each display would be connected together so that the first digit of all 3 displays would be lit together, then the second digit of all 3 displays lit together and so on. Obviously some changes would be needed to your code to work like that.

This seems like a reasonable solution to simplify the wiring, and perhaps use less pins on the Arduino (which frankly, not that important to me).
However, I don't see how that will solve the problem of dimmer lighting. Still I'd have a digit which is brighter (probably the first on in the code that is being lit).
Maybe I'm wrong?

In any case, thanks for the help thus far, and any assistance regarding the code would be greatly appriciated.

misha55678:
I don't see how that will solve the problem of dimmer lighting. Still I'd have a digit which is brighter (probably the first on in the code that is being lit).

The dimmer lighting is caused by the digits being lit for different lengths of time. Make the times equal and the brightness will be equal.

Try this. It should help with the uneven brightness:

void showNumber (int num, int disp) {
 
  digit4 = num % 10;
  digit3 = (num / 10) % 10;
  digit2 = (num / 100) % 10;
  digit1 = (num / 1000) % 10;
 
  digitalWrite(latchPin[disp], LOW);
  shiftOut(dataPin[disp], clockPin[disp], MSBFIRST, B00000001); // NUM X X X
  shiftOut(dataPin[disp], clockPin[disp], MSBFIRST, digits[digit1]);
  digitalWrite(latchPin[disp], HIGH);
  delay(1);

  digitalWrite(latchPin[disp], LOW);
  shiftOut(dataPin[disp], clockPin[disp], MSBFIRST, B00000010); // X NUM X X
  shiftOut(dataPin[disp], clockPin[disp], MSBFIRST, digits[digit2]);
  digitalWrite(latchPin[disp], HIGH);
  delay(1);

  digitalWrite(latchPin[disp], LOW);
  shiftOut(dataPin[disp], clockPin[disp], MSBFIRST, B00000100); // X X NUM X
  shiftOut(dataPin[disp], clockPin[disp], MSBFIRST, digits[digit3]);
  digitalWrite(latchPin[disp], HIGH);
  delay(1);

  digitalWrite(latchPin[disp], LOW);
  shiftOut(dataPin[disp], clockPin[disp], MSBFIRST, B00001000); // X X X NUM
  shiftOut(dataPin[disp], clockPin[disp], MSBFIRST, digits[digit4]);
  digitalWrite(latchPin[disp], HIGH);
  delay(1);
  
  digitalWrite(latchPin[disp], LOW);
  shiftOut(dataPin[disp], clockPin[disp], MSBFIRST, B00000000); // X X X X
  shiftOut(dataPin[disp], clockPin[disp], MSBFIRST, B00000000);
  digitalWrite(latchPin[disp], HIGH);
   
}

But it will not help fix the overall dimness of the display, which will get worse when you add the third display, or the flickering that you will probably get then.