CIRC
05

.:8 More LEDs:.
.:74HC595 Shift Register:.

16 pin dip chip

(ARDX) .:Arduino Experimentation Kit:. (ARDX)

What We're Doing

Time to start playing with chips, or integrated circuits (ICs) as they like to be called. The external packaging of a chip can be very deceptive. For example, the chip on the Arduino board (a microcontroller) and the one we will use in this circuit (a shift register) look very similar but are in fact rather different. The price of the ATMega chip on the Arduino board is a few dollars while the 74HC595 is a couple dozen cents. It's a good introductory chip, and once you're comfortable playing around with it and its datasheet (available online http://ardx.org/74HC595) the world of chips will be your oyster. The shift register (also called a serial to parallel converter), will give you an additional 8 outputs (to control LEDs and the like) using only three Arduino pins. They can also be linked together to give you a nearly unlimited number of outputs using the same three pins. To use it you "clock in" the data and then lock it in (latch it). To do this you set the data pin to either HIGH or LOW, pulse the clock, then set the data pin again and pulse the clock repeating until you have shifted out 8 bits of data. Then you pulse the latch and the 8 bits are transferred to the shift registers pins. It sounds complicated but is really simple once you get the hang of it.

(for a more in depth look at how a shift register works visit: http://ardx.org/SHIF)

The Circuit

The Parts

circuit 5 breadboard sheet 3d view CIRC-05
Breadboard Sheet
x1
2 pin header 2 Pin Header
x4
74HC595 dip IC Shift Register
74HC595
x1
wire Wire
10mm LED Red LED
x8
resistor 560 Ohm Resistor
Green-Blue-Black-Black
x8

Schematic

Resources

.:download:.

Breadboard layout sheet
http://ardx.org/BBLS05

Fritzing diagram
https://wcrsyyc.github.io/ardx/fritzing/CIRC05.fzz

.:view:.

assembly video
http://ardx.org/VIDE05

Code (no need to type everything in just)

Download the Code from ( http://ardx.org/CODE05 )
(and then copy the text and paste it into an empty Arduino Sketch)

/*     ---------------------------------------------------------
 *     |  Arduino Experimentation Kit Example Code             |
 *     |  CIRC-05 .: 8 More LEDs :. (74HC595 Shift Register)   |
 *     ---------------------------------------------------------
 *
 * We have already controlled 8 LEDs however this does it in a slightly
 * different manner. Rather than using 8 pins we will use just three
 * and an additional chip.
 *
 *
 */


//Pin Definitions
//The 74HC595 uses a serial communication
//link which has three pins
int data = 2;
int clock = 3;
int latch = 4;

//Used for single LED manipulation
int ledState = 0;
const int ON = HIGH;
const int OFF = LOW;


/*
 * setup() - this function runs once when you turn your Arduino on
 * We set the three control pins to outputs
 */
void setup()
{
  pinMode(data, OUTPUT);
  pinMode(clock, OUTPUT);
  pinMode(latch, OUTPUT);
}

/*
 * loop() - this function will start after setup finishes and then repeat
 * we set which LEDs we want on then call a routine which sends the states to the 74HC595
 */
void loop()                     // run over and over again
{
  int delayTime = 100; //the number of milliseconds to delay between LED updates
  for(int i = 0; i < 256; i++){
    updateLEDs(i);
    delay(delayTime);
  }
}


/*
 * updateLEDs() - sends the LED states set in ledStates to the 74HC595
 * sequence
 */
void updateLEDs(int value)
{
  digitalWrite(latch, LOW);     //Pulls the chips latch low
  shiftOut(data, clock, MSBFIRST, value); //Shifts out the 8 bits to the shift register
  digitalWrite(latch, HIGH);   //Pulls the latch high displaying the data
}

/*
 * updateLEDsLong() - sends the LED states set in ledStates to the 74HC595
 * sequence. Same as updateLEDs except the shifting out is done in software
 * so you can see what is happening.
 */
void updateLEDsLong(int value)
{
  digitalWrite(latch, LOW);      //Pulls the chips latch low
  for(int i = 0; i < 8; i++){    //Will repeat 8 times (once for each bit)
	  int bit = value & B10000000; //We use a "bitmask" to select only the eighth
	                               //bit in our number (the one we are addressing this time through
	  value = value << 1;          //we move our number up one bit value so next time bit 7 will be
	                               //bit 8 and we will do our math on it
	  if(bit == 128){digitalWrite(data, HIGH);} //if bit 8 is set then set our data pin high
	  else{digitalWrite(data, LOW);}            //if bit 8 is unset then set the data pin low
	  digitalWrite(clock, HIGH);                //the next three lines pulse the clock pin
	  delay(1);
	  digitalWrite(clock, LOW);
  }
  digitalWrite(latch, HIGH);  //pulls the latch high shifting our data into being displayed
}


//These are used in the bitwise math that we use to change individual LEDs
//For more details http://en.wikipedia.org/wiki/Bitwise_operation
int bits[] = {B00000001, B00000010, B00000100, B00001000, B00010000, B00100000, B01000000, B10000000};
int masks[] = {B11111110, B11111101, B11111011, B11110111, B11101111, B11011111, B10111111, B01111111};
/*
 * changeLED(int led, int state) - changes an individual LED
 * LEDs are 0 to 7 and state is either 0 - OFF or 1 - ON
 */
void changeLED(int led, int state)
{
  ledState = ledState & masks[led];  //clears ledState of the bit we are addressing
  if(state == ON){ledState = ledState | bits[led];} //if the bit is on we will add it to ledState
  updateLEDs(ledState);              //send the new LED state to the shift register
}

Not Working? (3 things to try)

The Arduino's power LED goes out

This happened to us a couple of times, it happens when the chip is inserted backwards. If you fix it quickly nothing will break.

Not Quite Working

Sorry to sound like a broken record but it is probably something as simple as a crossed wire.

Frustration?

Shoot us an e-mail, this circuit is both simple and complex at the same time. We want to hear about problems you have so we can address them in future editions.
help@oomlout.com
info@robotgames.com

Making it Better?

Doing it the hard way:

An Arduino makes rather complex actions very easy, shifting out data is one of these cases. However one of the nice features of an Arduino is you can make things as easy or difficult as you like. Lets try an example of this. In your loop switch the line.
updateLEDs(i); -> updateLEDsLong(i);
Upload the program and notice nothing has changed. If you look at the code you can see how we are communicating with the chip one bit at a time. (for more details http://ardx.org/SPI ).

Controlling Individual LEDs:

Time to start controlling the LEDs using a method similar to what we did in CIRC02. As the eight LED states are stored in one byte (an 8 bit value) for details on how this works try http://ardx.org/BINA. An Arduino is very good at manipulating bits and there are an entire set of operators that help us out. Details on bitwise operations at ( http://ardx.org/BITW ).

Our implementation

Replace the loop() code with

  int delayTime = 100; //the number of milliseconds to delay
                       //between LED updates
  for(int i = 0; i < 8; i++){
    changeLED(i,ON);
    delay(delayTime);
  }
  for(int i = 0; i < 8; i++){
    changeLED(i,OFF);
    delay(delayTime);
  }

and upload to cause the lights to light up one after another and then off in a similar manner. Check the code and Wikipedia to see how it works, or shoot us an e-mail if you have questions.

More Animations:

Now things get more interesting. If you look back to the code from CIRC02 (8 LED Fun) you see we change the LEDs using digitalWrite(led, state), this is the same format as the routine we wrote changeLED(led, state). You can use the animations you wrote for CIRC02 by copying the code into this sketch and changing all the digitalWrite()'s to changeLED()'s. Powerful? Very. (you'll also need to change a few other things but follow the compile errors and it works itself out).