bclose

39 – 4 DIGIT 7 SEGMENT DISPLAYS

Objectives

 

 

    • Our first 4 digit numeric display.
    • Multiplexing the digits.
    • Learning to program: splitting the problem into functions.
    • Back to operations with integers.
 

Bill of materials

Arduino UNO

Arduino Uno or equivalent. This chapter accepts any other Arduino board.

Breadboard

A solderlees Breadboard.

Jumper wires

Some  jumper wires

330 Ohm resistor

4 x 330 Ω resistors.

BCD 4 digit 7 segment display

A 4-digit 7-segment display.

Transistor 2N2222

4 x 2N2222 Transistors

4-digit LED displays

 

In the previous chapter, things went quite well using a digit, but now that we have got the hang of it, we want to use 4 digits to tell the time, for example.

And if we want to show 4 digits… are we going to multiply 8 cables x 4 digits plus voltage and GND making a total of 34 pins?

For a start, Arduino UNO does not have so many pins (the Mega does have them, but remember, elegance, great elegance). So if you were to make these displays how would you avoid using 34 pins? Think about it, what solution would you choose to solve the problem?

Well, an easy one and cheap, that is what the manufacturers like. The idea is to have 8 pin to turn on the 7 segments plus the point, and have other 4 pins to select to which of the digits corresponds the information placed in the segments a, b, c, d, e, f, g, h.

The idea is more or less like that, but to do it we would also need a few memories and latches, as in the shift register, so someone said: “No, no, cheaper yet.” And a creative engineer said: “If we connect these 4 pin, which are used to select the digit, to ground via a transistor each, we can turn on only one at a time. But if we do it fast enough, passing from one to another, they won’t even notice it.” Needless to say that the creative engineer became project manager.

And that’s it. We just keep using 8 pin to turn on the segments, but only one is active at a time. And making a rapid cycle, we turn on one at a time and quickly move to the next and so on, and so on… Problem solved.

So the first thing we have do is to connect the 8 segments of the display to pins 2 through 10 of our Arduino, to test them. Connect GND to the cathode of the first digit via a resistor and check the connections.

 

Initial connections

 

Again, I have to insist on reading the data sheet of your display and do not trust in the diagram below, because yours may be different. Look at the code of your display and download the data sheet from internet. Read it, just in case your pins match the diagram below from Parallax.

This diagram is for the display that we are dealing with, the 5461AS, and yours could not use the same pins, although the probability is high. If it were not the case you would only have to connect the correct pins in the same order of your Arduino.

 

Chapter 39, 5461AS pinout

What I’ve done (because my display only have 12 pins), is to connect the 8 segments and the cathode to ground via a resistor, to test the first digit and later I will worry about the rest. It is imperative that you ensure that the segments are properly connect before anything else.

You can test a simple sketch like this, which turns them on and off in sequence, to check the connection of the segments:

Sketch 39.1
void setup()
   { 
       for ( int i=2 ; i<10 ; i++)
             pinMode( i, OUTPUT);
   }

void loop()
   { 
       for (int j=2; j<10 ; j++)  
         {    digitalWrite( j, HIGH);
              delay(300);
              digitalWrite( j, LOW) ;
              delay(300);
         }
    }

If all turn on we can pass to the next phase.

 

CIRCUIT WIRING DIAGRAM

 

Now we are confident that our 7 segments are plugged in properly, it is the time to worry about the 4 pins of Arduino taht will be used to choose which digit turns on.

Our first idea would be to connect these display outputs, that is, the pins 12, 9, 8 and 6, to 4 pins of our Arduino. If we set these pins HIGH except the one that we want to turn on, that will be set LOW, the circuit would seem to be closed to GND and work.

But no way. The typical consumption of each segment (as each LED) falls between 15 and 20mA. As we have 8 segments, when we write the digit 8 plus the point, the consumption will be 8 x 15 = 120 mA and could even reach 160 mA. This is well above the 40 mA that pin of our Arduino can supply or drain, so we’d better think something else before perceiving a burning smell.

And the solution, dear friends, is naturally using a transistor to close the circuit of each digit.

Chapter 39, 5461AS pinout and schematic

The 2N2222 is already an old acquaintance (do not forget the base resistor, it is essential). Setting LOW the pins 9, 10, 11, and 12 all the transistors are cut off, and no digit can be turned on. If we set to HIGH the pin 12, the transistor saturates and allows the output of the first digit close the circuit to Ground, which will turn on the segments according to the values from pins 2 to 8 of Arduino.

Now we set to LOW the pin 12 and HIGH the pin 11. The values of the segments will turn on now the second digit and so on with the third and the fourth. The only trick is to do it fast, and our Duino is very good at it.

 

THE CONTROL PROGRAM

 

We are going to make good use of the Display() function, that we wrote in the previous chapter, in order to draw the digits on the display. If you can remember, it used an array to know which segments have to be turned on:

Sketch 39.2
byte Digit[10][8] =
   { 
     { 1,1,1,1,1,1,0,0 },    // 0
     { 0,1,1,0,0,0,0,0 },    // 1
     { 1,1,0,1,1,0,1,0 },    // 2
     { 1,1,1,1,0,0,1,0 },    // 3
     { 0,0,1,0,0,1,1,0 },    // 4
     { 1,0,1,1,0,1,1,0 },    // 5
     { 1,0,1,1,1,1,1,0 },    // 6
     { 1,1,1,0,0,0,0,0 },    // 7
     { 1,1,1,1,1,1,1,0 },    // 8
     { 1,1,1,0,0,1,1,0 }     // 9
   };

