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.
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:
- 1x Arduino Uno
- 1x breadboard 830 point
- 28x jumper wires
- 1x 8-bit shift register 74HC595N
- 1x 10k ohm potentiometer
- 8x LEDs 3mm
- 6x 220 ohm resistors
- 2x 100 ohm resistors
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.
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.
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).
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:
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:
- constants and globals
- initialization
- 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:
The video cannot be shown at the moment. Please try again later.
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.