loading
Picture of The 74HC164 Shift Register and your Arduino
PDR_0103.JPG
Shift registers are a very important part of digital logic, they act as glue in between the parallel and serial worlds. They reduce wire counts, pin use and even help take load off of your cpu by being able to store their data.

They come in different sizes, with different models for different uses, and different features. The one I will be discussing today is the 74HC164 8 bit, serial in parallel out, non latched, shift register.

Why? Well for one it is one of the most basic shift registers out there, which makes learning about it easier, but it just so happened to be the only one I had (lol!)

This instructable covers how this chip works, how to wire it, and interface it with an arduino including some sample sketches and led circuits.

I hope you all enjoy!



 
Remove these adsRemove these ads by Signing Up

Step 1: So, what are shift registers?

Picture of So, what are shift registers?
As mentioned earlier they come in all different flavors, and I also mentioned that I am using a 74HC164 8 bit, serial in parallel out, non latched, shift register

so what does that all mean?!?

First, the name
74 -- means its part of the 74xx logic family, and since its logic it cannot directly control very much current  (16-20ma for the entire chip is common) , it only passes signals around, but that does not mean that signal is not going to a transistor which can switch a higher current load.

HC means its a high speed cmos device, you can read about that on the link below, but what you basicly need to know about that is that it is a  low power device and will run from 2 to 5 volts (so if your using a 3.3 volt arduino your ok)

Also it can work properly at high speeds this particular chip has a typical speed of 78mhz, but you can go as slow or as fast (until it starts goofing up) as you want
www.kpsec.freeuk.com/components/74series.htm

164 is the model number for this chip, there is a large chart of them on wikipedia
en.wikipedia.org/wiki/List_of_7400_series_integrated_circuits

Next, 8 bit
A shift register is made up of flip flop circuits, a flip flop is 1 bit of memory, this one has 8 (or 1 byte of memory). Since it is memory, if you do not need to update the register you can just stop "talking" to it and it will remain in whatever state you left it, until you "talk" to it again or reset power.

other 7400 logic series shift registers can go upto 16 bit

serial in parallel out

This means your arduino sends it data serially (on off pulses one after another) and the shift register places each bit on the correct output pin. This model only requires 2 wires to be controlled, so you can use 2 digital pins on the arduino, and break those 2 out to 8 more digital outputs

some other models are parallel in serial out, they do the same thing but as inputs to the arduino (for example a NES gamepad)

non latched

This may be a downfall of this chip if you need it. As data enters a shift register via serial, it shows up on the first output pin, when a clock pulse enters in, the first bit shifts over 1 place, creating a scrolling effect on the outputs, for example 00000001 would show up on the outputs as

1
01
001
0001
00001
000001
0000001
00000001

If your talking to other logic devices who are sharing the same clock and not expecting this, it  could cause issues. Latched shift registers have an extra set of memory, so once the data is done entering the register you can flip a switch and show the outputs, but it adds another wire, software, and things to keep up with.

In the case of this instructable we are controlling LED displays, the scrolling effect happens so fast you cant see it (except when you very first turn on the chip), and once the byte is in the shift register there is no more scrolling

We will be controlling bargraph type, 7 segment, and a 16LED 4x4 dot matrix with this chip and software on the arduino using only 2 digital pins (+ power and ground)



Step 2: Basic wiring and operation

Picture of Basic wiring and operation
pinout.jpg
Wiring
The 74HC164 is a 14 pin chip, it has 4 input pins, 8 output pins, power and ground, so lets start from the top.

Pins 1 and 2 are both serial inputs, they are setup as a logical AND gate, meaning that they both have to be logic high (ie 5 volts) in order for the bit to be seen as a 1, a low state (0 volts) on either will read as a zero.  We dont really need this and its easier to deal with in software, so choose one and tie it to V+ so it always reads high. I choose to use a jumper from pin 1 to pin 14 (V+) since you can just pop a breadboard jumper over the chip. The one remaining serial input (pin 2 in my schematics) will goto digital pin 2 of the arduino.

Pins 3,4,5,and 6 of the 74HC164 are the first 4 bytes of output

