Seven segmented displays are great. They are pretty simple, don't take much power, and have a lot of flexibility when it comes to displaying numbers. But setting aside 14 pins just to run it is such a pain. If only there was a way to use them without sacrificing so many precious pins. Turns out there is! Shift Registers are logical IC's that can hold or shift data sent into them.  They only take up three pins! Combine this with the arduino function "ShiftOut" and there is a lot more options suddenly open. Oh, and one more great thing. They can be chained together to have even greater flexibility and still only using three pins. Just another one of the many things that I made at TechShop today.


Step 1: Materials

Arduino Uno

2 digit 7 segmented display (common anode)

2x 74HC595 (the shift registers can be picked up on places like sparkfun.com for about $1.50)

14x 660ohm resistors



usb cable

Step 2: Circuit

Now this can get a little dense and crazy if you're not careful so plan ahead and try to be as clean as possible. Not only do you have to keep track of which led goes where, you also have to keep track of how it interfaces with the shift registers. I used two colors for wiring so I knew which digit when where. Following the schematic and labeling your wires will be your best bet. Don't forget that because this is a common anode display all of the led's will be on when the IC sinks the current into them instead of being a source. 

Step 3: Shift Registers

But how does this all work? Shift registers have a very specific function. They either store a digital state or shift that state to the next bit on the next clock cycle. This means that a stream of bits can be shifted into registers in combination with the clock using just those two inputs. It doesn't "erase" anything, it just tries to shift it left and out to another register if possible. The third input, the latch, is used as a read/write safety. Even thought the clock tells when to shift, the latch must allow a shift to happen. If the latch is high, then data cannot be written to the register and the register holds the data.

Step 4: Code

Similar to the port manipulation process in an earlier instructable, the positions of each led need to be translated into numbers. By marking the combinations that result in numbers and formatting that into binary of hex data, each number can be easily accessed. 

This is the code for making the shift registers count from 0 to 99 and loop. Notice how the latch first has to be set low, then shifted out out, then set high again. The latch is what allows the registers to retain their position in between clock cycles. The second digit comes first because it is sent into register 1 and then shifted by 1 byte out to register 2 as digit one takes its place.

#define LATCH 4
#define CLK 3
#define DATA 2

//This is the hex value of each number stored in an array by index num
byte digitOne[10]= {0x6F, 0x09, 0x73, 0x3B, 0x1D, 0x3E, 0x7C, 0x0B, 0x7F, 0x1F};
byte digitTwo[10]= {0x7B, 0x11, 0x67, 0x37, 0x1D, 0x3E, 0x7C, 0x13, 0x7F, 0x1F};

int i;

void setup(){
  pinMode(LATCH, OUTPUT);
  pinMode(CLK, OUTPUT);
  pinMode(DATA, OUTPUT);

void loop(){
  for(int i=0; i<10; i++){
    for(int j=0; j<10; j++){
      digitalWrite(LATCH, LOW);
      shiftOut(DATA, CLK, MSBFIRST, ~digitTwo[i]); // digitTwo
      shiftOut(DATA, CLK, MSBFIRST, ~digitOne[j]); // digitOne
      digitalWrite(LATCH, HIGH);

That's all for shift registers!
<p>This was really helpful and works wonderfully. Unfortunately I need to drive 5 seven segments and don't know how to work out the hex values for the rest of the places. Can you please help?</p>
<p>I have risen from the dead to answer your post! For more than a couple of 7 segmented displays, I would advise against using this method. The wiring alone is unnecessarily complex and is prone to making errors. One error, and the whole thing goes crazy. I would instead recommend using 7 segmented displays that work on the i2c bus. You can put multiple ones of those on just 2 pins, analog 4 and 5 on the Uno. I haven't written a tutorial for that, but I know that i2c powered displays are also well documented.</p>
<p>Hi! please rise from the dead again. What do i change in the code to make it countdown from 30</p>
<p>hi, i am confusing about how to write <em>hex value of each number stored in an array by index num </em></p><p><em>please explain</em></p><p><em><br></em></p><p><em>thank you</em></p>
<p>Hello,</p><p>I use common cathode displays, it works but it displays anything. Can you help me to adapt the code? (Reverse the signal?) Thanks</p>
<p>I found ! I removed the &quot;~&quot; and I changed the hexadecimal code because the pinout of my display is different from yours.</p><p>Thanks for this Instructable !</p>
<p>Done! I I finished my project using these displays: A toy washing machine:</p><p><a href="https://www.instructables.com/id/Making-a-Motorized-Washing-Machine-for-Children-Wi/">https://www.instructables.com/id/Making-a-Motorized...</a></p>
<p>please help ,,writing code</p>
<p>HOW TO DISPLAY ANALOG value on 74hc595 based 4-digit 7 segment display using arduido mega boart through SPI Communication.</p>
<p>i made this via matLab &gt;&gt; https://www.youtube.com/watch?v=gw9FbqH85Po</p>
<p>Thanks for your post it helped me a lot</p><p>My design is slitly different (only one resistor), due to hardware and child &quot;sabotage&quot; (he took one chip when I was not looking ... and I'm still trying to find it).</p>
<p>I've been looking around for some time, trying to find a nice, simple code to help me interface with a 3 digit 7 segment display. Today I have found it! Thank you for taking the time to upload your instructable. I had to make some changes to the hex data for digitOne and digitTwo, only because I had outputs wired/soldered differently. For the third digit, I created a third data array, and added the appropriate code in the loop. </p><p>Here's the code that worked for me, if it can help anyone else: </p><p>#define LATCH 4<br> #define CLK 3<br> #define DATA 2</p><p> //This is the hex value of each number stored in an array by index num<br> byte digitOne[10]= {0x88, 0xE6, 0x41, 0x44, 0x26, 0x14, 0x18, 0xC6, 0x00, 0x04};<br> byte digitTwo[10]= {0x88, 0xE6, 0x41, 0x44, 0x26, 0x14, 0x18, 0xC6, 0x00, 0x04};<br> byte digitThree[10]= {0x88, 0xE6, 0x41, 0x44, 0x26, 0x14, 0x18, 0xC6, 0x00, 0x04};</p><p> int i;</p><p> void setup(){<br> <br> pinMode(LATCH, OUTPUT);<br> pinMode(CLK, OUTPUT);<br> pinMode(DATA, OUTPUT);<br> <br> }</p><p> void loop(){<br> for(int h=0; h&lt;10; h++){<br> for(int i=0; i&lt;10; i++){<br> for(int j=0; j&lt;10; j++){<br> digitalWrite(LATCH, LOW);<br> shiftOut(DATA, CLK, MSBFIRST, ~digitThree[h]); // digitThree<br> shiftOut(DATA, CLK, MSBFIRST, ~digitTwo[i]); // digitTwo<br> shiftOut(DATA, CLK, MSBFIRST, ~digitOne[j]); // digitOne<br> digitalWrite(LATCH, HIGH);<br> delay(1000);<br> }<br> }<br> }<br> }</p><p>Anyways, thanks again for the post!</p>
<p>Tq to your tutorial, i made it. Although i confused with byte, because my 7 segment is common anode. If i want to make 8 = 00000000, not 01111111.</p>
<p>Nice instruable! I was able to follow it and understand the logic behind it all! The only thing I'm not grasping (and this may be my own stupidity) but how does it &quot;shiftout&quot;? I get that to make a &quot;one&quot; the hex is 0x09 (if I'm reading correctly) but how does the arduino/IC's know which IC to send that out to? Thanks! </p>
<p>The shift register has an output pin which is connected to the input pin of the next shift register. Both shift registers share the clock and (where applicable) the latch, but the uC only shifts data into the first register. It's up to the uC programming to know that it needs to shift 8, 16, 24, 32, or whatever number of bits in order to populate all of the registers - the bits merely &quot;fall out&quot; of one end into the next (and don't require latching to do so).</p><p>With different coding, this project could be made with common segment addressing, pulsing each digit (so, write two bytes out to the registers - one to identify the numeric arrangement, and a second to identify which one of multiple digit positions to illuminate). Such an arrangement could drive EIGHT 7-segment digits with just the two shift registers, and half as many resistors, but at a slight cost to overall brightness (which might be offset by the reduction in current drain, and therefore lesser voltage drop).</p>
<p>Hi great work...I need an advice on how i can increment and decrement the counting using push button switches.</p><p>thanks</p>
great work! you should also check out binary to 7 seg decoders. They make it really easy to drive 7 segs: <br />https://www.instructables.com/id/Breadboard-How-To/step5/7-Segment-Display-on-a-Breadboard-Part-2/ <br />you just send them binary data and they output the appropriate decimal number on the 7 seg. I was driving a common cathode 7 seg, but you can find decoders for common anode as well.

About This Instructable




More by madebyjoe:Arduino powered GLCD (Graphic LCD) - I made it at TechShop Arduino Bluetooth Serial Connections! - I made it at TechShop Android Tablet PS3 / Xbox360 Controller Mount - I made it at TechShop 
Add instructable to: