9
Shift Registers

Parts You'll Need for This Chapter

  • Arduino Uno or Adafruit METRO 328
  • USB cable (Type A to B for Uno, Type A to Micro-B for METRO)
  • Half-size or full-size breadboard
  • Assorted jumper wires
  • 220Ω resistors (×8)
  • 5 mm red LEDs (×8)
  • 5 mm green LEDs (×4)
  • 5 mm yellow LEDs (×3)
  • Sharp GP2Y0A21YK0F IR distance sensor with JST cable
  • SN74HC595N shift register

As you plug away building exciting new projects with your Arduino, you might already be thinking: “What happens when I run out of pins?” Indeed, one of the most common uses for the Arduino platform is to put an enormous number of blinking LEDs on just about anything. Light up your room! Light up your computer! Light up your dog! Okay, maybe not that last one.

But there's a problem: What happens when you want to start blinking 50 LEDs (or controlling other digital outputs), but you've used up all of your I/O pins? That's where shift registers can come in handy. With shift registers, you can expand the I/O capabilities of your Arduino without having to pay a lot more for an expensive microcontroller with additional I/O pins. In this chapter, you'll learn how shift registers work, and you'll implement both the software and hardware necessary to interface your Arduino with shift registers for the purpose of expanding the digital output capabilities of your Arduino. Once you've completed the exercises in this chapter, you will be familiar with shift registers and will also be able to make more informed design decisions when developing a project with a large number of digital outputs.

Understanding Shift Registers

A shift register is a device that accepts a stream of serial bits and simultaneously outputs the values of those bits onto parallel I/O pins. Most often, shift registers are used for controlling large numbers of LEDs, such as the configurations found in seven-segment displays or LED matrices. Before you dive into using a shift register with your Arduino, consider the diagram in Figure 9-1, which shows the inputs and outputs to a serial-to-parallel shift register. Variations to this diagram throughout the chapter illustrate how different inputs affect the outputs.

Diagram depicting shift register input/output functions, in which the eight circles represent LEDs connected to the eight outputs of the shift register.

Figure 9-1: Shift register input/output diagram

The eight circles represent LEDs connected to the eight outputs of the shift register (through current-limiting resistors, of course). The three inputs are the serial communication lines that connect the shift register to the Arduino.

Sending Parallel and Serial Data

There are essentially two ways to send multiple bits of data. Recall that the Arduino, like all microcontrollers, is digital; it only understands 1s and 0s. So, if you want sufficient data to control eight LEDs digitally (each one on or off), you need to find a way to transmit a total of 8 bits of information. In previous chapters, you did this in parallel by using the digitalWrite() and analogWrite() commands to exert control over multiple I/O pins. For an example of parallel information transmission, suppose that you were to turn on eight LEDs with eight digital outputs; all the bits would be transmitted on independent I/O pins at the same time.

In Chapter 7, “USB Serial Communication,” you learned about serial transmission, which transmits 1 bit of data at a time. Shift registers allow you to easily convert between serial and parallel data transmission techniques. This chapter focuses on serial-to-parallel shift registers, sometimes called serial in, parallel out (SIPO) shift registers. With these handy devices, you can “clock in” multiple bytes of data serially, and output them from the shift register in parallel. You can also chain together shift registers, and thus control hundreds of digital outputs with just three Arduino I/O pins.

Working with the 74HC595 Shift Register

For this project, you'll be using the 74HC595 shift register. Take a look at the pin-out diagram from the datasheet shown in Figure 9-2.

Diagram of the shift register pin-out functions, depicting pins Q A through 11 representing the eight parallel outputs.

Figure 9-2: Shift register pin-out diagram

Credit: Courtesy of Texas Instruments Incorporated

Understanding the Shift Register pin Functions

Following is a breakdown of the shift register pin functions:

  • pins QA through QH represent the eight parallel outputs from the shift register (connected to the circles shown in Figure 9-1).
  • VCC will connect to 5V.
  • GND will connect to a shared ground with the Arduino.
  • The SER pin is represented by the DATA input in Figure 9-1. This is the pin where you will feed in eight sequential binary bits to set the values of the parallel outputs.
  • The SRCLK pin is represented by the CLOCK pin in Figure 9-1. Every time this pin goes high, the values in the register shift by 1 bit. It will be pulsed eight times to pull in all the data that you are sending on the data pin.
  • The RCLK pin is represented by the LATCH pin in Figure 9-1. Also known as the register clock pin, the latch pin is used to “commit” your recently shifted serial values to the parallel outputs all at once. This pin allows you to sequentially shift data into the chip and have all the values show up on the parallel outputs at the same time.

