loading
This instructable will attempt to explain, in simple terms, what a shift register is, and how you can use it with the Raspberry Pi to expand the GPIO port by running eight outputs with just four GPIO ports.

To start with, what is a shift register?  Wikipedia has a technical definition of shift registers, but in a nut shell, shift registers let you take serial input (one bit after the other), and output it in parallel.

Let's say, for example, you wanted to output six digital bits from your Raspberry Pi to drive a display based on the HD44780, like this one, but your project had to give up almost all the GPIO to other things, and all you have left is four pins. You can send those six bits one after the other to the shift register using those four pins, which will then appear to the display as six parallel outputs.

For this project, which is a first step towards the above situation, I'm going to run LEDs off each of the eight outputs, just as a proof of concept.  The attached video shows the end result of this process.  Just a bunch of flashing lights for now, but stay tuned.  This is really the second in a series of instructables leading up to my Voiceberry Pi  (see the first one here).

Step 1: Wiring Up the Chip Part 1: Data Pins 1-4

I picked up a few shift registers for $0.39 each at Jameco.com.  The ones I eneded up getting were SN74HC164N's from Texas Instruments.  Not that it really means anything one way or the other, but that's what I ended up getting.  The datasheet is available right there at Jameco, and details how to wire up the chip are in there.  But here's the pinout:

1: Input A
2: Input B
3: Data 1
4: Data 2
5: Data 3
6: Data 4
7: Ground
8: Clock
9: NOT Clear
10: Data 5
11: Data 6
12: Data 7
13: Data 8
14: Vcc

Unless you get the same chip, your pinout will be different, and you should follow your datasheet.

To start with, the chip goes in the bread board, and then four LEDs are linked up from data pins 1-4 to a common lead (not ground, yet).

Step 2: Wiring Up the Chip Part 2: Data Pins 5-8

To wire up the next four LEDs, they go into the breadboard right next to the first four, but then wires need to run from the data pins 5-8 to the anode of the LEDs.

Additionally, a limiting resistor has to be inserted between the LEDs' cathodes and what will become ground.

Step 3: Wiring Up the Chip Part 3: the Other Pins

The next wires too hook up are, in order of the pictures:

Vcc: Chip pin 14 to GPIO pin 2
Ground: Chip pin 7 to GPIO pin 6
Clock: Chip pin 8 to GPIO 7
NOT Clear:Chip pin 9 to GPIO 11
Input A: Chip pin 1 to GPIO pin 13
Input B: Chip pin 2 to GPIO pin 15

Note that GPIO 2 and 6 are hard wired as +5V and Ground repsectively, but all other GPIO pin choices were quite arbitrary.  I could have used any valid GPIO pin, and chose the ones I chose to keep them close to the ground and 5v pins.

Step 4: Now What? or I Still Don't Get It!

So you've got it all wired up, but what does it all mean?  How does it work, and how to do I make it work?  Well, this varies a little from chip to chip, but for the most part it's the same.

NOT Clear is set to low first, to clear the shift register, and then the clock is turned HIGH and LOW.
The input wire can be high or low, depending on what you want to set, and the clock is turned HIGH and LOW.
Each bit to be sent in is set either high or low, and the clock is turned HIGH, then LOW.

Each time you want to send another bit to the register, you set that bit on the input, and then "tick" the clock, by setting it HIGH, then LOW. There is a minimum time the clock must be HIGH, but the timing of the RPi is such that turning it HIGH, then immediately LOW will be more than the minimum time for my chip.

My video shows the LEDs switching back and forth between and ON OFF pattern and and OFF ON pattern.  As an example, let's setup the OFF ON pattern.

1) Set NOT Clear LOW, and tick the clock (turn clock HIGH, then LOW).   Set NOT Clear HIGH. This clears all outputs.

2) Set the INPUT to HIGH, and tick the clock.  This sets the first output HIGH

3) Set the INPUT to LOW, and tick the clock.  This SHIFTS the outputs one to the right (1 goes to 2, 2 goes to 3, and so on), and
sets the first output to LOW.  Our pattern is now LOW HIGH

4) Set the INPUT to HIGH, and tick the clock.  This SHIFTS the outputs again, and sets the first output to HIGH.  Our pattern is now HIGH LOW HIGH

5) Set the INPUT to LOW, and tick the clock. This SHIFTS the outputs, and sets the first output to LOW, giveing LOW HIGH LOW HIGH

6) Set the INPUT to HIGH, and tick the clock. This SHIFTS the outputs again, and sets the first output to HIGH.  Our pattern is now HIGH LOW HIGH LOW HIGH

7) Set the INPUT to LOW, and tick the clock. This SHIFTS the outputs, and sets the first output to LOW, giveing LOW HIGH LOW HIGH LOW HIGH

8) Set the INPUT to HIGH, and tick the clock. This SHIFTS the outputs again, and sets the first output to HIGH.  Our pattern is now HIGH LOW HIGH LOW HIGH LOW HIGH

9) Set the INPUT to LOW, and tick the clock. This SHIFTS the outputs, and sets the first output to LOW, giveing LOW HIGH LOW HIGH LOW HIGH LOW HIGH

Step 5: The Code

Attached to this step is my code to run the video you've seen twice now.

An important part of the code I'd like to point out is the sleep statement.  It seems so unimportant, but it's really not.

