Digit 7 Segment Display

4 Digit 7 Segment Display

 

In this tutorial, we are going to show you how to set up a 4 digit 7 segment display to create a count up timer that activates when light is detected. 

Materials

How does it work?

Before we can start wiring stuff and writing code, we have to understand how a 4 digit 7 segment display works.

Physical layout

Physical layout

 

LEDs Connection

LEDs Connection

These two diagrams can help us understand how the display works. The display consists of four digits. Each number (or digit) consists of 7 segments (A-G). Each segment has an LED  that can turn on or off. This way we can display any number or letter that we want by turning on the correct segments of each digit. For example, if we want to display the number 2 in any of the digits, we would have to turn on segments A, B, G, E, and D, and set the desired digit low to allow current to flow in that channel . But what about when we try to use all 4 digits at the same time? Well in that case we have to use something called multiplexing. Multiplexing consists of turning on and off each digit at a time so fast that to our eyes it will look like all four digits are on at the same time. For example, say we want to display the number 5489. We would start by turning on digit 1 to display number “5.” Then we turn off digit 1 and turn on digit 2 to display number “4.” Next we turn off digit 2 and turn on digit 3 to display number “8.” Finally we turn off digit 3 and turn on digit 4 to display number “9,” and the process repeats at a very fast rate (we are talking about milliseconds).   

 

Wiring

So now that you have a basic understanding on how the display works, let's start wiring the components.

Arduino Pro Mini Wiring

 

Arduino Pro Mini Wiring

 

LED Segment Wiring

LED Segment Wiring

 

Complete WiringComplete Wiring

 

Display Pinout

 

Display Pinout



  • Light Sensor to Arduino Pin A0

  • Arduino Pin A3 to Arduino RST

 

Code

int digit1 = 10; 
int digit2 = 11; 
int digit3 = 6; 
int digit4 = 9; 

int segA = 12;
int segB = 8;
int segC = 4;
int segD = 3; 
int segE = A1; 
int segF = 7; 
int segG = 5; 

int colon = 2; 
int light_sensor = A0;
int reset = A3; 

int time_var1 = 0;
int sensor_value = 0;
int light = 100;
long second = 1000;
long minute = 60000;
long hour = 3600000;

void setup() {
  
  digitalWrite(reset, HIGH);
  pinMode(reset, OUTPUT);
  
  Serial.begin(9600);
  
  pinMode(segA, OUTPUT);
  pinMode(segB, OUTPUT);
  pinMode(segC, OUTPUT);
  pinMode(segD, OUTPUT);
  pinMode(segE, OUTPUT);
  pinMode(segF, OUTPUT);
  pinMode(segG, OUTPUT);
  pinMode(digit1, OUTPUT);
  pinMode(digit2, OUTPUT);
  pinMode(digit3, OUTPUT);
  pinMode(digit4, OUTPUT);
  pinMode(colon , OUTPUT);
  pinMode(light_sensor, INPUT);
 
  digitalWrite(segA, LOW);
  digitalWrite(segB, LOW);
  digitalWrite(segC, LOW);
  digitalWrite(segD, LOW);
  digitalWrite(segE, LOW);
  digitalWrite(segF, LOW);
  digitalWrite(segG, LOW);
  digitalWrite(digit1, HIGH);
  digitalWrite(digit2, HIGH);
  digitalWrite(digit3, HIGH);
  digitalWrite(digit4, HIGH);
  digitalWrite(colon , HIGH);
}

void loop() {
  
  sensor_value = analogRead(light_sensor); 
  long timeNow = millis();
  int minutes = timeNow/minute;
  int seconds = (timeNow % minute)/second;
  int time_var = minutes*100;
  
  if(sensor_value > light && timeNow < hour){
    digitalWrite(reset, HIGH);
    
    if(seconds=1){
      int time_var1 = time_var + seconds;
      displayNumber(time_var1);   
    }
    else{
      int time = concatenate(minutes,seconds);
      displayNumber(time);
    }
 }
  else{
    digitalWrite(reset, LOW);
  }
}

int concatenate(int x, int y) {
    int pow = 10;
    while(y >= pow)
        pow *= 10;
    return x * pow + y;        
}