You will not be using the images or images pins in these examples, but you might want to use them for your project, so it's worth understanding what they do. images stands for “output enable.” The bar over the pin name indicates that it is active low. In other words, when the pin is held low, the output will be enabled. When it is held high, the output will be disabled. In these examples, this pin will be connected directly to ground, so that the parallel outputs are always enabled. You could alternatively connect this pin to an I/O pin of the Arduino to simultaneously turn all the LEDs on or off. The images pin is the serial clear pin. When pulled low, it empties the contents of the shift register. For your purposes in this chapter, you will tie it directly to 5V to prevent the shift register values from being cleared.

Understanding How the Shift Register Works

The shift register is a synchronous device; it only acts on the rising edge of the clock signal. Every time the clock signal transitions from low to high, all the values currently stored in the eight output registers are shifted over one position. (The last one is either discarded or output on the QH' pin if you are cascading registers.) Simultaneously, the value currently on the DATA input is shifted into the first position. When this is done eight times, the present values are shifted out and the new values are shifted into the register. The LATCH pin is set high at the end of this cycle to make the newly shifted values appear on the outputs. The flowchart shown in Figure 9-3 further illustrates this program flow. Suppose, for example, that you want to set every other LED to the ON state (QA, QC, QE, QG). Represented in binary, you would want the output of the parallel pins on the shift register to look like this: 10101010.

Now, follow the previously described steps for writing to the shift register. First, the LATCH pin is set low so that the current LED states are not changed while new values are shifted in. Then, the LED states are shifted into the registers in order on the CLOCK edge from the DATA line. After all the values have been shifted in, the LATCH pin is set high again, and the values are output from the shift register.

Illustration depicting the process of shifting serial data from the Arduino into a shift register.

Figure 9-3: Shifting a value into a shift register

Shifting Serial Data from the Arduino

Now that you understand what's happening behind the scenes, you can write the Arduino code to control the shift register. As with all your previous experiments, you can use a convenient function that's built in to the Arduino IDE to shift data into the register IC. The shiftOut() function lets you easily shift out 8 bits of data onto an arbitrary I/O pin. It accepts four parameters:

  • The data pin number
  • The clock pin number
  • The bit order
  • The value to shift out. If, for example, you want to shift out the alternating pattern described in the previous section, you can use the shiftOut() function as follows:
shiftOut(DATA, CLOCK, MSBFIRST, B10101010);

The DATA and CLOCK constants are set to the pin numbers for those lines. MSBFIRST indicates that the most significant bit will be sent first (the leftmost bit when looking at the binary number to send). You could alternatively send the data with the LSBFIRST setting, which would start by transmitting the bits from the right side of the binary data. The final parameter is the number to be sent. By putting a capital B before the number, you are telling the Arduino IDE to interpret the following numbers as a binary value rather than as a decimal integer.

Next, you will build a physical version of the system that you learned about in the previous sections. First, you need to get the shift register wired up to your Arduino:

  • The DATA pin will connect to pin 8.
  • The LATCH pin will connect to pin 9.
  • The CLOCK pin will connect to pin 10.

Don't forget to use current-limiting resistors with your LEDs. Reference the diagram shown in Figure 9-4 to set up the circuit.

Now, using your understanding of how shift registers work, and of the shiftOut() function, you can use the code in Listing 9-1 to write the alternating LED pattern to the attached LEDs.

Diagram of the eight-LED shift register circuit with an alternating LED pattern on the shift register.

Figure 9-4: Eight-LED shift register circuit diagram

Created with Fritzing

Because the shift register will latch the values, you need to send them only once in the setup; they will then stay at those values until you change them to something else. This program follows the same steps that were shown graphically in Figure 9-3. The LATCH pin is set low, the 8 bits of data are shifted in using the shiftOut() function, and then the LATCH pin is set high again so that the shifted values are output on the parallel output pins of the shift register IC.

Converting Between Binary and Decimal Formats

In Listing 9-1, the LED state information was written as a binary string of digits. This string helps you visualize which LEDs will be turned on and off. However, you can also write the pattern as a decimal value by converting between base2 (binary) and base10 (decimal) systems. Each bit in a binary number (starting from the rightmost, or least significant, bit) represents an increasing power of 2. Converting binary representations to decimal representations is very straightforward. Consider the binary number from earlier in the chapter, now displayed in Figure 9-5 with the appropriate decimal conversion steps.

Illustration depicting the result of the conversion of binary to decimal notation.

Figure 9-5: Binary to decimal conversion

The binary value of each bit represents an incrementing power of 2. In the number in this example, bits 7, 5, 3, and 1 are high. So, to find the decimal equivalent, you add 27, 25, 23, and 21. The resulting decimal value is 170. You can prove to yourself that this value is equivalent by substituting it into the code listed earlier. Replace the shiftOut() line with the following:

shiftOut(SER, CLK, MSBFIRST, 170);

You should see the same result as when you used the binary notation.

Controlling Light Animations with a Shift Register

In the previous example, you built a static display with a shift register. However, you'll probably want to display more dynamic information on your LEDs. In the next two examples, you will use a shift register to control a lighting effect and a physical bar graph.

Building a “Light Rider”

The light rider is a neat effect that makes it look like the LEDs are chasing each other back and forth. You will use the same circuit that you used previously. The shiftOut() function is very fast, and you can use it to update the shift register several thousand times per second. Because of this, you can quickly update the shift register outputs to make dynamic lighting animations. Here, you light up each LED in turn, “bouncing” the light back and forth between the leftmost and rightmost LEDs. Watch a demo video of this project at exploringarduino.com/content2/ch9 if you want to see what the finished project will look like before you build it.

You first want to figure out each animation state so that you can easily cycle through them. For each time step, the LED that is currently illuminated turns off, and the next light turns on. When the lights reach the end, the same thing happens in reverse. The timing diagram in Figure 9-6 shows how the lights will look for each time step and the decimal value required to turn that specific LED on.

Illustration depicting the sequential array pattern of light rider animation steps.

Figure 9-6: Light rider animation steps

Recalling what you learned earlier in the chapter, convert the binary values for each light step to decimal values that can easily be cycled through. Using a for loop, you can cycle through an array of each of these values and shift them out to the shift register one at a time. The code in Listing 9-2 does just that.

By adjusting the value within the delay function, you can change the speed of the animation. Try changing the values of the seq array to make different pattern sequences.

Responding to Inputs with an LED Bar Graph

Using the same circuit but adding an IR distance sensor, you can make a bar graph that responds to how close you get. To mix it up a bit more, try using multiple LED colors. The circuit diagram in Figure 9-7 shows the circuit modified with different-colored LEDs and an IR distance sensor.

Circuit diagram depicting a circuit modified with different-shaded LEDs and an infrared distance sensor.

Figure 9-7: Distance-responsive bar graph

Created with Fritzing

Using the knowledge you already have from working with analog sensors and the shift register, you should be able to make thresholds and set the LEDs accordingly based on the distance reading. Figure 9-8 shows the decimal values that correspond to each binary representation of LEDs.

As you discovered in Chapter 3, “Interfacing with Analog Sensors,” the range of usable values for the IR distance sensor is not the full 10-bit range. (I found that a maximum value of around 500 worked for me, but your setup will probably differ.) Your minimum might not be zero either. It's best to test the range of your sensor and fill in the appropriate values. You can place all the bar graph decimal representations in an array of nine values. By mapping the IR distance sensor (and constraining it) from 0 to 500 down to 0 to 8, you can quickly and easily assign distances to bar graph configurations. The code in Listing 9-3 shows this method in action.

Illustration depicting the decimal values that correspond to each binary representation of LEDs.

Figure 9-8: Bar graph decimal representations

Load this program on to your Arduino and move your hand back and forth in front of the distance sensor—you should see the bar graph respond by going up and down in parallel with your hand. If you find that the graph hovers too much at “all on” or “all off,” try adjusting the maxVal and minVal values to better fit the readings from your distance sensor. To test the values you are getting at various distances, you can initialize a serial connection in the setup() command and call Serial.println(distance); right after you perform the analogRead(DIST); step.

Summary

In this chapter, you learned the following:

  • How a shift register works
  • The differences between serial and parallel data transmission
  • The differences between decimal and binary data representations
  • How to create animations using a shift register
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset