Monday, August 9, 2010

Shift Registers








Shift Registers (SN74595 Serial to Parallel)


Shift Registers simplify the wiring to portions of circuits that require multiple General Purpose Input/Output lines.  For example, if you wanted to light up 8 LEDs and be able to control each one individually, then you would need 8 GP I/O lines from your microcontroller to do it.  But if you used a shift register then you would  only require 2 or 3 GP I/O lines to operate those 8 LED outputs.

Daisy-Chaining
You can gain even more GP I/O lines with the shift register's built-in daisy-chaining features.  With daisy-chaining you can chain multiple shift register ICs together together, gaining 8 more outputs for each IC and still only need the initial 3 GP I/O pins.  The code becomes a bit more complex at this point as now you will need to send a byte for the second chip as well and a third byte for the third chip and so on.  If you want to change the value on the 4th shift register then you must still send 4 bytes even if the first three bytes do not change value.  If you can meet this challenge then you will benefit from the extra GP I/O pins.

I have seen two common types of shift registers, NON-LATCHED, and LATCHED. I have worked mostly with LATCHED shift registers.  At one point before I added an LCD display to my Super Car project, I used an LED bar graph to display status and remaining battery power.

Non-Latched
Non-Latched serial to parallel shift registers will "shift" in the data AS it is being sent.  This means that if you wanted to light up a LED at the 5th position of an 8 LED bar graph and you could slow the process down, you would see the light appear to "move" gradually from the 1st position to it's intended destination at the 5th position as that byte gets shifted in.

Latched
Latched Shift-Registers are like their Non-Latched counterparts, in that they simplify wiring and provide more ouputs.  However, the output will not occur until the Shift-Register’s “latch pin” (also known as a register pin) is set HIGH again.  This makes for more predictable response but requires 3 GP I/O pins where a non-latched shift register only requires 2.  

Operation of a LATCHED shift register:
The LATCHED shift register works by setting it's latch LOW.  During the time that the latch is low, a binary number can be sent to the shift register.  When the latch is set HIGH, the stored binary number controls the HIGHs and LOWs of the Shift-Register’s output terminals.

So, that was the technical explanation but it is even more fun to think of ways in which you could use a shift register in your projects.  Below I provide some ideas that I have come up with for using Shift-Registers.  Below the examples I have included sample code that could be used to measure battery voltage and display it on an LED bar graph using a shift register.



Examples:   
Binary counter - For a simple example, I programmed an Arduino with a "for loop" that would pass the numbers 0-255 to the shift register in a binary form.  The shift register lit up the LED bar graph and visually displayed the progression of the binary count.  Here is another example for specific lights.  <<YOUTUBE VIDEO LINK is below!! >>



LED bar graph battery meter - 0000000 could be empty and 00000011 could be very low and 00001111 could be half, 00111111 could be 3/4 power and 11111111 could be full.  You can send the proper binary number based on a reading from an analog pin and the arduino “map” command.  Be careful, the Arduino can handle the 1.5v and even 3v battery voltages but is only designed to handle up to 5v.  << Code to drive an LED bar graph is available below!! >>


LED Status Panel - Or maybe you would like the bar graph to light up different LEDs based on conditions in your program such as a "ready to receive data" condition or an "error" condition.  So, you send a binary number to the Shift-Register and it will output that value as ONs and OFFs.  For example, if I wanted all 8 lights of the LED Bar Graph to light up, you would send 1111111 (decimal 255) to the Shift-Register.  If you wanted only the lights on the left and right side as well as the two lights in the middle to light up, you would send 10011001 (decimal 153.)  And if you wanted the LED Bar Graph to turn off all lights then you would send 00000000 (decimal 0.)  Based on conditions you could light up certain lights on the LED Bar Graph.  I used such a design in an early version of Super Car in order to visually see the control signals coming from the Visual Basic .NET program that I was using to send signals to the Arduino.

REFERENCES:
http://www.instructables.com/id/The-74HC164-Shift-Register-and-your-Arduino/
http://www.tekcrack.com/arduino-purdy-lcd-74hc595n-shift-register.html
http://www.ecs.umass.edu/ece/m5/tutorials/parallel_serial_shift_register.html
http://www.circuitspecialists.com/prod.itml/icOid/3058
http://www.protostack.com/forum/blog.php?u=2&b=35&c=1 - Daisy Chaining
http://www.sqlskills.com/blogs/paulselec/post/Arduino-figuring-out-shift-registers.aspx



http://www.youtube.com/watch?v=s4pxpPeZJlE



Code:(LED Bar Graph Driver)

//*************************************************************** // Name : LED Bar Graph Driver // Author : Nickolas Andersen // Date : 08/08/2010 // Version : 1.0 // Notes : Uses a potentiometer for input to drive what the // : LED bar graph should display //**************************************************************** int latchPin = 11; //Pin connected to ST_CP of 74HC595 RCLK pin 12 int clockPin = 10; //Pin connected to SH_CP of 74HC595 SRCLK pin 11 int dataPin = 13; //Pin connected to DS of 74HC595 SER pin 14 int potPin = 5 ; int RAWpotval = 0 ; int MAPpotval = 0 ; byte LEDpotval = B00000000 ; void setup() { pinMode(latchPin, OUTPUT); pinMode(clockPin, OUTPUT); pinMode(dataPin, OUTPUT); Serial.begin(9600) ; } void loop() { FindPotVal() ; Serial.print("RAW, MAP, LED potval: ") ; Serial.print(RAWpotval); Serial.print(", "); Serial.print(MAPpotval); Serial.print(", "); Serial.println(LEDpotval, DEC); digitalWrite(latchPin, LOW); shiftOut(dataPin, clockPin, MSBFIRST, LEDpotval); digitalWrite(latchPin, HIGH); delay(1); } void FindPotVal () { RAWpotval = analogRead(potPin); MAPpotval = map(RAWpotval, 0, 1023, 0, 255); if (MAPpotval >= 0 && MAPpotval < 32 ) { LEDpotval = B00000000 ; return ; } if (MAPpotval >= 32 && MAPpotval < 64 ) { LEDpotval = B00000001 ; return ; } if (MAPpotval >= 64 && MAPpotval < 96 ) { LEDpotval = B00000011 ; return ; } if (MAPpotval >= 96 && MAPpotval < 128 ) { LEDpotval = B00000111 ; return ; } if (MAPpotval >= 128 && MAPpotval < 160 ) { LEDpotval = B00001111 ; return ; } if (MAPpotval >= 160 && MAPpotval < 192 ) { LEDpotval = B00011111 ; return ; } if (MAPpotval >= 192 && MAPpotval < 224 ) { LEDpotval = B00111111 ; return ; } if (MAPpotval >= 224 && MAPpotval < 255 ) { LEDpotval = B01111111 ; return ; } if (MAPpotval == 255 ) { LEDpotval = B11111111 ; return ; } }

No comments:

Post a Comment

Keep it clean. :)