Displaying Multiple Digits on 7 Segment Display Simultaneously

Hello, everyone!

First time poster here so I apologize if this is in the wrong section.

I am currently working on a timer/counter project on my Arduino Uno (Elegoo version). I am using a 5641AS 4 Digit 7 Segment display to show the numbers. Most of the project is working but I am having trouble displaying multiple and different numbers at the same time. My goal at the moment is to count from 0 to a specified end number and have all the required digits to display on the 7 segment.

I created a function that power combinations of segments that will create the numbers, 0-9. To select the correct digit position (first digit, second digit, etc), I created a function that will turn on a certain digit position (LOW signal to pin) and the other three off (HIGH signal to pin).

The main algorithm involves dividing the current time/value into its digits which are then stored into its respective variable. What I am having trouble with is displaying all 4 digits of a number like 1234 at the same time. After the 1234 is separated into its digits, a call the function that selects the correct digit position and then the function that lights the correct segments to form a number. For example, to display the first digit of 1234, the left most digit position is selected and then the segments for number 1 are lit up. This goes on until all the digits of 1234 are displayed.

The problem is that the 7 segment is simply “sweeping” through the digits extremely fast. The first digit would light up, turn off, second digit would light up, turn off, third digit would light up, turn off, fourth digit would light up then turn off. I can’t seem to find a way to display all digits at the same time without using a delay to turn on and off each digit individually and then moving on to the next. What I want is to display all digits of 1234 at the same time, wait a delay of 1 second, display 1235 and so on. If I don’t turn off the first digit position before trying to display the following digits, 4 digits are displayed at the same time without the sweeping effect but they are all the same number.

Sorry for the long post but if anyone can provide any help that would be greatly appreciated. Thank you!

