Using a shift register 74HC595N with Arduino

In this simple project I’m going to use an 8-bit shift register 74HC595N to control 8 LEDs using only few pins of my Arduino Uno.

Description

In this project I’m using an 8-bit shift register to animate a short strip made of 8 colored LEDs.

The animation is the simplest possible: only one LED at a time is ON and the one which is ON moves back and forward  bouncing from one side of the strip to the other.

controlling LEDs using a shift register and a potentiometer with Arduino, project in action

It is also possible to control the delay between two iterations of the animation (so making it faster or slower) setting the value of a potentiometer.

Obviously this simple project it’s just an excuse to demonstrate how to use an 8-bit shift register with Arduino, but it could easily be extended to something more complex as I’m probably going to show you in my next posts.

Components

This is what I used for this project:

You can also find all these components bundled in one of the LEDs kits available in our online shop.

8-bit Shift Register 74HC595N

A shift register is a chip you can use to control many outputs (8 here) at the same time while only using a few pins (3 here) of your Arduino.

8-bit shift register 74HC595

It is also possible to link multiple shift registers together in order to extend the number of outputs you can control, but this will be explained in another post.

If you want to check the details of the shift register used for this tutorial, you can download the datasheet from our website.

Wiring

Wiring may seem quite complex looking at the following picture, but things are not that bad when you break them down into logic blocks.

Using a shift register 74HC595N with Arduino, wiring

Having a closer look at the following scheme you will notice that this project is based on 3 main blocks: the shift register (left) the LEDs strip (center) and the potentiometer (right).

Using a shift register 74HC595N with Arduino - wiring scheme

The potentiometer is a very simple object, so let’s concentrate on the two other blocks.

The strip of LEDs is made of 8 LEDs, each of them is connected to an output pin of the shift register which basically controls the LEDs state.

To better understand the wiring of the shift register it’s probably better having a look at the pinout scheme:

8-bit shift register 74HC595N pinout

Pins marked as Q0-Q7 (15 and 1-7) are the output pins and are the ones connected to the LEDs.

Pin16 is connected to 5V, whereas pins 8, 10 and 13 are connected to ground.

Finally pins 14, 12 and 11 are data, latch and clock pins and are the ones used by Arduino to pass data to the shift register.

Sketch Code

For this tutorial I decided to split the sketch in 3 blocks of code:

  1. constants and globals
  2. initialization
  3. main loop

That’s just for clarity, so if you want to use this code in your project you’ll need to copy and paste the three blocks in a single file or you can download it from our website.

In the first block there’s all the code used to declare and initialize global and constant data.

// == CONSTANTS ==
// pin connected to ST_CP of 74HC595
const byte PIN_LATCH = 11;
// pin connected to SH_CP of 74HC595
const byte PIN_CLOCK = 12;
// pin connected to DS of 74HC595
const byte PIN_DATA = 8;

// -- DELAY RANGE --
const int MIN_DELAY = 50;
const int MAX_DELAY = 500;

// == GLOBAL DATA ==
byte val = 1;
byte dir_forward = 1;

The first three costants are the Arduino pins used for the shift register, than 2 more constants to limit the time delay range and finally two global variables that will be updated in the main loop:

  • val: the value passed to the shift register, which represents the LEDs configuration
  • dir_forward: a flag used to keep track of the direction of the LEDs animation.

It’s important to imagine val not as a single numeric value, but as 8 different values (8 bits) packed in a single variable (1 byte), so basically val is something like XXXXXXXX where each X can be a 0 or a 1 and that represents our LEDs configuration.

The setup function is pretty simple, all it does is initializing the pins and writing 0 to the shift register so to turn all the LEDs off (LEDs configuration is 00000000).

void setup() 
{
  //set pins to output so you can control the shift register
  pinMode(PIN_LATCH, OUTPUT);
  pinMode(PIN_CLOCK, OUTPUT);
  pinMode(PIN_DATA, OUTPUT);

  // the LEDs don't change while you're sending in bits
  digitalWrite(PIN_LATCH, LOW);
  // shift out the bits
  shiftOut(PIN_DATA, PIN_CLOCK, MSBFIRST, 0);
  //take the latch pin high so the LEDs will light up
  digitalWrite(PIN_LATCH, HIGH);
}

When sending a value to the shift register with the function shiftOut the latch pin needs to be set to LOW before the writing and then to HIGH after it.

At this point you should have realized how useful a shift register can be! Basically it allows us to replace 8 calls to digitalWrite like:

digitalWrite(PIN_LED1, HIGH);
digitalWrite(PIN_LED2, LOW);
digitalWrite(PIN_LED3, LOW);
...
digitalWrite(PIN_LED8, LOW);

with a single call to shiftOut.

The main loop is where the animation happens in few easy steps.

At first the potentiometer’s value is read and converted to a value in the delay range [MIN_DELAY, MAX_DELAY] using the function map. That value will be used to decide the delay before the next execution of the main loop.

Then the current LEDs configuration is sent to the shift register using the function shiftOut and finally the next LEDs configuration is computed.

void loop() 
{
    // -- read the value from the potentiometer and convert it to delay time -- 
    int pot_val = analogRead(A5);
    int delay_time = map(pot_val, 0, 1023, MIN_DELAY, MAX_DELAY);    

    // take the PIN_LATCH low so LEDs don't change while you're sending in bits
    digitalWrite(PIN_LATCH, LOW);

    // send the bits
    shiftOut(PIN_DATA, PIN_CLOCK, MSBFIRST, val);

    // -- set next LED on --
    if(dir_forward)
    {
      // val = val * 2 OR move 1 bit left
      val <<= 1;

      // 128 is 1000000, reached last LED -> revert the sequence
      if(128 == val)
        dir_forward = 0;
    }
    else
    {
      // val = val / 2 OR move 1 bit right
      val >>= 1;

      // back to the first LED -> revert the sequence
      if(1 == val)
        dir_forward = 1;
    }

    // take the latch pin high so the LEDs will light up
    digitalWrite(PIN_LATCH, HIGH);

    // pause before next cycles
    delay(delay_time);
}

Computing the next LEDs configuration is pretty straightforward: basically it’s a simple shift of the only 1 bit in val. The direction (left or right) of the shift operation is defined by the value of the flag dir_forward.

What happens to val when using a shift operator is something like this:

// initial value
byte val = 1;   // val = 00000001

// going forward
val <<= 1;      // val = 00000010
val <<= 1;      // val = 00000100
...             // 4 more times
val <<= 1;      // val = 10000000

//going backward
val >>= 1;      // val = 01000000
val >>= 1;      // val = 00100000
...             // 4 more times
val >>= 1;      // val = 00000001

Obviously using the same shift operator 7 times in a row makes the 1 (the LED which is ON) move from one side to the opposite and that’s how the animation effect is achieved.

Project in action

Finally a short video to show you the project in action:


Download YouTube Video | Convert YouTube to MP3 | Replay Media Catcher

I hope you enjoyed this tutorial and that everything was clear, but if you have any question don’t hesitate to leave a comment and I’ll be happy to answer.

Leave a Reply

Your email address will not be published. Required fields are marked *


− 6 = 1

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>