Display a 2-digit number using 7-segment displays

As we’ve seen in the previous tutorial, it’s pretty easy to display a single digit number on a seven segment display. If you want to display two digits though, you’ll quickly see it’s a bit more complicated. Today we’ll learn how to multiplex two 7-segment displays in order to display a 2-digit number.

The problem

The main problem is that each digit requires 7 or 8 pins of the microcontroller, depending on whether or not we want to use the decimal point. Let’s say we don’t use the digital point, so we have 7 segments per digit. If we take a 4 digit number for example, which would be used to display the time on a microwave oven or an alarm clock, we would need 4*7 signals to control our displays, which is 28 pins of the microcontroller!

It’s more than the total number of pins on a PIC16F88! And even on a bigger microcontroller, we can’t afford to waste that many pins just to display a basic information. Most embedded applications will use multiple sensors, and control several outputs. In addition to this, it would be a waste of space on a PCB, as it would require a lot of traces. Most applications need the smallest PCB possible, because a bigger PCB is more expensive, and makes the device bigger.

Let’s see what solution we can find to this problem! We’ll consider a 2-digit number, which will require two 7-segment displays. The technique we’ll learn can be reused with as many displays as you want, so this is just as an example.

Bill of Material

As usual, we’ll need the basic components required for the PIC to run. Please check this tutorial if you forgot how to get started with PIC microcontrollers.

We’ll also need two 7-segment displays of the same type (either two common anodes or two common cathodes), and 8 resistors (330Ω). If you don’t use the decimal point, then you can use only 7 resistors.

The last components we’ll need are two 2N7000 N-channel MOSFETs. We’ll talk about it later in this tutorial, but they’ll be use to turn ON or OFF each display.

Idea

The idea behind this tutorial is that if you turn ON and OFF each display fast enough, while applying different signals to each, then our eyes will see it as a constant display.

In order to do this, we’ll control each segment of both display with a single signal. It means that segment A of both displays will be controlled by a unique signal, segment B of both displays will be controlled by another unique signal, and so on.

Now let’s try this, and see that there is another thing to add to make it work.

Basic circuit (that will not work!)

Let’s start building a simple circuit, based on the one from our previous tutorial about 7-segment displays. We’ll use the same circuit, and only add a second 7-segment. We’ll connect the cathode of both displays to GND. The circuit is the following:

Basic circuit (that will fail) Let's start building a simple circuit, based on the one from our previous tutorial about 7-segment displays. (LINK). We'll use the same circuit, and only add a second 7-segment. We'll connect the cathode of both displays to GND. The circuit is the following: (01-two-identical-displays) (04-two-identical-displays-breadboard) If you program your microcontroller with the same program we used in our last lab (link), you'll see that both displays show the same digit. This is normal, because they are both controlled by the same signals.
Circuit with two identical displays
Two identical displays on a breadboard
Two identical displays on a breadboard

If you program your microcontroller with the same program we used in our last lab, you’ll see that both displays show the same digit. This is normal, because they are both controlled by the same signals.

Display different digits

Now how can we show a different digit on each display? It’s simple: instead of connecting the cathodes of our displays to GND, we’ll control them from the PIC. But we can’t connect them directly to a pin of the microcontroller, as too much current would flow in this pin. Indeed, each LED draws around 10 to 20mA. If we have 7 LEDs, it would be between 70 and 140mA, which is way much higher that what the pins of the PIC can handle.

Instead, we’ll use a N-channel MOSFET. I use a 2N7000, but most MOSFETs are suitable. We’ll control its gate with an output signal from the PIC. We’ll connect its source to GND, and its drain to the cathode pins of our displays. This way, we can control individual 7-segment displays with only 7 signals for the segments, and 2 signals for the cathodes. As you can guess, it would require 4 signals for the cathodes if we used 4 seven segment displays.

Let’s modify our circuit!

Circuit for two different digits

The only modification we need to make is to connect the cathodes of each display to the drain of the corresponding MOSFET, like shown below.