Pin 7 connects to ground

Jumping to the right, pin 8 is the clock pin, this is how the shift register knows the next serial bit is ready for it to read, this should be connected to digital pin 3 on the arduino.

Pin 9 is to clear the entire register at once, if it goes low, you have the option to use it, but nothing in this inscrutable does, so tie it to V+

pins 10, 11 12 and 13 are the last 4 bytes of output

pin 14 is the chips power

Operation
First you need to set the serial input of the register (digital pin 2 on the arduino) high or low, next you need to flip the clock pin (digital pin 3) from low to high, the shift register will read the data on the serial input and shift the output pins by 1, repeat 8 times and you have set all 8 outputs.

This can be done by hand with for loops and digital writes in the arduino IDE, but since this is a very common hardware level communications (SPI) they have a single function that does it for you.

shiftOut(dataPin, clockPin, bitOrder, value)

Just tell it where the data and clock pins are connected to the arduino, which way to send the data and what to send, and its taken care of for you (handy)

Step 3: Projects

Picture of Projects
Okay, enough lecture and theory, lets do some fun stuff with this chip!

There are 3 projects to try in this instructable, the first 2 are easy and can be breadboarded out in moments. The third one, the 4x4 led matrix, requires more time and thought to construct, due to the led wiring.

List of parts

Project 1: '2 Wire' bargraph LED display controller
1 * 74HC164 Shift register
1 * solderless breadboard
1 * arduino, or arduino compatible (5v)
1 * 330 ohm 1/4 watt resistor
8 * normal output red LED's
12 * jumper wires

Project 2: '2 Wire' 7 segment display controller

1 * 74HC164 Shift register
1 * solderless breadboard
1 * arduino, or arduino compatible (5v)
1 * 330 ohm 1/4 watt resistor
1 * common cathode seven segment display
9 * jumper wires

Project 3: '2 Wire' 4x4 led matrix display
1 * 74HC164 Shift register
1 * arduino, or arduino compatible (5v)
4 * 150 ohm 1 1/4 watt resistor
8 * 1Kohm 1/8 watt resistor (or larger)
8 * NpN transistor (2n3904 or better)
16 * normal output red LED's