void displayNumber(int toDisplay) {

#define DISPLAY_BRIGHTNESS  500
#define DIGIT_ON  LOW
#define DIGIT_OFF  HIGH

  long beginTime = millis();

  for(int digit = 4 ; digit > 0 ; digit--) {

    switch(digit) {
    case 1:
      digitalWrite(digit1, DIGIT_ON);
      break;
    case 2:
      digitalWrite(digit2, DIGIT_ON);
      break;
    case 3:
      digitalWrite(digit3, DIGIT_ON);
      break;
    case 4:
      digitalWrite(digit4, DIGIT_ON);
      break;
    }

    lightNumber(toDisplay % 10);
    toDisplay /= 10;

    delayMicroseconds(DISPLAY_BRIGHTNESS); 
    lightNumber(10); 

    digitalWrite(digit1, DIGIT_OFF);
    digitalWrite(digit2, DIGIT_OFF);
    digitalWrite(digit3, DIGIT_OFF);
    digitalWrite(digit4, DIGIT_OFF);
  }

  while( (millis() - beginTime) < 10) ; 
}

void lightNumber(int numberToDisplay) {

#define SEGMENT_ON  HIGH
#define SEGMENT_OFF LOW

  switch (numberToDisplay){

  case 0:
    digitalWrite(segA, SEGMENT_ON);
    digitalWrite(segB, SEGMENT_ON);
    digitalWrite(segC, SEGMENT_ON);
    digitalWrite(segD, SEGMENT_ON);
    digitalWrite(segE, SEGMENT_ON);
    digitalWrite(segF, SEGMENT_ON);
    digitalWrite(segG, SEGMENT_OFF);
    break;

  case 1:
    digitalWrite(segA, SEGMENT_OFF);
    digitalWrite(segB, SEGMENT_ON);
    digitalWrite(segC, SEGMENT_ON);
    digitalWrite(segD, SEGMENT_OFF);
    digitalWrite(segE, SEGMENT_OFF);
    digitalWrite(segF, SEGMENT_OFF);
    digitalWrite(segG, SEGMENT_OFF);
    break;

  case 2:
    digitalWrite(segA, SEGMENT_ON);
    digitalWrite(segB, SEGMENT_ON);
    digitalWrite(segC, SEGMENT_OFF);
    digitalWrite(segD, SEGMENT_ON);
    digitalWrite(segE, SEGMENT_ON);
    digitalWrite(segF, SEGMENT_OFF);
    digitalWrite(segG, SEGMENT_ON);
    break;

  case 3:
    digitalWrite(segA, SEGMENT_ON);
    digitalWrite(segB, SEGMENT_ON);
    digitalWrite(segC, SEGMENT_ON);
    digitalWrite(segD, SEGMENT_ON);
    digitalWrite(segE, SEGMENT_OFF);
    digitalWrite(segF, SEGMENT_OFF);
    digitalWrite(segG, SEGMENT_ON);
    break;

  case 4:
    digitalWrite(segA, SEGMENT_OFF);
    digitalWrite(segB, SEGMENT_ON);
    digitalWrite(segC, SEGMENT_ON);
    digitalWrite(segD, SEGMENT_OFF);
    digitalWrite(segE, SEGMENT_OFF);
    digitalWrite(segF, SEGMENT_ON);
    digitalWrite(segG, SEGMENT_ON);
    break;

  case 5:
    digitalWrite(segA, SEGMENT_ON);
    digitalWrite(segB, SEGMENT_OFF);
    digitalWrite(segC, SEGMENT_ON);
    digitalWrite(segD, SEGMENT_ON);
    digitalWrite(segE, SEGMENT_OFF);
    digitalWrite(segF, SEGMENT_ON);
    digitalWrite(segG, SEGMENT_ON);
    break;

  case 6:
    digitalWrite(segA, SEGMENT_ON);
    digitalWrite(segB, SEGMENT_OFF);
    digitalWrite(segC, SEGMENT_ON);
    digitalWrite(segD, SEGMENT_ON);
    digitalWrite(segE, SEGMENT_ON);
    digitalWrite(segF, SEGMENT_ON);
    digitalWrite(segG, SEGMENT_ON);
    break;

  case 7:
    digitalWrite(segA, SEGMENT_ON);
    digitalWrite(segB, SEGMENT_ON);
    digitalWrite(segC, SEGMENT_ON);
    digitalWrite(segD, SEGMENT_OFF);
    digitalWrite(segE, SEGMENT_OFF);
    digitalWrite(segF, SEGMENT_OFF);
    digitalWrite(segG, SEGMENT_OFF);
    break;

  case 8:
    digitalWrite(segA, SEGMENT_ON);
    digitalWrite(segB, SEGMENT_ON);
    digitalWrite(segC, SEGMENT_ON);
    digitalWrite(segD, SEGMENT_ON);
    digitalWrite(segE, SEGMENT_ON);
    digitalWrite(segF, SEGMENT_ON);
    digitalWrite(segG, SEGMENT_ON);
    break;

  case 9:
    digitalWrite(segA, SEGMENT_ON);
    digitalWrite(segB, SEGMENT_ON);
    digitalWrite(segC, SEGMENT_ON);
    digitalWrite(segD, SEGMENT_ON);
    digitalWrite(segE, SEGMENT_OFF);
    digitalWrite(segF, SEGMENT_ON);
    digitalWrite(segG, SEGMENT_ON);
    break;

  case 10:
    digitalWrite(segA, SEGMENT_OFF);
    digitalWrite(segB, SEGMENT_OFF);
    digitalWrite(segC, SEGMENT_OFF);
    digitalWrite(segD, SEGMENT_OFF);
    digitalWrite(segE, SEGMENT_OFF);
    digitalWrite(segF, SEGMENT_OFF);
    digitalWrite(segG, SEGMENT_OFF);
    break;
  }
}

