Using 7 Segment LED displays, Part 1

LED displays are everywhere, and for good reasons. They are very legible, they cost next to nothing, and they are very reliable. It’s true that what you can show on these is rather limited, since everything you can show has to be built out of seven segments only, but for showing hexadeximal numbers 0 to F it is excellent, and most of the time you just want to show such data.

In this three part posting, I will take you through building a system that uses first a single 7 segment digit for showing the numbers 0 to 9 and any combination of 7 segments.

While you can power one 7 segment display directly from Arduino as it has sufficient pins to use, you will run out of pins as soon as you want to add another display. This is why shift registers are used; you can send any number to the display with just 4 pins, and you can create a daisy chain of shift registers to hook up even 8 displays. Some shift registers can manage 64 devices.

To complete this tutorial, you will need a breadboard, some jumper wires, a shift register chip called 74HC595, and a single digit 7 segment display. I highly recommend buying an Arduino starter kit such as the Freenove Ultimate Starter Kit for Arduino, because you get everything you can ever need for learning Arduino when you buy one of these. It’s only about 31 euros at the moment at eBay. The Github link above takes you to the page where you can download the Tutorial PDF for free. This presentation is based on the tutorial, which provides excellent instruction.

If you don’t want to get the whole package, the 74HC595 chips can be found on eBay for 89 cents per ten units.

For LED digits, the eBay treasure trove can offer you a package of various LED units for peanuts. This package has about a dozen LEDs for one euro. I suggest you buy these instead of the single digits, because you will soon want to expand from one digit to more digits.

Words of caution

LED segment displays come in two flavors, common cathode or common anode. In Common Anode (CA) you supply voltage to one pin and ground others to get the segments to light up, and in Common Cathode (CC), you provide voltage to segment pins and ground one pin.

While this is not a problem with the Arduino in mind, the 74HC595 chips are used with Common Anode LEDs. When you buy LEDs and shift registers, make sure they match.

Also, LEDs always want to have a current-limiting resistor in front of the voltage. If you use these elements as listed in this tutorial, you should connect a 220 ohm resistor in each of the pins. I have sometimes left out the resistor, but it can damage the display and cause problems with the Arduino’s durability. The value of the resistor depends on the LEDs and the available current.

How does it work – the Shift Register?

The shift register is used to take in bytes and distribute the bits in the byte to separate pins. This way you don’t need to have a single pin on the Arduino for each of the pins of the LED, but insted, you send a byte to the shift register which deals it out to the pins, and after a time set by you, it is flushed and a new byte is sent in to be dealt with.

It’s also possible to chain the shift registers so that you can have four LEDS for example, to enable you to have a counter to 0 to 9999 or a timer going up or down. In this example we will use one shift register, because we have one 7 segment display to run.

The 74HC595 pinout. Source: Freenove Tutorial
  • The pins Q0 to Q7 correspond to segments A to DP as seen below.
  • VCC is 5V from Arduino
  • GND is Ground from Arduino
  • Q7′ is the data output pin in case you are building a daisy chain of shift registers, but otherwise is left disconnected
  • DS is the input pin on which the byte of information is to be sent
  • OE or output enable is the pin that tells the shift register whether to take in data or distribute data. It is grounded.
  • ST_CP, or latch pin, is used to update the data
  • SH_CP, or clock pin, is used to time the operation of the shift register
  • MR is the memory erase pin, and is connected to 5V

How does it work – the LEDS?

A 7 segment LED is just what it says, a set of LEDs arranged in a pattern of 8, with the decimal point as the eighth. When you power the display with voltage to the anode pin (usually 5 volts, but 9 or 12 volts for large digits), and ground each segment’s pin, that pin will light up.

Kuvahaun tulos haulle creative commons 7 segment led
Segment labels.
Source: Creative Commons

The pins are arranged in two rows at each end of the unit:

Segment pins
Source: Creative Commons

The pins are labelel from 1 to 10, with 1 to 5 starting from the bottom left and continuing to 6 to 10 from top right. Pins 3 and 8 are usually the anodes, but when you buy these displays, remember to check the pin order. In the Freenove digits, the pinout order is as follows:

A = 7
B = 6
C = 4
D = 2
E = 1
F = 9
G = 10
DP = 5

So, seeing that list and wanting to display the number 3 for example, means you should connect the pins A, B, C, D and G to have the number light up. If you were doing this straight from the Arduino, you would have set it up so that A would be your pin 3, for example, B would be 4 etc. until Decimal Point would be your pin 10. Then you would code something like

digitalWrite(pinA, low);
digitalWrite(pinB, low);
digitalWrite(pinC, low);
digitalWrite(pinD, low);
digitalWrite(pinE, high);
digitalWrite(pinF, high);
digitalWrite(pinG, low);
digitalWrite(pinDP, high);

That looks a little arduous, and therefore it is usually done using an array. In the array you can have a value 0 for off and 1 for on for any segment, and this saves you time and effort when you can just pick the right value from the array. See the list below – number 1 has the segments B and C as one, and the others are off (the last bit is the Decimal Point, so if you want that on, just change the zero to one:

0 = 11111100
1 = 01100000
2 = 11011010
3 = 11110010
4 = 01100110
5 = 10110110
6 = 10111110
7 = 11100000
8 = 11111110
9 = 11110110

This is then put into an array:

array num = [
11111100, 
01100000, 
11011010, 
11110010, 
01100110, 
10110110, 
10111110, 
11100000, 
11111110, 
11110110];

So, to pick the number 4 from here, you’d say in the code,

NumToShow = num[3]

Another way to do this is to use hexadecimals. This table and the code example are from the Freenove manual. Note that the Number/Letter is not the binary value shown in the Binary number column – it is the 7 segment representation of the number. in fact, you can make up any combination of the 7 segments by finding out what binary number corresponds to the desired layout. See Wikipedia for more, there is an image of all the possible combinations of seven segments.

This table can be put into a byte array as follows:

byte num[] = {
0xc0, 
0xf9, 
0xa4, 
0xb0, 
0x99, 
0x92, 
0x82, 
0xf8, 
0x80, 
0x90, 
0x88, 
0x83, 
0xc6, 
0xa1, 
0x86, 
0x8e};

and to pick the value four from it would be the same code as above.

So, let’s go and do the wiring for the system. First you place the shift register straddling the groove down the breadboard. This enables you to use the four remaining holes on each pin for your jumper wires. Note the notch on the top of the chip and have it on the right.

Then, place the digit similarly over the groove. If you use resistors, it’s a good idea to place them above and below the display with the connections leading away from the display, otherwise you will find the installation a little cramped.

I have found that it’s a good idea to first connect all wires to the shift register and label them, then connect them to the Arduino and the display. The shift register is going to be the hub of all wires so connecting the last two will be hard if you have little space.

The LED wires run from Q0 to A, Q1 to B etc. and Q7 to DP. The ground wire of the shift register is connected to the ground rail (blue strip running down the side of the breadboard), and the 5V pin of the shift register to the voltage rail of the breadboard (red strip). Connect the pins Q7′ and VCC to the voltage rail. The common anode of the LED unit is either 3 or 8 and that is to be connected to the voltage rail. Add resistors to LED pins 1, 2, 4, 5, 6, 7, 9 and 10 and have them point away from the LED unit as shown in this picture.

Shift regoister, LED and resistors
Shift register, LED and resistors

Connect the red rail of the breadboard to Arduino’s 5V pin and the blue rail to any of the three GND pins on it. Then connect DS to Arduino’s pin 11, ST_CP to Arduino pin 12, and ST_CH to Arduino pin 13. In the picture below, the common anode isn’t connected yet to the Voltage rail, so the digit is missing one pin from either 3 or 8 to the Voltage of the breadboard. It doesn’t work really well without the pin.

Connections. I know it looks messy

This makes us ready for adding code and running Arduino. This code will cycle through the hexadecimals 0 to F on the display, and it is adapted from Freenove’s tutorial. Note the use of the latchPin to enable data transfer, it is pulled low to open the transfer and pulled high after the transfer is done

int latchPin = 12; // Pin connected to ST_CP of 74HC595, Pin12 
int clockPin = 13; // Pin connected to SH_CP of 74HC595, Pin11 
int dataPin = 11; // Pin connected to DS of 74HC595, Pin14 

// Define the encoding of characters 0-F of the common-anode 7-segment Display 
byte num[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e}; 

void setup() { // set Arduino pins to output 
pinMode(latchPin, OUTPUT); 
pinMode(clockPin, OUTPUT); 
pinMode(dataPin, OUTPUT); } 

void loop() { // Cycling display 0-F 
for (int i = 0; i <= 0x0f; i++) { 

// Output low level to latchPin 
digitalWrite(latchPin, LOW); 

// Send serial data to 74HC595. num[i] picks the ith from array num 
shiftOut(dataPin, clockPin, MSBFIRST, num[i]); 

// Output high level to latchPin, and 74HC595 will update 
// the data to the parallel output port. 
digitalWrite(latchPin, HIGH); 
delay(1000); 
   } 
}

Note that this doesn’t use the decimal points. To do that, we need to add another array called numdec. In it, every hexadecimal value has had 128 subtracted from it, which turns on the decimal point. If you now use this code instead, you will see every character first without a decimal point and then with one.

int latchPin = 12; // Pin connected to ST_CP of 74HC595(Pin12)
int clockPin = 13; // Pin connected to SH_CP of 74HC595(Pin11)
int dataPin = 11;  // Pin connected to DS of 74HC595(Pin14)

// Define the encoding of characters 0-F without decimal point  
byte num[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e};

// Define the encoding of characters 0-F with decimal point  
byte numdec[] = {0x40, 0x79, 0x24, 0x30, 0x19, 0x12, 0x02, 0x78, 0x00, 0x10, 0x08, 0x03, 0x46, 0x21, 0x06, 0x0e};

 void setup() { // set pins to output
   pinMode(latchPin, OUTPUT);
   pinMode(clockPin, OUTPUT);
   pinMode(dataPin, OUTPUT);
 }
 
void loop() { // Cycling display 0-F without and with decimal point

   for (int i = 0; i <= 0x0f; i++) {
     // Output low level to latchPin
     digitalWrite(latchPin, LOW); 
     // Send serial data to 74HC595 
     shiftOut(dataPin, clockPin, MSBFIRST, num[i]); 
      // Output high level to latchPin, and 74HC595 will update the 
      // data to the parallel output port. 
     digitalWrite(latchPin, HIGH); 
     delay(500);
     digitalWrite(latchPin, LOW); 
     // Send serial data to 74HC595 
     shiftOut(dataPin, clockPin, MSBFIRST, numdec[i]); 
     // Output high level to latchPin, and 74HC595 will update the 
     // data to the parallel output port. 
     digitalWrite(latchPin, HIGH); 
     delay(500);    
   }
 }

So, this set enables you to use a decimal point if you need one, in case you want to display something like temperature that may require a decimal. If that is the case, use the numdec array instead of the num array for that digit in tour set of digits. The video below runs the code with both arrays being used.

7 segment LED with and without decimal point

In the next episode, we will use a LED display with four segmented digits instead of just one. That is much more useful in most applications that a single digit, though in my range, the hot plates use single digit LED displays with the dot enabled for half values between integers. It’s nice to know just how it is done.

Loading

Leave a Reply

Your email address will not be published. Required fields are marked *

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.