a means to construct it and regulated 5 volt power that can handle 160+ma (you can turn on all the LED's at once like a brake light)


Step 4: Project 1[pt 1]: '2 Wire' bargraph LED display controller hardware

Picture of Project 1[pt 1]: '2 Wire' bargraph LED display controller hardware
PDR_0105.JPG
Hook up the arduino and shift register according to the schematic, I already have a 10 segment bargraph display ready for breadboard use and that is what you will see in the image, but you can do the same thing  with individual led's

On the second page I stated that these were not driver devices, that they were logic devices, with tiny amounts of current able to pass through them. In order run 8 LEDs, while keeping the circuit simple, and not cooking the shift register, requires that we limit the current quite a bit.

The LED's are wired in parallel and share a common ground (common cathode), before going into the power supply ground they need to pass through a 330 ohm resistor, limiting the total amount of current that all the LED's could possibly use to 10ma (at 5 volts)

This leaves the LED's in a sickly looking state but they do light up and thus serve for this example, in order to drive the LED's at their proper current you will need to insert a transistor where the shift register can turn on / off a higher current source (see project 3)

The Data pin of the shift register (pin 2) needs to connect to arduino digital pin # 2
The Clock pin of the shift register (pin 8) needs to connect to arduino digital pin # 3

Step 5: Project 1[pt 2]: '2 Wire' bargraph LED display controller software

Picture of Project 1[pt 2]: '2 Wire' bargraph LED display controller software
msls.jpg
Example 1:
Open the file " _164_bas_ex.pde" Inside the arduino IDE, Its a simple sketch that just lets you define on or off  LED's in the bargraph display

The first 2 lines define the pin numbers we will be using for data and clock, I use #define over const integer, I find it easier to remember, and there is no advantage to one or the other once compiled

#define data 2
#define clock 3


next is the void setup function, it only runs once, so the arduino turns on, sets the shift register and has nothing else to do. Inside the void setup function we set the clock and data pins as OUTPUT pins, then using the shiftOut function we send the data to the shift register

void setup()
{
  pinMode(clock, OUTPUT); // make the clock pin an output
  pinMode(data , OUTPUT); // make the data pin an output
  shiftOut(data, clock, LSBFIRST, B10101010); // send this binary value to the shift register
}


In the shiftOut function you can see its arguments
data is the data pin, clock is the clock pin

LSBFIRST refers to what order its in, when writing it out in binary notation (Bxxxxxxxx) the 7th element past the B is the Least Signifigant Bit First, this is fed in first so it ends up on the last output once all 8 bits are fed in

B10101010 is the Binary value being sent to the shift register, and it will turn on every odd light, try playing with different values to turn on or off different patterns

and finally a empty void loop (because you need one even if your not using it)

void loop(){} // empty loop for now


Example 2:
the first 8 lines are the same as the first 8 lines of the first example, in fact they will not change for any of the other projects, so

#define data 2
#define clock 3

void setup()
{
  pinMode(clock, OUTPUT); // make the clock pin an output
  pinMode(data , OUTPUT); // make the data pin an output


But now in void setup there is an 8 count for loop, its taking an empty byte and shifting 1 bit in at a time starting from the leftmost bit and moving right. This is backwards from the first example where we started from the rightmost bit and worked left, but using MSBFIRST the shift out function sends the data the correct way

Also we add a delay in the for loop so it slows down enough to be visible.

  for(int i = 0; i < 8; ++i) //for 0 - 7 do
  {
    shiftOut(data, clock, MSBFIRST, 1 << i); // bit shift a logic high (1) value by i
    delay(100); // delay 100ms or you would not be able to see it
  }
   
}

void loop(){} // empty loop for now


upload the script and you should now see the bargraph light up each light one at a time

 

Step 6: Project 2: '2 Wire' 7 Segment display controller

Picture of Project 2: '2 Wire' 7 Segment display controller
7.jpg
Look at the pinout of your 7 segment display (I only had a dual one but just using half) and use the drawing below to connect each segment to the correct bit on the shift register

bit 1 = pin 3
bit 2 = pin 4
bit 3 = pin 5
bit 4 = pin 6
bit 5 = pin 10
bit 6 = pin 11
bit 7 = pin 12
bit 8 = pin 13 (if you want to use the decimal point)

And the cathode of the display through the 330ohm resistor and to power supply ground

now open the seven_seg_demo.pde in the arduino IDE

First you see where we define the data and clock pins

#define data 2
#define clock 3


Next we set all of the charater patterns in binary, this is pretty easy, look at the drawing below, if you need the middle segment type in a one, next do you need the top segment, if so  type in another one, keep doing this until you cover all 8 segments, notice my rightmost bit (bit 8) is always 0, thats becuase i never turn on the decimal point.

byte zero  = B01111110;
byte one   = B00000110;
byte two   = B11011010;
byte three = B11010110;
byte four  = B10100110;
byte five  = B11110100;
byte six   = B11111100;
byte seven = B01000110;
byte eight = B11111110;
byte nine  = B11110110;


next in void setup we set our data and clock pins to outputs

void setup()
{
  pinMode(clock, OUTPUT); // make the clock pin an output
  pinMode(data , OUTPUT); // make the data pin an output3
}


then in void loop we use shiftOut to display each pattern (number) wait 1/2 a second and display the next, 0 to 9, since its being done in the void loop function it will count 0-9 and repeat forever.

void loop()
{
    shiftOut(data, clock, LSBFIRST, zero);
    delay(500);
    shiftOut(data, clock, LSBFIRST, one);
    delay(500);
    shiftOut(data, clock, LSBFIRST, two);
    delay(500);
    shiftOut(data, clock, LSBFIRST, three);
    delay(500);
    shiftOut(data, clock, LSBFIRST, four);
    delay(500);
    shiftOut(data, clock, LSBFIRST, five);
    delay(500);
    shiftOut(data, clock, LSBFIRST, six);
    delay(500);
    shiftOut(data, clock, LSBFIRST, seven);
    delay(500);
    shiftOut(data, clock, LSBFIRST, eight);
    delay(500);
    shiftOut(data, clock, LSBFIRST, nine);
    delay(500);
}


Step 7: Project 3[pt 1]: '2 Wire' 4x4 led matrix display

Picture of Project 3[pt 1]: '2 Wire' 4x4 led matrix display
PDR_0096.JPG
The 4x4 LED matrix project is quite a bit more complex, but it is almost all in construction, I choose to make mine soldered on perfboard, but it should be possible to replicate on a breadboard , just a lot more spaced out.

The circuitry also differs in that the shift register is not directly driving the led's, instead the shift register outputs are sent through a 1Kohm resistor to the base of a NpN transistor, when the output of the bit is high, it lets enough current and voltage pass into the transistor to switch the connection tween the collector and emitter, the collectors are tied to a "sturdy" regulated 5 volts.

The emitters of the transistors are connected to 150 ohm resistors and the resistors are tied to the annodes of 4 led's in a row and limits the row to 20ma, although when drawing images on the display only 1 led is on at a time, and therefore near full brightness (near becuase they switch on and off really fast to make up the whole image)

There are 4 rows and 4 columns, each row gets a resistor and a transistor, on each column the LED's cathodes are tied together, ran into the collector of a transistor, whose base is also controlled by the shift register, and finally out to ground.

Large version of schematic
www.instructables.com/files/orig/F7J/52X0/G1ZGOSRQ/F7J52X0G1ZGOSRQ.jpg


Step 8: Project 3[pt 2]: '2 Wire' 4x4 led matrix display

Picture of Project 3[pt 2]: '2 Wire' 4x4 led matrix display
PDR_0107.JPG
PDR_0110.JPG
The shift register controls both the anode and the cathodes of the LED's in a YX format, look at the following

bit 1 = column 1 (rightmost)
bit 2 = column 2
bit 3 = column 3
bit 4 = column 4
bit 5 = row 1 (topmost)
bit 6 = row 2
bit 7 = row 3
bit 8 = row 4

To make an image draw out a 4x4 square on graph paper and fill in which ones you want displayed, next make a YX table. Below you will see a mapping for a simile, well as best one can do on 4x4 "pixels"

For each filled in section I write down which column (Y) it is in, then which row it is in (X)

Now open up the _4x4.pde file in the arduino IDE you will see our old 2 friends

#define data 2
#define clock 3


then a array of integers

int img[] = {1,1,4,1,1,3,4,3,2,4,3,4};

If you look its just a list of my written down YX coordinates, it would be a big pain in the butt to convert those values by hand, and we have a computer ... let it do it!

Moving on there is void setup where we make our clock and data pins OUTPUTS

void setup()
{
  pinMode(clock, OUTPUT); // make the clock pin an output
  pinMode(data , OUTPUT); // make the data pin an output3
}


And a confusing looking void loop, to start things off we need to declare some local variables

void loop()
{
  int Y;
  int X;
  byte out;


Then a for loop, this loop needs to be as long as the amount of entries in the img array, for this image I only used 6 pixels, so that makes 12 YX coordinates. I make it skip every other number by using i +=2, because we read 2 coordinates per loop

  for(int i = 0; i < 12; i += 2) // number of points in the img array, this case 12
  {


Now we read the Y  entery at [i] in the array, and subtract one from its value, because bytes don't start at one, they start at zero, but we counted from 1

    // get the first pair of YX cords
    Y = (img[i] - 1); // subtract one since the bit count starts at 0


Next we read the X  entery at [i + 1] in the array, and subtract one from its value, because of the same reason

     X = (img[i+1] - 1);

After we have the YX values of the pixel, we do some bitwise or math and shifting to the left.

First we need to read the X value, and whatever its value is shift it that many places + 4 left, so if X is 4 and add 4 it is bit 8 (MSB), looking at the chart again ...

bit 1 = column 1 (rightmost)
bit 2 = column 2
bit 3 = column 3
bit 4 = column 4
bit 5 = row 1 (topmost)
bit 6 = row 2
bit 7 = row 3
bit 8 = row 4

Bit 8 is the last row

Next the Y value is also shifted to the left, this time just by its self, nothing added on.

Finally the two are or'ed together into 1 byte instead of 2 half bytes (nibbles), using bitwise or (the symbol |   ) takes two bytes and basicly adds them together, lets assume

X   = 10000000
Y   = 00000001
--------------------
OR =10000001

row 4 column 1

out = 1 << (X + 4) | 1 << Y;

And finally shiftOut to display the current picture,  and keep doing that until we have no more data in the array ... delay a moment and loop forever, since we were shifting data to the left and we need the MSB to be on the last output pin of the shift register send it out first.

    shiftOut(data, clock, MSBFIRST, out); // shift the byte out to our register
    delay(1); // delay it abit so it has a chance to leave a spot of light in your eyes


Feel free to make your own images, and effects, There are 3 sample files, the smiley face and a checkerboard (which looks more like stripes), and finally a random sparkle maker
 

_4x4.pde884 bytes
_4x4_chx.pde892 bytes

Step 9: Conclusion

Picture of Conclusion
PDR_0102.JPG
PDR_0103.JPG
Over all this is a pretty handy little chip, and I am glad I scrapped it off of a old piece of electronics headed to the trash.

It can be used for other things besides display systems, but everyone likes lights and the instant feedback of seeing whats going on is extremely helpful for the visual thinkers like I.

Also please forgive my code, I have only had the arduino since bout the third week of October, and its been a pretty big crash course. But that's the great thing about the system, if you sit down and work with it, its full of neat features that make controlling the world with an 8 bit microcontroller quite easy to do.

As always questions and comments are most welcome, and thanks for reading, I hope you learned a lot

abhijit26831 month ago

In Led Matrix,how we will decide that we have to use Max7219 or shift register ?

ThijssjihT2 months ago

Thank you for this instructable. I'm just beginning with digital electronics, so I found this subject difficult to understand, but you made it very easy.

npitz3 months ago

would you share the microcontroller circuit board layout??

mobilohm7 months ago

Hello I'd like to know if you'll provide the code anytime...

with regard to LCD, you can use F. Malpertida's LCD library. for a tested design.. check here:

https://arduinodiy.wordpress.com/2014/01/12/two-wi...

maxatan8 months ago

Great tuto !

Thanks a lot for this insructables

pradipkhare2 years ago
Hi Osgeld,
Thanks for explaining it nicely and with full of illustrations and code. Appreciate the same.
Do you have something similar on using LCD (16x2) instead?

something like this: ? a two wire interface for LCD with 74xx164

https://arduinodiy.wordpress.com/2014/01/12/two-wire-interface-for-lcd/

diy_bloke11 months ago

great. I just quickly needed to test if a specific HC164 was still working and this did perfectly. Now I know the problem is in another circuit, not the 164.
One question though... you refer one of the LED's to pin 9... but that is connected with Vcc, so I guess it is pin 10-13. worked for me

schel1 year ago

Awesome Info delivery Osgeld! Do you know if small servos could be used with these magic little shifters? I see very little v / A can go through these hence all the LED examples, would love to get more outs for stepper motors too...whaddaya think? would these work?

mrthlinh1 year ago

This is an amazing instruction. Thanks a lot

Rollie582 years ago
Hello osgeld,
This was very helpful. I am designing a programmable musical water fountain and considering using a shift register to control MOSFETS, which will control solenoid valves. Do I understand correctly that the shift register will scroll through and trigger my MOSFETS continuously until I reset? Probably not a good idea for the valves.
Also, why do you recommend 74HC595 for an 8*8 display? I am not seeing the reason when reading the data sheets.
I am a noob, BTW.
It only scrolls on a clock pulse, so you just have to stop talking to it and it freezes in that position.
mr.future112 years ago
is it possible to make screening message display in 8*8 matix dipalay using arduino and this shift register
osgeld (author)  mr.future112 years ago
it is but you really dont want to, use a 74hc595
kris_ge2 years ago
Hi,

This is really a great webiste. I just got it from a friend and already it helped me out with something I was looking for for a very long time -> this tutorial on led matrices controlled by shift registers. Can somebody help me with mapping it to a 16x16 led array. I have one panel here with 16x16 LEDs, controlled by 32x M74HC4094 shift registers. WOW is almost the same only that in my case each LED is connected to a shift registers' output.
WVvan3 years ago
Thank you for creating this Instructable. Made it most clear.
yapadqoi3 years ago
Clear!
Thx.
Henry_Best3 years ago
"some other models are parallel in serial out, they do the same thing but as inputs to the arduino". What part numbers are these, as I can't find an 8 bit PISO shift register on the 74XX parts list?
most 74 logic series I.C. have a complementary part that are 1 or 2 digits different, take a look at the 165 and 166.
Those don't do what I want, but never mind as I've sorted the problem. I need to input information from 15 different switches to the arduino, but I don't have that many pins spare (some are in use as outputs). I've used 4 * 73LS30 (8 input NAND gates) to give a binary 4 bit output, so they will only use 4 pins on the arduino. Not as good as 1 pin (serial) but better than 15 pins!
claymantoo3 years ago
Very cool tutorial!!!
I had a problem figuring out where to plug in the clock (8)
and pin 9 (V+) on the 74HC164. I finally got it and grounded pin 9.
I was wondering why when I touched pin 9, the leds would light up.
Then realized I was acting as a sort of ground then it hit me. LOL
My next tutorial will be the 7 segment display.

Also I was wondering how I can have the 4x4 matrix flash letters.
Could you give me some insight on that?
Nasmi3 years ago
How can I open the file .tmp in arduino IDE ? it seems doesnt work.
thank you :)
osgeld (author)  Nasmi3 years ago
click on the links above it will open in your browser, just copy and paste, or rename the tmp file to pde (have no idea why its doing that)
Nasmi osgeld3 years ago
Okay .. i'll try .. Thanks !
ahinkle093 years ago
This is an excellent instructible! This is by far the best beginners guide to shift registers i've come accross. Thank you so much for putting this out there.
PeckLauros3 years ago
Nice instructables.
Eax53 years ago
I hope you still answer questions for this instructable. I have finished constructing the 4x4 matrix. Everything seams to work fine, but I am having trouble lighting up the LEDs.

I can easily address an individual LED to light up, but when I do I get surroundings LEDs to turn on as well ( much dimmer then the addressed LED)

I have attacked a picture to show you what is going on. I am trying to just light up and LED that is in position (1,1) but as the same time LED (4,4) is dimly lit.

here is the piece of code that I am using.
shiftOut(data, clock, MSBFIRST, B10000001);
delay(1);

Any guess as to why?
IMG_20110930_143010.jpg
Eax53 years ago
Hello Wanted to say thank you for a great tutorial, I am about to finish building the 4x4 Matrix and will let you know how it goes.
Russ12343 years ago

Great tutorial.  Thanks for making it, it's real helpful!
syntar694 years ago
This is a fantastic guide!

I've been looking for something written like this for a while.
I now have a fully working 4x4 led matrix, that I've built myself, and got to show the patterns I want.

This is all thanks to you.


Cheers,

Mikey C
Super rad tutorial dood!
TheBurf4 years ago
Great instructable, clear, easy to follow, helped alot
Tamerz4 years ago
It has been so long since I have done any electronics. This was very helpful, much better than the one output per segment I was using!
MCUman4 years ago
It's a great way to add an alphanumeric LCD to a low pin count MCU. Instead of 14 pins, it drops to 4.
matt byrne5 years ago
Great write up, very useful.
n3r05 years ago
 Great instructable! You gave the best explanation of shift registers that I have heard so far.
kitecraft5 years ago
Fantastic instructable!  Thank you :)
I made this with your help.
http://www.youtube.com/watch?v=3UNbvYED0bI
osgeld (author)  kitecraft5 years ago
Pretty cool!

I have 4 or 5 of these chips laying around, and just for giggles I wired up a old 4 section 7 segment led display from an alarm clock
Bongmaster5 years ago
kool ible :)
i got a bunch of shift regs to put to use :P