void setup()
    {           
         for (int i= 2; i<13; i++)
              pinMode(i, OUTPUT);
    }

But we are going to upgrade the Display() function to write a digit in the position we want, where position 0 are the units, position 1 tens, position 2 hundreds and position 3 thousands.

void Display(int pos, int N)
   {  
       digitalWrite(9 ,LOW);        // Turns off all digits
       digitalWrite(10,LOW);
       digitalWrite(11,LOW);
       digitalWrite(12,LOW);
 
      for (int i= 0 ; i<8 ; i++)    // This doesn't change from the last chapter 
            digitalWrite(i+2 , Digit[N][i]);
      digitalWrite(pos + 9, HIGH);      // Turns on the digit in the position pos
  }

As you see, the function is the same on the part of turning on the segments, but at the beginning we have turned off all digits, then we set HIGH the pins we want and only then activate the transistor output of the position we want, what makes the digit turn on in the position requested in pos.

We set the output pin as + 9, because positions 0, 1, 2, 3 corresponds also here to pins 9, 10, 11, 12.

Once that we have solved how to draw the chosen number in the selected position, we have to write another function to decompose a given number in units, tens, hundreds and thousands.

Making a show of creativity I have called this function CalculateDigits():

void CalculateDigits( int Num)
   {
      int Digit0 = Num %10 ;
      int Digit1 = (Num % 100) / 10 ;
      int Digit2 = (Num % 1000) / 100;
      int Digit3 = Num  / 1000);

      Display(3 , Digit3);
      Display(2 , Digit2);
      Display(1 , Digit1);
      Display(0 , Digit0);
   }

Just in case anyone missed the day we spoke of integer operations we will work on a specific case. Let’s choose the number 2386. How do we get their digits separated?

2386 % 10 = 6          The % operator returns the remainder of the division by 10, that is, 6.
2386 % 100 = 86        Now we calculate the integer division by 10, that is, 8, decimals are drop out
2386 % 1000 = 386      386 / 100 = 3
2386  / 1000 = 2       Directly, that's why the integer division was invented.

And then we show directly the digits on the display.

Finally, inside the main function, we start calling the CalculateDigits() function to count tenths of a second (we will do the countdown later).

void loop()
   {
       CalculateDigits(millis() / 100);
   }

Did you think it was going to be difficult? Well sorry. It’s that simple. We already knew the millis() function, that shows the internal clock of our Duino in milliseconds. Making the entire division (again) counts up to 999 seconds.

And what if we want to make a countdown? Come on, think a moment before looking at the solution.

 
  • It is very easy too. As our counter goes up to 9999 we only have to subtract the calculation above from the counter, or simply use instead of 9999 the number from which we want to discount..
 

 

It is more interesting and practical to convert this number to sexagesimal minutes and seconds to make a clock.

void loop()
   {
       int n = millis() / 1000;       // We convert  it to seconds
       int seconds = n % 60;
       int minutes =  n / 60;
       int k = minutes * 100 + seconds;
       CalculateDigits(k);
   }

Again using the internal clock of our Duino via the millis() function, (as it counts in milliseconds, we divide it by a thousand to convert it to seconds), we calculate the seconds and minutes. Then, as CalculateDigits() expects a centesimal number, we multiply the minutes by 100 to fit in.

 

 

I propose you as an exercise making a watch that performs a countdown from a given number.

 
  • The circuit we have seen, is the right one to ensure that the display have a long and peaceful life. In fact, it is the recommended by the manufacturer. In internet you will find many examples in which, instead of transistors, there are used a certain value resistors to limit the current intensity in the output controls. I preferred not to do so, even knowing that the assembly that I have proposed is quite more laborious..
 

SOME FINAL COMMENTS

 

To wire this assembly is disgusting and if it were a serious commercial circuit it would be expensive (although the components are cheap, to assemble them costs much money, rather than the components in this case).

So in practice, I advise you not to use these displays this way in your projects. There are too many cables and there is always someone giving a lot of hassle. We typically use instead a I2C display or similar with an internal control circuit, or we use a BCD chip as the MAX7219 (we will discuss the matter in the near future).

And why, despite everything, we have assembled this prototype? Because it is important that you understand how things work and the concept of multiplexing is one of the basic keys to understanding digital electronics.

By the way, have you realized that multiplexing digits using our Duino to loop through the full cycle in less time than our eye perceives, any use of the delay() function will ruin the invention?. Put one where you please and see what happens.

Although so far we have used and abused the delays, they are impractical and potentially very dangerous as projects get complicated, and this is one of those cases. We’ll talk about solutions.

 

SUMMARY

 

 

    • We have introduced the 4 digit 7 segment LED displays.
      • As an exercise the way we have dealt with these displays is fine, but we’ll see other ways to handle these displays, less laborious
    • We have enhanced the Display() function in order to use it in displays with several digits (it would be very easy to upgrade it to handle 8 digits).
    • We have split a series of logical problems into smaller steps easier to handle in order to improve our competence in finding useful algorithms.
    • We have seen that we are able to deal with complex problems by using small steps and functions that, when combined, solve problems that initially don’t seem to be tackled.
 

 

 

 

No Comments

Give a Reply