Code Explanation

int digit1 = 10; 
int digit2 = 11; 
int digit3 = 6; 
int digit4 = 9; 

int segA = 12;
int segB = 8;
int segC = 4;
int segD = 3; 
int segE = A1; 
int segF = 7; 
int segG = 5; 

int colon = 2; 
int light_sensor = A0;
int reset = A3; 

int time_var1 = 0;
int sensor_value = 0;
int light = 100;
long second = 1000;
long minute = 60000;
long hour = 3600000;

Here we are simply declaring what pins from the display correspond to the Arduino according to our wiring setup. We also assign an Arduino  pin to our light sensor and a pin to Reset. Furthermore, we initialize and declare some variables that will be used later in the code.

void setup() {
  
  digitalWrite(reset, HIGH);
  pinMode(reset, OUTPUT);
  
  Serial.begin(9600);
  
  pinMode(segA, OUTPUT);
  pinMode(segB, OUTPUT);
  pinMode(segC, OUTPUT);
  pinMode(segD, OUTPUT);
  pinMode(segE, OUTPUT);
  pinMode(segF, OUTPUT);
  pinMode(segG, OUTPUT);
  pinMode(digit1, OUTPUT);
  pinMode(digit2, OUTPUT);
  pinMode(digit3, OUTPUT);
  pinMode(digit4, OUTPUT);
  pinMode(colon , OUTPUT);
  pinMode(light_sensor, INPUT);
 
  digitalWrite(segA, LOW);
  digitalWrite(segB, LOW);
  digitalWrite(segC, LOW);
  digitalWrite(segD, LOW);
  digitalWrite(segE, LOW);
  digitalWrite(segF, LOW);
  digitalWrite(segG, LOW);
  digitalWrite(digit1, HIGH);
  digitalWrite(digit2, HIGH);
  digitalWrite(digit3, HIGH);
  digitalWrite(digit4, HIGH);
  digitalWrite(colon , HIGH);
}

Here we set the RST pin high through pin A3 in order to be able to use pin A3 as a reset button whenever it is set low. Then we initialize serial communication, set all the pins as outputs, set the light sensor as input, turn off all the segments, and set all the digits and the colon high.

void loop() {
  
  sensor_value = analogRead(light_sensor); 
  long timeNow = millis();
  int minutes = timeNow/minute;
  int seconds = (timeNow % minute)/second;
  int time_var = minutes*100;
  
  if(sensor_value > light && timeNow < hour){
    digitalWrite(reset, HIGH);
    
    if(seconds=1){
      int time_var1 = time_var + seconds;
      displayNumber(time_var1);   
    }
    else{
      int time = concatenate(minutes,seconds);
      displayNumber(time);
    }
 }
  else{
    digitalWrite(reset, LOW);
  }
}

