Introduction: 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
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
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);
delay(500);
}
}
}
That's all for shift registers!
14 Comments
5 years ago
Plese give me the counter clockwise code for this ic
Thank You
6 years ago
HOW TO DISPLAY ANALOG value on 74hc595 based 4-digit 7 segment display using arduido mega boart through SPI Communication.
Reply 5 years ago
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
6 years ago
hi, i am confusing about how to write hex value of each number stored in an array by index num
please explain
thank you
Reply 5 years ago
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',' ','=','-','_','[',']');
8 years ago on Introduction
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?
Reply 8 years ago on Introduction
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.
Reply 6 years ago
Hi! please rise from the dead again. What do i change in the code to make it countdown from 30
6 years ago
please help ,,writing code
7 years ago on Step 4
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!
9 years ago on Introduction
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!
Reply 8 years ago on Introduction
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).
8 years ago on Step 4
Hi great work...I need an advice on how i can increment and decrement the counting using push button switches.
thanks
10 years ago on Introduction
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.