I am using Visual Studio Code instead of the Arduino IDE and have posted a link to my code on pastebin. (#include <Arduino.h>//Arduino Pins for Segments int A=2; //BCD pin 11int - Pastebin.com)

Video of it running Imgur: The magic of the Internet

7 Segment.txt (4.98 KB)

This is one of the most common questions asked on the forum. There was one only a couple of days ago.

I see 12 resistors, which is strange, but I can't read the values. Do you have resistors on the anodes and on the cathodes? What values?

For the moment, would recommend disconnecting the Arduino because you may be damaging it.

I can't seem to find a way to display all digits at the same time

This may come as a shock. You can't. Because of the way the display is wired, with common anodes and common cathodes, only one digit can ever be lit. This is normal, 99.5% of these displays are like that. What you need to do is exactly what you are doing now, but faster. Do it fast enough and to the eye it will look like all the digits are on at the same time, even though that isn't the case in reality. The technique is called multiplexing and effect on the eye is called persistence of vision.

This is how you should post code on the forum

#include <Arduino.h>

//Arduino Pins for Segments 
int A=2; //BCD pin 11
int B=3; //BCD pin 7
int C=4; //BCD pin 4
int D=5; //BCD pin 2
int E=6; //BCD pin 1
int F=7; //BCD pin 10
int G=8; //BCD pin 5
int DP=9; //BCD pin 3

//Arduino Digit Pins
double D1=10; //BCD pin 12 
double D2=11;//BCD pin 9
double D3=12;//BCD pin 8
double D4=13; //BCD pin 6

double digitsarray[4]={0,0,0,0};


unsigned long time_now = 0;

double start_time=1234;
double current_time=start_time;

double end_time=9999;

void mydelay(int y); 
void displaynumber(double num);
void displayoff();
void selectdigit(double d);


void setup() {

Serial.begin(9600); 
//Pin Set up
pinMode(A,OUTPUT);
pinMode(B,OUTPUT);
pinMode(C,OUTPUT);
pinMode(D,OUTPUT);
pinMode(E,OUTPUT);
pinMode(F,OUTPUT);
pinMode(G,OUTPUT);
pinMode(DP,OUTPUT);

pinMode(D1,OUTPUT);
pinMode(D2,OUTPUT);
pinMode(D3,OUTPUT);
pinMode(D4,OUTPUT);


}



void loop() {
  //digits
digitalWrite(D1,HIGH);
digitalWrite(D2,HIGH);
digitalWrite(D3,HIGH);
digitalWrite(D4,HIGH);

//variables for storing individual digits of current time/value
int value;
int firstdigit;
int seconddigit;
int thirddigit;
int fourthdigit; 









 
Serial.print("Current Time:\n");
Serial.print(current_time);



    value=current_time;
  
  //divides number into individual digits
    fourthdigit=value%10; 
    value=value/10;
    thirddigit=value%10;
    value=value/10;
    seconddigit=value%10;
    value=value/10;
    firstdigit=value%10;

    digitsarray[0]=firstdigit;
    digitsarray[1]=seconddigit;
    digitsarray[2]=thirddigit;
    digitsarray[3]=fourthdigit;

 
 


 displayoff();
 selectdigit(1);
 displaynumber(digitsarray[0]);

 mydelay(100);
 

 displayoff();
 selectdigit(2);
 displaynumber(digitsarray[1]);
 
 mydelay(100);
 

 displayoff();
 selectdigit(3);
 displaynumber(digitsarray[2]);
 
 mydelay(100);


displayoff();
selectdigit(4);
displaynumber(digitsarray[3]);

mydelay(100);





 
mydelay(600);
 current_time=current_time+1;
   
}


void mydelay(int y)
{
  time_now = millis();
   
    
   
    while(millis() < time_now + y){
        
    }
}

void displaynumber(double num)
{
  //mumbers 0-9
  
  if(num==0)
  {
    
    

    digitalWrite(A,HIGH);
    digitalWrite(B,HIGH);
    digitalWrite(C,HIGH);
    digitalWrite(D,HIGH);  
    digitalWrite(E,HIGH);
    digitalWrite(F,HIGH);
    digitalWrite(G,LOW);

  }

  if(num==1)
  {
    digitalWrite(A,LOW);
    digitalWrite(B,HIGH);
    digitalWrite(C,HIGH);
    digitalWrite(D,LOW);  
    digitalWrite(E,LOW);
    digitalWrite(F,LOW);
    digitalWrite(G,LOW);
  }

  if(num==2)
  {
  digitalWrite(A,HIGH);
  digitalWrite(B,HIGH);
  digitalWrite(C,LOW);
  digitalWrite(D,HIGH);  
  digitalWrite(E,HIGH);
  digitalWrite(F,LOW);
  digitalWrite(G,HIGH);
  }
  
  if(num==3)
  {
  digitalWrite(A,HIGH);
  digitalWrite(B,HIGH);
  digitalWrite(C,HIGH);
  digitalWrite(D,HIGH);  
  digitalWrite(E,LOW);
  digitalWrite(F,LOW);
  digitalWrite(G,HIGH);
  }

 if(num==4)
  {
  digitalWrite(A,LOW);
  digitalWrite(B,HIGH);
  digitalWrite(C,HIGH);
  digitalWrite(D,LOW);  
  digitalWrite(E,LOW);
  digitalWrite(F, HIGH);
  digitalWrite(G,HIGH);
  }

  if(num==5)
  {
    digitalWrite(A,HIGH);
    digitalWrite(B,LOW);
    digitalWrite(C,HIGH);
    digitalWrite(D,HIGH);  
    digitalWrite(E,LOW);
    digitalWrite(F,HIGH);
    digitalWrite(G,HIGH);
  }

   if(num==6)
  {
    digitalWrite(A,HIGH);
    digitalWrite(B,LOW);
    digitalWrite(C,HIGH);
    digitalWrite(D,HIGH);  
    digitalWrite(E,HIGH);
    digitalWrite(F,HIGH);
    digitalWrite(G,HIGH);
  }

   if(num==7)
  {
    digitalWrite(A,HIGH);
    digitalWrite(B,HIGH);
    digitalWrite(C,HIGH);
    digitalWrite(D,LOW);  
    digitalWrite(E,LOW);
    digitalWrite(F,HIGH);
    digitalWrite(G,LOW);
  }

   if(num==8)
  {
    digitalWrite(A,HIGH);
    digitalWrite(B,HIGH);
    digitalWrite(C,HIGH);
    digitalWrite(D,HIGH);  
    digitalWrite(E,HIGH);
    digitalWrite(F,HIGH);
    digitalWrite(G,HIGH);
  }

   if(num==9)
  {
    digitalWrite(A,HIGH);
    digitalWrite(B,HIGH);
    digitalWrite(C,HIGH);
    digitalWrite(D,HIGH);  
    digitalWrite(E,LOW);
    digitalWrite(F,HIGH);
    digitalWrite(G,HIGH);
  }


}

void displayoff()
{
    //turns all segments off
    digitalWrite(A,LOW);
    digitalWrite(B,LOW);
    digitalWrite(C,LOW);
    digitalWrite(D,LOW);  
    digitalWrite(E,LOW);
    digitalWrite(F,LOW);
    digitalWrite(G,LOW);

    
}

void selectdigit(double d)
{
digitalWrite(D1,HIGH);
digitalWrite(D2,HIGH);
digitalWrite(D3,HIGH);
digitalWrite(D4,HIGH);

//switches the selected digit to turn on
switch((int) d)
{
    case 1: 
    digitalWrite(D1, LOW);
    break;
    case 2: 
    digitalWrite(D2, LOW); 
    break;
    case 3: 
    digitalWrite(D3, LOW); 
    break;
    case 4:
    digitalWrite(D4, LOW); 
    break;
    
}

}

There are so many things wrong that I would feel cruel of I listed them all at this point, and it would take longer than starting over. Sorry!

PaulRB:
This is one of the most common questions asked on the forum. There was one only a couple of days ago.

I see 12 resistors, which is strange, but I can’t read the values. Do you have resistors on the anodes and on the cathodes? What values?

For the moment, would recommend disconnecting the Arduino because you may be damaging it.
This may come as a shock. You can’t. Because of the way the display is wired, with common anodes and common cathodes, only one digit can ever be lit. This is normal, 99.5% of these displays are like that. What you need to do is exactly what you are doing now, but faster. Do it fast enough and to the eye it will look like all the digits are on at the same time, even though that isn’t the case in reality. The technique is called multiplexing and effect on the eye is called persistence of vision.

Hi! This is my first time using the 7 segment display and I read that I should also use current limiting resistors for the pins. I used what I could find at the moment so there’s 330 ohm and 1k ohm resistors connected for the segments and the decimal point.

So I just need to decrease the delay between turning on each digit position? I tried setting the delay to 1ms but the display just sweeps so fast that you can barely see one digit light up. I tried lighting up a digit position 1ms after the previous one and having all digits appear to stay lit for 1 second after.

Why exactly did you create your own (flawed!) delay() function? Why are you using floating point data type to represent pin numbers?

So I just need to decrease the delay between turning on each digit position?

Yes, but also you need to repeat the process over and over, at least 50 times per second, for however long you want the display to be on.

There are easier ways to do this. There is a library called SevSeg for example, but also there are various chips which will do the job with minimum intervention by the Arduino. So the question is, what do you want to learn, the detailed fundamentals or the more practical ways?

In terms of your current circuit, it's not normal or necessary to have resistors on both the segments and the digit commons, or to have different values for the decimal points. But you must bear in mind the maximum current that an Uno pin can source or sink is 40mA, but for long life keep it below 30mA. Only on large led displays do you need different resistors on the decimal points. Large displays have 2 or 3 LEDs in series inside each segment, but only one in the decimal point, so need different resistors. But normal size displays have only one led in each segment, same as the decimal point, so the same resistor value is needed.

If you put resistors on the digit common pins and scan the display by digit, that causes a problem. The brightness won't be consistent between numbers, for example "1" would look much brighter than "8".

aarg:
Why exactly did you create your own (flawed!) delay() function? Why are you using floating point data type to represent pin numbers?

Hi! I read that using millis() for the delay provides more accurate timing. That part of the code is not mine. I guess I should just stick with the normal delay function.

TheEmpyrean:
Hi! I read that using millis() for the delay provides more accurate timing. That part of the code is not mine. I guess I should just stick with the normal delay function.

No, in fact delay() uses micros() for timing because it's more accurate than millis().

void delay(unsigned long ms)
{
	uint32_t start = micros();

	while (ms > 0) {
		yield();
		while ( ms > 0 && (micros() - start) >= 1000) {
			ms--;
			start += 1000;
		}
	}
}

PaulRB:
Yes, but also you need to repeat the process over and over, at least 50 times per second, for however long you want the display to be on.

There are easier ways to do this. There is a library called SevSeg for example, but also there are various chips which will do the job with minimum intervention by the Arduino. So the question is, what do you want to learn, the detailed fundamentals or the more practical ways?

In terms of your current circuit, it's not normal or necessary to have resistors on both the segments and the digit commons, or to have different values for the decimal points. But you must bear in mind the maximum current that an Uno pin can source or sink is 40mA, but for long life keep it below 30mA. Only on large led displays do you need different resistors on the decimal points. Large displays have 2 or 3 LEDs in series inside each segment, but only one in the decimal point, so need different resistors. But normal size displays have only one led in each segment, same as the decimal point, so the same resistor value is needed.

If you put resistors on the digit common pins and scan the display by digit, that causes a problem. The brightness won't be consistent between numbers, for example "1" would look much brighter than "8".

Thanks for the help! I will rebuild the circuit and try again. I did not know about the SevSeg library. I will modify my code and try to get it working without the library. If not, I will look at the SevSeg library.

You can do this fairly easily using the Adafruit 0.56" 4-Digit 7-Segment Display w/I2C Backpack.

I used one a while back, and after figuring out how to simultaneously display different characters at the same time, created a write-up on it.

You can read through it here: Using an Adafruit 7-Segment Display with I2C Backpack

You essentially write to a buffer, then dump the buffer to the display. The display then holds the values until you dump the buffer again, but can change the buffer in the meantime. So you can send values for each segment to the buffer, without affecting what is being shown. Then after you have the values in the buffer, write it to the display all at once.

No flickering, and no sweeping of the segments.