In this part of the code we read the value of the light sensor. Then we use the function millis() to know the time that has passed since the Arduino started running in milliseconds. Next we use two conversion formulas to calculate minutes and seconds based on the time that the millis() function outputs. Then we check if the light sensor has detected light and if the Arduino has not been running for more than an hour. If the case is true, then we set the reset pin high and use the functions “concatenate” and “displayNumber ”  to display the time in our LED display. However, since we are concatenating minutes and seconds, there is a slight problem whenever the seconds are less than ten. Let’s see what the problem is. Pretend the timer just started counting, and so it looks something like this:

 

So at the beginning of the counter everything looks fine. But let’s see what happens after the first minute


The function that concatenates the numbers ignores the zeroes at the left. So instead of displaying 1:01, 1:02, 1:03 and so on, we are displaying 11, 12, 13. To solve this we use the variable “time_var” which takes the minutes and multiplies them by 100. So now whenever we have less than ten seconds, we use time_var, add the seconds to it, and display that number instead. This is just a way of adding that missing zero between the numbers.

If more than one hour passes, or if the light sensor does not sense enough light, the Arduino will reset and thus, the timer will start again.

int concatenate(int x, int y) {
    int pow = 10;
    while(y >= pow)
        pow *= 10;
    return x * pow + y;        
}

This is the function that concatenates the minutes and the seconds. Let’s say that we want to concatenate 1 and 20 to display the time 1:20, then:

x = 1     y = 20     pow = 10

Is 20 >= 10? Yes, Therefore pow is now 100. So we return (1*100) + 20 = 120 which will display 1:20.

void displayNumber(int toDisplay) {

#define DISPLAY_BRIGHTNESS  500
#define DIGIT_ON  LOW
#define DIGIT_OFF  HIGH

  long beginTime = millis();

  for(int digit = 4 ; digit > 0 ; digit--) {

    switch(digit) {
    case 1:
      digitalWrite(digit1, DIGIT_ON);
      break;
    case 2:
      digitalWrite(digit2, DIGIT_ON);
      break;
    case 3:
      digitalWrite(digit3, DIGIT_ON);
      break;
    case 4:
      digitalWrite(digit4, DIGIT_ON);
      break;
    }

    lightNumber(toDisplay % 10);
    toDisplay /= 10;

    delayMicroseconds(DISPLAY_BRIGHTNESS); 
    lightNumber(10); 

    digitalWrite(digit1, DIGIT_OFF);
    digitalWrite(digit2, DIGIT_OFF);
    digitalWrite(digit3, DIGIT_OFF);
    digitalWrite(digit4, DIGIT_OFF);
  }

  while( (millis() - beginTime) < 10) ; 
}

This is the function that sends the number that we want to display to the 4 digit 7 segment display. Here is where the multiplexing takes place. We are basically turning on and off each digit with its respective segments at a fast rate to display the desired number. Say we want to display the number 15, which represents the time 0:15. We start by turning on digit 4, which needs to display the number 5. To do this we use a function called “lightNumber” with the argument 15 % 10 = 5. So we pass the number 5 to be displayed in digit 4 of our display. Then our toDisplay variable adopts the value 15 / 10 = 1. Next we turn off all the display. Now we turn on digit 3, which needs to display the number 1 (this is the new value of the toDiplay variable). Once again we use the function “lightNumber” with the argument 1 % 10 = 1. So we pass the number 1 to be displayed in digit 3 of our display. Then our toDisplay variable adopts the value 1 / 10 = 0. Finally, we turn off all the display. Since now the value of toDisplay is zero, the process will repeat for digits 2 and 1, but they will display zero. So in the end we have 00:15.  