Connect the cathodes to the drain of the MOSFETs
Connect the cathodes to the drain of the MOSFETs

The complete circuit is the following.

Complete circuit to control two 7-segment displays from a PIC
Complete circuit to control two 7-segment displays from a PIC

And it looks like this on a breadboard:

Final circuit on a breadboard
Final circuit on a breadboard

Now let’s try something! Using the same program as previously, try to connect the gate of a MOSFET to GND and then 5V. You’ll see that if you connect it to GND, then the display will be OFF, no matter what signal you apply to its segments. If you connect the gate to 5V, then the display is ON, and the segments which receive 5V will be ON.

The reason for this is simple: when you apply 0V to the gate, the MOSFET acts like an opened switch. When you apply 5V, it acts like a closed switch.

Software

What we’re going to do

We’ll use what we just learned to display two digits. We’ll obviously always apply the same signals to the segments, but we’ll only turn one display ON at a time. It means we’re going to display the first digit with the first seven segment display ON and the other one OFF, and then we’ll display the second digit with only the second display ON. If we do this fast enough, our eyes will not see any flickering and it will appear as a constant display.

Let’s create separate files!

To make our code more tidy, we create two additional files to our main.c. Let’s name them dual7seg.h and dual7seg.c.

In the header file, we give the name CATHODE_0 and CATHODE_1 to RA0 and RA1, which will be used to turn ON or OFF respectively the display 0 and the display 1 (display 0 shows the tens, display 1 shows the units). We also give the name SEGMENTS to the Port B, which will be use to control individual segments. Then we declare two functions:

  • void dual7segSetValue(uint8_t value): will be used to change the number to display.
  • void dual7segRefreshDisplay(): will turn ON or OFF each digit alternately.

Here is the code of dual7seg.h:

Variables used

In the .c file, we declare 3 global variables:

  • value0: will contain the units
  • value1: will contain the tens
  • digitToDisplay: will be equal to 0 or 1 to indicate which digit should be displayed

We also declare a constant array of uint8_t, representing the values of the segments for each number from 0 to 9. The last value will display ‘-‘ to represent a number our of range (too big to be displayed on 2 digits).

Set value

The function used to set the value to display is the following. It first checks that the number given in parameter is not too big to be displayed, which is the case if it’s greater than 99. If it’s too big, then we display ‘–‘ to indicate an error. If not, we store the value of the tens in value1 by dividing the number by 10, and we put the value of the units in value0 by calculating its modulo by 10.

Refreshing the display

This function will be called periodically by the main function, at a high enough frequency so that our eyes see no flickering. It alternately turns ON one display and OFF the other, and makes sure the correct signals are applied to the display that is ON.


Full code for dual7seg.c

The full code for the .c file is the following.

Test in the main function

In order to test our little library, we write a main function that will count from 0 to 255. For the numbers between 0 and 99, it should display the correct numbers on the 7 segment displays, and for the other numbers it should display “–“.

The first step is to declare a variable that will hold the value of our counter. We also declare a variable “i”, that we’ll use to implement a delay.

In the while(1) loop, we set the value to display with the dual7segSetValue function. The number will be incremented thanks to “++”.

Then, we use a for loop that will make sure our number is printed for long enough so we can see it counting. The number of iterations is arbitrary, and you can experiment to find a number that suits you. In this for loop, we use a short delay between each refresh of the display. In the code below, we display each digit for 5 ms, and then switch the digit to display.

You can experiment and use bigger values for the delay. If the value is high enough (100ms is good), you’ll see how each digit is alternately displayed. If the value is low enough, the alternation will become invisible to our eyes.

The full code for the main file with the configuration bits is the following.

Result

Now if you program your microcontroller, you should see that your circuit counts from 0 to 99, and then displays “–“. If you wait a little bit, it will start counting from 0 again.

The following video shows the result on a breadboard.

Please post a comment below if you have any question, and make sure to write down your email address to receive our new tutorials!

[wysija_form id=”2″]

Be the first to comment

%d bloggers like this: