Introduction: Arduino Powered 7 Seg LED Display Using Shift Registers - I Made It at TechShop

Picture of Arduino Powered 7 Seg LED Display Using Shift Registers - I Made It at TechShop

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.

http://techshop.ws

Step 1: Materials

Picture of 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

breadboard

wire

usb cable

Step 2: Circuit

Picture of 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

Picture of 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

Picture of 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);
      delay(500);
    }
  }
}


That's all for shift registers!

Comments

Ronak Dhaduk (author)2017-09-11

Plese give me the counter clockwise code for this ic

Thank You

ANSHU_SINGH (author)2016-09-10

HOW TO DISPLAY ANALOG value on 74hc595 based 4-digit 7 segment display using arduido mega boart through SPI Communication.

winniepough (author)ANSHU_SINGH2017-09-07

I think it was you to whom I sent a message with 'how to display characters characters to 7 segmnents. would you please send back a copy. i lost the file. dmb_job1@yahoo.com

vinodchinthoti (author)2017-02-28

hi, i am confusing about how to write hex value of each number stored in an array by index num

please explain


thank you

Hex code for digits

const uint8_t digitToSegment[] =
XGFEDCBA
0b00111111, // 0 // A
0b00000110, // 1 // ---
0b01011011, // 2 // F | | B
0b01001111, // 3 // -G-
0b01100110, // 4 // E | | C
0b01101101, // 5 // ---
0b01111101, // 6 // D
0b00000111, // 7
0b01111111, // 8
0b01101111, // 9
0b01110111, // A
0b01111100, // b
0b00111001, // C
0b01011110, // d
0b01111001, // E
0b01110001, // F end Hex
0bo1110000, // c begin other char
0b01110110, // H
0b01110100, // h
0b00110000, // I left two segments
0b00010000, // i more sense to use lower case to avoid confusion with lower case L
0b00111000, // L
0b00000110, // l right two segmants, same as a one
0b01010100, // n
0b00111111, // O same as a zero
0b01011100, // o
0b01110011, // P
0b01001000, // r
0b01101101, // S same as a five
0b00111111, // U
0b00011101, // u
0b00000000, // blank
0b01001000, // = equals
0b01000000, // - dash / minus
0b00001000, // _ underscore
0b00111001, // [ left bracket
0b00001111, // ] right bracket
};

static const char CharToInt8_t[37] = ('0','1','2','3','4','5','6','7','8','9','A','B','C','d','E','F',
'c','H','h','I','i','L','l','n','O','o','P','r','S','U','u',' ','=','-','_','[',']');

7hjain (author)2014-08-17

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?

madebyjoe (author)7hjain2014-08-18

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.

MashC (author)madebyjoe2017-03-01

Hi! please rise from the dead again. What do i change in the code to make it countdown from 30

MagicManu (author)2016-12-09

Hello,

I use common cathode displays, it works but it displays anything. Can you help me to adapt the code? (Reverse the signal?) Thanks

MagicManu made it! (author)MagicManu2016-12-09

I found ! I removed the "~" and I changed the hexadecimal code because the pinout of my display is different from yours.

Thanks for this Instructable !

MagicManu (author)MagicManu2017-01-03

Done! I I finished my project using these displays: A toy washing machine:

https://www.instructables.com/id/Making-a-Motorized...

ANSHU_SINGH (author)2016-09-10

please help ,,writing code

namila007 made it! (author)2016-09-04

i made this via matLab >> https://www.youtube.com/watch?v=gw9FbqH85Po

SylvainM2 made it! (author)2015-10-04

Thanks for your post it helped me a lot

My design is slitly different (only one resistor), due to hardware and child "sabotage" (he took one chip when I was not looking ... and I'm still trying to find it).

NathanW7 (author)2015-06-16

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.

Here's the code that worked for me, if it can help anyone else:

#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]= {0x88, 0xE6, 0x41, 0x44, 0x26, 0x14, 0x18, 0xC6, 0x00, 0x04};
byte digitTwo[10]= {0x88, 0xE6, 0x41, 0x44, 0x26, 0x14, 0x18, 0xC6, 0x00, 0x04};
byte digitThree[10]= {0x88, 0xE6, 0x41, 0x44, 0x26, 0x14, 0x18, 0xC6, 0x00, 0x04};

int i;

void setup(){

pinMode(LATCH, OUTPUT);
pinMode(CLK, OUTPUT);
pinMode(DATA, OUTPUT);

}

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

Anyways, thanks again for the post!

yudha_hamdi made it! (author)2014-09-28

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.

DoctorWoo (author)2014-05-22

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 "shiftout"? I get that to make a "one" 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!

splud (author)DoctorWoo2014-07-28

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 "fall out" of one end into the next (and don't require latching to do so).

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).

stiu (author)2014-07-08

Hi great work...I need an advice on how i can increment and decrement the counting using push button switches.

thanks

amandaghassaei (author)2012-08-17

great work! you should also check out binary to 7 seg decoders. They make it really easy to drive 7 segs:
https://www.instructables.com/id/Breadboard-How-To/step5/7-Segment-Display-on-a-Breadboard-Part-2/
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

112,174views

73favorites

License:

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