7-Segment LED Tutorial

Updated: Apr 16

Learn how to build a basic counter from a 7-Segment LED, controlling its speed from a potentiometer.

Above: Photo of the circuit you will be building. Turn the dial to increase or decrease the speed of the counter.


[Disclaimer: As an Amazon Associate I earn from qualifying purchases from paid links in this article]

Parts List (contains paid links):

Arduino UNO (1): https://amzn.to/3mHeKnz

7-Segment Common Cathode Numerical Display (1): https://amzn.to/3deTu5u

Potentiometer (1) : https://amzn.to/3a6Bvw7

Jumper Wires (Assorted): https://amzn.to/2QqrBhW

330 Ohm Resistor: https://amzn.to/3ddnj6g


Software

Arduino IDE

Introduction

A 7-Segment LED is simpler than it looks. It's actually just what its name implies -- a device with 7 distinct LED's. Each segment, or LED, is controlled the same way that a regular LED is turned on our off (high or low). To see a sample project from this site which uses the 7-Segment LED, refer to the Code Atari Breakout and Build your own Arduino Controller article.


Different types of 7-Segment LED's


Even with a regular LED, there is an Anode (usually the longer side, with is positive), and the Cathode (the shorter side, which connects to ground.).


Common Cathode (the type shown in this tutorial)- Each LED has its own VCC, which means they all need there own power source. However, there is only 1 common ground. So you end up having a bunch of wire all sending power to the device (1 wire to each segment), and then 1 wire coming out of it that it connected to ground.

Common Anode - This works the opposite of the above. We will not be using it for this tutorial.

About the 7-Segment LED

Shown to the right is the component that was used in this tutorial. It has a total of 10 pins. 7 of these pins are for each of the 7 LED's, with an addition for the Decimal point and then lastly 2 pin for ground.



If you search online, you can usually find the datasheet for the component you have. Since there are lot of varieties out there for 7-Segment LED's, I needed to find the info for the one I got at RadioShack. Although in this case the component is not very complicated, I believe it is good practice to find the data sheet and try to understand what it is telling you. Luckily, I was able to pair this up with the original plastic bag that it Radio






















The back of the packaging from RadioShack (slightly crumpled...but still informative! ) to the left is showing what I think is a much clearer diagram of the pin locations on the display.








Connecting the display to the Arduino UNO




This is a chart that maps the segments to pins, then finally to the Arduino digital pins as shown in the schematic below. The order is important for reasons explained below. The code must know the mapping in order to light up the correct segments to draw numbers.





Breadboard Schematic




Software


Install the SevSeg.h Library


The code uses the SevSeg library, which simplifies a lot of the work to tell the display which LED's to turn on for each number. To add this to your project go to Tools ->Manage Libraries...


Type "SevSeg" in the searcbar and then click Install.



Once that's installed, it will allow us to do things like this, which will tell the display to show the digit '3'. This lights up 4 segments, so without this library we would have to 'teach' the program which segments = the digit 3.

sevseg.setNumber(3);

The 'delay()' function


Especially in a lot of beginner tutorials on the Arduino, there is extensive use of the delay() function. It goes something like this:


// Wait for 1 second
delay(1000);

This is fine if all we want to do is blink and LED once every second. But this actually stops the program thread for an entire seconds, meaning that the Arduino will not react to any sensors or perform any other code for that duration. For this project, we want to the Arduino to be continuously reading the value of our potentiometer, and then react immediately to adjust the speed that the numbers are changing. If we use the delay function, then it would be an entire second until the LED responded to any changes, and even then they would be momentary.


To illustrate this problem, look at the following:


void loop(){  
   val = analogRead(potPin) + 65; // Read potentiometer   
   
   delay(1000); // Wait 1 second
  
   num++;    // Increment Number    
}

The code after delay(1000) would only execute every 1 second...but so would the code prior to it.


So, the solution is to implement our own timing function.


void loop(){  
 val = analogRead(potPin) + 65; // Read potentiometer  
 
 if(millis()-time > val)   // Check if time has passed    
  {    
     // Increment Number
     num++;
    time = millis();             
  }  
}

One last important bit about using the SevSeg Library...

we must pass the library details about our physical connections to the 7-segment display. The pin numbers are passed in alphabetical order, so it expects A, B, C, D....etc. Refer to the chart put together above for this to make sense.


byte segmentPins[] = {2, 3, 4, 6, 7, 9, 8, 5};


The Full Code

/* 7- Segment LED Tutorial with Speed Control
 * 
 * This example code demonstrates how make a 7-Segment
 * LED endlessly count from 0-9, and allow variable control
 * of the counting speed via a rotary potentiometer. The program
 * does so without the use of the 'delay()' function so that 
 * input is continusly received from the potentiometer.
 * 
 * CodeIsEveryWhere.com 
 *   
 */

#include "SevSeg.h"
SevSeg sevseg; 

unsigned long time = millis();
int potPin = 0;
int val = 0; 
int num = 0;

void setup(){
  Serial.begin(9600);
  byte numDigits = 1;
  byte digitPins[] = {};
  byte segmentPins[] = {2, 3, 4, 6, 7, 9, 8, 5};
  bool resistorsOnSegments = true;  
  byte hardwareConfig = COMMON_CATHODE; 
  sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, 
  resistorsOnSegments);
  sevseg.setBrightness(90);
}

void loop(){  
  val = analogRead(potPin) + 65; 
  Serial.println(val);
  sevseg.setNumber(num);
  sevseg.refreshDisplay();  
  if(millis()-time > val)     
  {    
    if (num == 9) {
      num = 0;  
    } else {
      num++;          
    }    
    time = millis();          
  }  
}