After you go through the process in the last step of setting your output, if you go right into clearing and setting your next output, you'll never get to "see" it on your LEDs.  It will just flash too quick to see it.  So you HAVE to pause the execution of the code for a second to get the LEDs to stay lit long enough for you to see them.

while running==True:
         try:
           shifter.clear()
           shifter.setValue(80)
           sleep(1)
           shifter.clear()
           shifter.setValue(170)
           sleep(1)
         except KeyboardInterrupt:
            running=False

Also, as an aside, notice what I did with the try/except statements.  This allows you to exit the code using Control-C, without generating the normal error.  A little thing, but I like how it works out.

Also note that this code is object oriented, and can be imported into other projects at a later date.  This will allow you to set output easily and quickly with this circuitry.

Step 6: Next Steps and Insights

What's next?  Well, finding a purpose for this, like running a display. Which is what my next step will be.

An insight: This chip really has two inputs.  Not all chips do, and I've passed over what the second input does.  This chip takes an AND on both inputs, and only considers the input HIGH when BOTH Input A and Input B are HIGH.  So I just set Input A HIGH the whole time, and kind of ignore it's there.

Another fun task, and I'll only give you hints here, would be to chain two (or more) shift registers together.  To do this with these chips, join up their Vccs, grounds and Input As, then hookup Data 8 of the first to Input B of the second.  OK, I'll just tell you how it's done, but not detail it step by step.

Stay tuned for the next two instructables--using a display with a shift register, and then, the long awaited, much anticipated, Vocieberry Pi.
<p>I could not open any of the videos you provided.</p>
<p>A couple of words of caution:</p><p>1) In Step 2), it looks like you are using one current limiting resistor and is it 22 ohms? 1/4W or 1/2W? Using one current limiting resistor with 8 LED's will make all the current go through one resistor. That can be bad for a project.</p><p>Say Vled = 1.8V</p><p>Vpin = 5V</p><p>Vresistor = Vpin - Vled = 5V - 1.8V = 3.2V</p><p>R = Vresistor / Isink</p><p>If I read the spec sheet correctly for a TI SN74HC164, I(input clamp) = +/- 20mA</p><p>I think that is the maximum current that can be sunk by a pin when low.</p><p>R = 3.2V / 20mA = 16 ohms</p><p>However, you have all LED's routed through one resistor.</p><p>I = 3.2V / 22 ohms = 0.145A</p><p>0.145A x 8 = 1.16A</p><p>P = (I^2)R = (1.16A ^ 2)22ohms = 29.6W</p><p>If you have your project working with these values, I must have missed something - it would not be the 1st time!</p><p>1.16A would be far too high for even a 1/2W resistor.</p><p>2) A schematic would go a long way to resolving what is going on here, what the resistor value is, exactly how the IC, LED's and resistor are all connected.</p><p>3) A list of components or BOM would also make things easier, especially when trying to gather your parts. This might seem unecessary with a project with only three different electronic components invovled, but it would resolve my questions.</p>
found out what was wrong - putting clear high in Shifter.setupBoard to start with and having Shifter.clear oscillate from low to high. <br>I am using a different chip but I don't know how that changes things (as I don't know lots about chips - other than eating them [omm nom nom nom]) <br> <br>Thanks for writing and sharing your code mrmath. I'm not moaning. <br> <br>For anyone else out there if you are using a 74HC595 with RPi.GPIO a slight adjustment is needed.
sage advice... I will have another go at wiring it. <br>Thanks!!
First thing I would check is to make sure the wiring is coming from the chips pins to the diodes correctly. Next I would swap out the chip for another one if that's possible. Last thing I'd do is tear the whole thing down, and start from scratch. Can't tell you how many times I've had a circuit not working, and been unable to find a wiring error, tore it down out of frustration, built it back up, and had it work perfectly. <br> <br>Good luck!
Hi, <br> <br>I get an odd thing happen using a 74HC595 - my left most led is in essence a mirror to the number 2 (adjacent) <br>I looped through all the values for setValue from 0 (totally blank) to 255. It's like I'm only 7 bit. <br> <br>any thoughts? Otherwise it seems to work nicely.
Sorry, but after putting all wires and check everything, I used the code and nothing happens. I added to the code the typical # / usr / bin / python. I tried changing the pins numbering but nothing happens. What i do wrong? <br>
is correct #inputA=15 or inputA=15 whitout #?
My shift register has two inputs that are ANDed together, so I have an inputA and and inputB. Originally, I was setting inputA high and using the input on inputB to run the shift register, but then I changed it to link inputA directly to inputB on the breadboard, and I didn't need inputA in my code anymore. So I commented it out.
At least it works, i change the pin numbering and voil&aacute; <br>
The last thing is <br>Which values are correct for the argument of setValues Function?
Whatever you want the output to be. It's binary, but flipped, so 1 is on the left and 128 is on the right. So 0x15 is HEX for 37, which in binary is 00010101. That would light the first, third and fifth LEDs from left to right.
thanks again
thank you!!!! this afternoon i'll prove it
WAIT! That was the wrong code. You have to get the code that I just put up there. shifter.py. NOT shifterDisplay.py. My apologies!
where is the code? <br>
Don't know what happened there, but I've attached it now. You should see it right on the first step. Sorry about that.

About This Instructable

68,672views

72favorites

License:

More by mrmath:Running an HD44780 Display off the ATmega on a Gertboard Voiceberry Pi! Driving an HD44780 Display using a Shift Register and a Raspberry Pi 
Add instructable to: