Using 7 Segment LED displays, Part 3

This part concludes my foray into segmented LEDs. Part 1 showed you how to work with single digits, part 2 expanded into four digit, one unit displays, and this one handles a system where you have four single digits acting as the four digits of part 2, only in much bigger size and with external power.

The 74HC595 chip is great when you have small digits that can be powered through the Arduino, but in case you need large format LEDs, you will have to power them separately. In my case, I wanted to build the same clock as in Part 2, but with 4 inch digits. This device is the countdown clock in the escape room that our Business teachers are building here at Haaga-Helia University of Applied Sciences.

The first digit lit up

I thought it’d be a simple and straightforward project to move from the small digits to these big ones, but it wasn’t that clear. First of all, you cannot use the same shift registers. For something that can handle larger currents and a 9-12V voltage, you need to buy TPIC6B595N or similar. These are readily available at eBay as linked. Second, you must do some soldering to a power supply that you plan to use.

Connecting the TPIC chip

The new chips have a different footprint and pin order. It’s a 20 pin chip, but it sits nicely on a breadboard.

TPIC6B595 Pinout
source: Protosupplies, inc
  • The Drain pins are connected to the LED segments, with 0 corresponding to A and 7 to G segment.
  • Pins 2 and 8 receive +5V from Arduino
  • Pins 10, 11 and 19 are grounded.
  • Pin 3 is for data in, Arduino pin 11 in my code
  • Pin 18 is for data out to the next shift register. It will enter pin 3 at the next shift register. Bear in mind there will be four of these in a chain so the last one will be left empty.
  • Pins 1 and 20 are not connected
  • Pin 9 is Output Enable, connected to Arduino pin 9 in my code
  • Pin 12 is Latch, Arduino pin 10
  • Pin 13 is Clock, Arduino pin 13

Wiring the LEDs

For this project you can recycle an old power adapter, mine came from an ADSL that died. It gives out 18V and 1.5A, so it is very suitable. To adjust the voltage, I added a buck down regulator to adjust the voltage to suit the LEDs. You must make sure the adapter you want to use is suitable for Arduino, as you will share the power supply.

I then cut the lead close to the connector, added two pinned wires to the big ones so as to get the power out at 12 volts before it enters the Arduino and gets regulated to 5V. Of the small wires, the red is connected to the red rail of the breadboard, and the black to Arduino’s ground to make sure it is shared among the Arduino and the digits. Make sure the solder jobs are solid and that you use insulation around the connections.

Each segment of each of the four digits needs to have a 220 ohm resistor in the segment wires, so I cut the female-male wires and added a resistor with insulation on each, so that’s a 32 x solder job. The segments from each display digits are led to the TPIC6B595 chips as shown above. The common anodes 3 and 8 are led to the red rail of the breadboard receiving the 12 volts.

With this complete, let’s look at the code.

The Arduino program

This application works by sending numbers as bytes to the shift registers. The shift register is latched open, byte data is passed to it, and when the latch closes, the shift register turns the byte into lit and unlit segments, displaying a number. Since we are using four chained registers, we will send the bytes in a certain order, and the registers will overflow until all of them have one byte.

For constructing the numbers, there are two byte tables. One is for the numbers without a decimal point, but the second number must show a decimal point to separate minutes from seconds. They look like this:

const byte numTable[] =
{
  B11111100,  //numeral 0
  B01100000,  //numeral 1
  B11011010,  //numeral 2
  B11110010,  //numeral 3
  B01100110,  //numeral 4
  B10110110,  //numeral 5
  B10111110,  //numeral 6
  B11100000,  //numeral 7
  B11111110,  //numeral 8
  B11110110   //numeral 9
};

and the decimal point one is

const byte numTableDP[] =
{
  B11111101,  //numeral 0
  B01100001,  //numeral 1
  B11011011,  //numeral 2
  B11110011,  //numeral 3
  B01100111,  //numeral 4
  B10110111,  //numeral 5
  B10111111,  //numeral 6
  B11100001,  //numeral 7
  B11111111,  //numeral 8
  B11110111   //numeral 9
};

The difference is the final byte as you can see. If it’s 0, no decimal point, if a 1, there is a decimal point. Numbers are picked from the array much in the same way as in the previous application, indeed this is very close to that one, but the data is sent in a different way. You will send it in four bytes, using this function send7segs():

void send7segs(){ 
  digitalWrite(_7segLATCH,LOW);    //Open shift registers for data
  shiftOut(_7segDOUT,_7segCLK,LSBFIRST,numTable[q]);   //send fourth digit
  shiftOut(_7segDOUT,_7segCLK,LSBFIRST,numTable[z]);   //send third digit
  shiftOut(_7segDOUT,_7segCLK,LSBFIRST,numTableDP[y]); //send second  
                                                       //digit with dp
  shiftOut(_7segDOUT,_7segCLK,LSBFIRST,numTable[x]);   //send first digit
  digitalWrite(_7segLATCH,HIGH);                       //end the transfer 
                                                       //of data

The second digit needs to show the decimal point, hence the byte is picked from a different table. Of course, you could do some bit arithmetics here and use just one table, but this method came to my mind first and worked, so I decided to go with it. The values x, y, z and q are derived from the remaining seconds as seen here in the main loop:

void loop(){
 if(digitalRead(doorPin)==LOW){  // while the switch at pin 3 is closed, this
                                 // will run
     second--;                   // second minus 1
   if (second==0) {              // handling the time out issue
     second = 2701;              // restarting at 45:01
   }
   mins = int(second/60);        // minutes as 45, 44, 43…
   secs = int(second % 60);      // seconds of every minute
   splitmins1 = int(mins / 10);  // first digit of minutes
   splitmins2 = int(mins % 10);  // second digit of minutes
   splitsecs1 = int(secs / 10);  // first digit of seconds
   splitsecs2 = int(secs % 10);  // second digit of seconds

   x = splitmins1; // index for first digit hexcode from num array
   y = splitmins2; // index for second digit hexcode from num array
   z = splitsecs1; // index for third digit hexcode from num array
   q = splitsecs2; // index for fourth digit hexcode from num array
   }
   else {                          // switch opens, the clock 
                                   // shows the time left at opening
     delay(10);
   }
   send7segs();
   delay(1000);
   }

The whole code is attached as a zip file to this blog post. The only thing I haven’t explained is a function called void clear_7segA(), but all it does is clear all the attached digits.

I hope you will find this foray into segmented LEDs useful. I certainly learned a lot while doing this project.

It works!

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.