Let’s suppose you have a project that needs to update three, 7-segment LEDs. Each 7-segment LED requires, well, 7 pins from your Arduino. That means you’ll need 21 pins from your Arduino to drive all 3 LEDs. Hmm, that’s a problem, Arduino’s don’t have 21 output pins. How about if we could use just 3 Arduino pins to drive all three, 7-segment LEDs! How can we do this, with shift registers. Read on to find out how.
All of the code used in this article can be found on GITHUB.
What is a Shift Register?
This article focuses on the 74HC595N shift register which is the little microchip shown below.
A shift register allows you to feed it a BYTE of data through the DS PIN that is split into individual bits and assigned to the output PINS Q0 (that’s a zero) through Q7.
How does this actually work? A shift register has two 8-bit registers. The first register is called the “stage” register and is where the last byte is sitting that you wrote to it. The second 8-bit register is for storage and you tell the shift register microchip to transfer the “stage” shift register to the “storage” shift register. The “storage” register is mapped to the output PINs Q0 through Q7.
When you write to a shift register the first thing you do is set the STCP to LOW. Each time you write a byte of data to the DS pin, the data goes into the “stage” register. It will remain there until you send the next byte of data. If you want the shift-register to transfer the “stage” register data to the “storage” register you need to raise the STCP to HIGH.
You can also piggy back or link shift registers together so that as bits are pushed out of one shift register they will feed another. This is shown in exercise 2 below.
Enough theory, let’s make a shift register do something.
Example 1 – Light Up 8 LEDs
Let’s do something fairly simple to get the feel of things. Let’s manage eight LEDs using a shift register. We’ll light each LED individually for 500 milliseconds and then start over from the beginning. The LEDs will light up in the sequence: 0,1,2,3,4,5,6,7,0,1,2,3,etc…
Here’s how the experiment will look when breadboarded…
You’ll need the following:
- 8 – LEDS – pick your favorite colors.
- 1 – 74HC595N Shift Register that can be purchased from DigiKey, Sparkfun, AdaFruit or many other sources. The 74HC595N is very common.
- 1 – Arduino – I like the Arduino Pro Mini from Sparkfun, but you can use whatever flavor you like.
- 1 breadboard
The first step is to prepare a breadboard to hold the 8 LEDs, the shift register and our Arduino. The following image was created using Fritzing and shows how the wiring is done.
Here’s how to wire them to your Arduino for our first test…
- Vcc – to power (+)
- Q0 – (+) side of LED 1
- DS – to Arduino PIN 4
- OE – to ground
- STCP – to Arduino PIN 5 – this is the latch pin. You start by writing a LOW value to this pin, then write the byte to DS then raise the STCP to HIGH
- SHCP – to Arduino PIN 6 – this is the clock pin and is how the Arduino and the Shift register agree on a clock
- MR – to power (+)
- Q7S – NOT USED YET – this is the piggy back PIN. If you connect this pin to another shift register DS pin then the bits will go to the next shift shift instead of going into the bit bucket.
- Q1 – (+) side of LED 2
- Q2 – (+) side of LED 3
- Q3 – (+) side of LED 4
- Q4 – (+) side of LED 5
- Q5 – (+) side of LED 6
- Q6 – (+) side of LED 7
- Q7 – (+) side of LED 8
- GND – to ground
Arduino Sketch Using One Shift Register and Eight LEDs
Next, we need to create the sketch that will exercise the shift register and light up the LEDs. Here’s how I approached it…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
const int DATAPIN1 = 4; // DS const int LATCHPIN1 = 5; // STCP const int CLOCKPIN1 = 6; // SHCP int ledValue = 1; void setup() { pinMode(DATAPIN1, OUTPUT); pinMode(LATCHPIN1, OUTPUT); pinMode(CLOCKPIN1, OUTPUT); } void loop() { digitalWrite(LATCHPIN1, LOW); shiftOut(DATAPIN1, CLOCKPIN1, MSBFIRST, ledValue); digitalWrite(LATCHPIN1, HIGH); ledValue = ledValue * 2; if (ledValue > 128) { ledValue = 1; } delay(500); } |
After you transfer the sketch to your Arduino you should be presented with a simple light show.
Example 1 – homework
Instead of having the lights start over at the beginning, have them go back. For example;
light the LEDs in the sequence, 0,1,2,3,4,5,6,7,6,5,4,3,2,1,0,1,2,3,etc…
Example 2 – Light 16 LEDs
In this experiment, we’ll leave the first shift register alone and tack on another breadboard with another shift register and another eight LEDs. Here’s how my mock up locked. It looks kind of messy because there are a lot of wires, but the wiring is simple as you see.
For this experiment, you’ll need the following:
- 16 LEDs
- 2 Shift Registers
- 1 breadboard
The only real difference between example 1 and 2 is that we’ll use the Q7S pin and wire up the next shift register as follows:
The first shift register is largey unchanged except for the one wire:
- Q7S – wired to DS PIN of second shift register
The second shift register gets wired pretty much as the first, except the DS PIN is wired to the Q7S pin of the first shift register.
- Vcc – to power (+)
- Q0 – (+) side of LED 1
- DS – to Q7S on the first shift register
- OE – to ground
- STCP – to Arduino PIN 5 – this is the latch pin. You start by writing a LOW value to this pin, then write the byte to DS then raise the STCP to HIGH
- SHCP – to Arduino PIN 6 – this is the clock pin and is how the Arduino and the Shift register agree on a clock
- MR – to power (+)
- Q7S – NOT USED
- Q1 – (+) side of LED 2
- Q2 – (+) side of LED 3
- Q3 – (+) side of LED 4
- Q4 – (+) side of LED 5
- Q5 – (+) side of LED 6
- Q6 – (+) side of LED 7
- Q7 – (+) side of LED 8
- GND – to ground
Here’s how the wiring looks in Fritzing…
Arduino Sketch Using Two Shift Registers and Sixteen LEDs
The code is pretty simple. If you look at the loop() method you’ll find two distinct logic flows. The first is when we are lighting LEDs associated with the first shift register. When doing this, we need to push an empty byte first so that when we push the byte that controls the LED on the first shift register, the second shift register receives the empty byte.
The second logic flow happens when we are lighting the LEDs connected to the second shift register. In this case, we push the byte with the bit set for the LED that we want to light and then we push an empty byte so that are first byte goes to the second shift register.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
const int DATAPIN1 = 4; // DS const int LATCHPIN1 = 5; // STCP const int CLOCKPIN1 = 6; // SHCP unsigned int ledValue = 1; void setup() { pinMode(DATAPIN1, OUTPUT); pinMode(LATCHPIN1, OUTPUT); pinMode(CLOCKPIN1, OUTPUT); } void loop() { // Using two shift registers and 16 LEDs, light // each LED individually. if (ledValue <= 128) { digitalWrite(LATCHPIN1, LOW); // Push an empty byte in the first shift register shiftOut(DATAPIN1, CLOCKPIN1, MSBFIRST, 0); // Then push the value byte into the shift register // which will be the display byte shiftOut(DATAPIN1, CLOCKPIN1, MSBFIRST, ledValue); digitalWrite(LATCHPIN1, HIGH); } else { // Push the value byte into the 1st shift register digitalWrite(LATCHPIN1, LOW); // The ledValue>>8 is a simple bit shift. shiftOut(DATAPIN1, CLOCKPIN1, MSBFIRST, ledValue>>8); // Push another byte into first shift register which // pushes the first byte into the second shift register. shiftOut(DATAPIN1, CLOCKPIN1, MSBFIRST, 0); digitalWrite(LATCHPIN1, HIGH); } ledValue = ledValue * 2; if (ledValue == 0) { ledValue = 1; } delay(500); } |
Summary
Shift registers provide a way to save output pins. They are pretty simple to use and cheap to buy. In my Sail Speed project, I have six, 7-segment LEDs that I’m controlling through shift registers and I’ve found the solution to be very easy to work with.
I hope this article helped you with you project.