void lightNumber(int numberToDisplay) {

#define SEGMENT_ON  HIGH
#define SEGMENT_OFF LOW

  switch (numberToDisplay){

  case 0:
    digitalWrite(segA, SEGMENT_ON);
    digitalWrite(segB, SEGMENT_ON);
    digitalWrite(segC, SEGMENT_ON);
    digitalWrite(segD, SEGMENT_ON);
    digitalWrite(segE, SEGMENT_ON);
    digitalWrite(segF, SEGMENT_ON);
    digitalWrite(segG, SEGMENT_OFF);
    break;

  case 1:
    digitalWrite(segA, SEGMENT_OFF);
    digitalWrite(segB, SEGMENT_ON);
    digitalWrite(segC, SEGMENT_ON);
    digitalWrite(segD, SEGMENT_OFF);
    digitalWrite(segE, SEGMENT_OFF);
    digitalWrite(segF, SEGMENT_OFF);
    digitalWrite(segG, SEGMENT_OFF);
    break;

  case 2:
    digitalWrite(segA, SEGMENT_ON);
    digitalWrite(segB, SEGMENT_ON);
    digitalWrite(segC, SEGMENT_OFF);
    digitalWrite(segD, SEGMENT_ON);
    digitalWrite(segE, SEGMENT_ON);
    digitalWrite(segF, SEGMENT_OFF);
    digitalWrite(segG, SEGMENT_ON);
    break;

  case 3:
    digitalWrite(segA, SEGMENT_ON);
    digitalWrite(segB, SEGMENT_ON);
    digitalWrite(segC, SEGMENT_ON);
    digitalWrite(segD, SEGMENT_ON);
    digitalWrite(segE, SEGMENT_OFF);
    digitalWrite(segF, SEGMENT_OFF);
    digitalWrite(segG, SEGMENT_ON);
    break;

  case 4:
    digitalWrite(segA, SEGMENT_OFF);
    digitalWrite(segB, SEGMENT_ON);
    digitalWrite(segC, SEGMENT_ON);
    digitalWrite(segD, SEGMENT_OFF);
    digitalWrite(segE, SEGMENT_OFF);
    digitalWrite(segF, SEGMENT_ON);
    digitalWrite(segG, SEGMENT_ON);
    break;

  case 5:
    digitalWrite(segA, SEGMENT_ON);
    digitalWrite(segB, SEGMENT_OFF);
    digitalWrite(segC, SEGMENT_ON);
    digitalWrite(segD, SEGMENT_ON);
    digitalWrite(segE, SEGMENT_OFF);
    digitalWrite(segF, SEGMENT_ON);
    digitalWrite(segG, SEGMENT_ON);
    break;

  case 6:
    digitalWrite(segA, SEGMENT_ON);
    digitalWrite(segB, SEGMENT_OFF);
    digitalWrite(segC, SEGMENT_ON);
    digitalWrite(segD, SEGMENT_ON);
    digitalWrite(segE, SEGMENT_ON);
    digitalWrite(segF, SEGMENT_ON);
    digitalWrite(segG, SEGMENT_ON);
    break;

  case 7:
    digitalWrite(segA, SEGMENT_ON);
    digitalWrite(segB, SEGMENT_ON);
    digitalWrite(segC, SEGMENT_ON);
    digitalWrite(segD, SEGMENT_OFF);
    digitalWrite(segE, SEGMENT_OFF);
    digitalWrite(segF, SEGMENT_OFF);
    digitalWrite(segG, SEGMENT_OFF);
    break;

  case 8:
    digitalWrite(segA, SEGMENT_ON);
    digitalWrite(segB, SEGMENT_ON);
    digitalWrite(segC, SEGMENT_ON);
    digitalWrite(segD, SEGMENT_ON);
    digitalWrite(segE, SEGMENT_ON);
    digitalWrite(segF, SEGMENT_ON);
    digitalWrite(segG, SEGMENT_ON);
    break;

  case 9:
    digitalWrite(segA, SEGMENT_ON);
    digitalWrite(segB, SEGMENT_ON);
    digitalWrite(segC, SEGMENT_ON);
    digitalWrite(segD, SEGMENT_ON);
    digitalWrite(segE, SEGMENT_OFF);
    digitalWrite(segF, SEGMENT_ON);
    digitalWrite(segG, SEGMENT_ON);
    break;

  case 10:
    digitalWrite(segA, SEGMENT_OFF);
    digitalWrite(segB, SEGMENT_OFF);
    digitalWrite(segC, SEGMENT_OFF);
    digitalWrite(segD, SEGMENT_OFF);
    digitalWrite(segE, SEGMENT_OFF);
    digitalWrite(segF, SEGMENT_OFF);
    digitalWrite(segG, SEGMENT_OFF);
    break;
  }
}

This is the function used to turn on the correct segments of a digit depending on the value of numberToDisplay (This is the value passed from the previous function).

 

Results

 


In this example we used a light sensor as a switch to activate the counter, but you can use another method like an actual switch or no switch at all.