Arduino 16 LEDs Using Two 74HC595 Shift Registers (unlimited Pins)

79,810

60

37

Introduction: Arduino 16 LEDs Using Two 74HC595 Shift Registers (unlimited Pins)

This is my first instructable, hope you will like it. I have been playing around with LEDs for a while and I realized that I am pretty much limited with Arduino pins and can not make huge projects which requires a lot of pins. This is small project with main focus to drive LEDs by using Arduino pins as less as possible and it demonstrates how to add infinite number of pins. In this particular project the 16 LEDs are driven with just only 3 Arduino pins. The key element is shift register. Each 74HC595 shift register can drive up to 8 LEDs and by daisy chaining registers it is possible to extend Arduino 3 pins to infinite number (for great number of registers, there could be problem with clock which is required for shift registers).

Step 1: Components

- Arduino UNO (x1)

- 74HC595 shift register (x2)

- LEDs (x16)

- 220omh resistors (x16)

- A lot of wires

- Two breadborads (one with 400 pins and other with 830)

- Potentiometer, to control the brightness (optional)

Step 2: Circuit

Make the circuit (see above) and connect the first shift register as following:

- GND (pin 8) to ground

- Vcc (pin 16) to 5V

- OE (pin 13) to ground

- MR (pin 10) to 5V

- DS (pin 14) to Arduino pin 11

- SH_CP (pin 11) to Arduino pin 12

- ST_CP (pin 12) to Arduino pin 8

Connect the second shift register exactly the same, but connect the DS (pin 14) to first register pin 9. After that connect pins: 1, 2, 3, 4, 5, 6, 7 and15 from both registers to LEDs. This connection makes all the pins always active and addressable, however when the Arduino is powered up some of the LEDs may be turned on. Solution for this is to connect MR (pin 10) and OE (pin 13) to Arduino directly, but it this way you have to sacrifice 2 Aurduino pins.

To add more shift registers connect them like the second register. Always connect MR and OE pins directly to Arduino and DS pin to previous register.

If you want to regulate the brightness of LEDs then connect potentiometer as shown in picture above to control resistance for all LEDs. However it is optional and you can get along without it.

Step 3: The Code

The existing codes are designed to limited number of shift registers and there is no universal function/method to do it. As a software developer it is unacceptable for me and I am used to make everything as dynamic as possible with no limitations. I redesigned the existing code samples to allow you to use unlimited number of shift registers. See code below:

int numOfRegisters = 2;
byte* registerState;

void setup() {
//Initialize array

registerState = new byte[numOfRegisters];

for (size_t i = 0; i < numOfRegisters; i++) {

registerState[i] = 0;

}

//... setup

}

void regWrite(int pin, bool state) {
//Determines register int reg = pin / 8;

//Determines pin for actual register

int actualPin = pin - (8 * reg);

//Begin session

digitalWrite(latchPin, LOW);

for (int i = 0; i < numOfRegisters; i++) {

//Get actual states for register

byte* states = ®isterState[i];

//Update state

if (i == reg) {

bitWrite(*states, actualPin, state);

}

//Write

shiftOut(dataPin, clockPin, MSBFIRST, *states);

}

//End session

digitalWrite(latchPin, HIGH);

}

Step 4: The Final Code

I posted the full source code on github, because here it would be unreadable:

https://github.com/jr2002008/Arduino-74HC595-shift-registers/blob/master/ArduinoLEDsWithShiftRegisters/ArduinoLEDsWithShiftRegisters.ino

In the final code I added several effects for those 16 LEDs. The effects are demonstrated in the video above. If you want to add more LEDs, connect more shit registers as described previously and change the value of numOfRegisters in the code (Also adjust logic for effects).

You can also use this code not for just LEDs only, if you simply want more pins for your Arduino use the regWrite(int pin, bool state) function to write state for any pin and there is no limit how much shift registers you are using, just change the value of numOfRegisters and every thing else is automated.

7 People Made This Project!

Recommendations

  • Organization Challenge

    Organization Challenge
  • Make it Glow Contest

    Make it Glow Contest
  • Game Design: Student Design Challenge

    Game Design: Student Design Challenge

37 Comments

0
Patrick PHEBUS
Patrick PHEBUS

2 months ago

Bonjour,
Je débute en Arduino. Je reprends votre programme, mais ça ne fonctionne que pour un seul registre (8 leds). NumOfRegisters ne change rien. J’ai 4 registres avec 32 leds, comment faire ?
Merci beaucoup

0
emulov
emulov

3 years ago

Thank you for this example! The code is very clean and it is so easy to expand the number of shift registers. In my project, I just need the ability to turn on or off a specific LED. So in the loop I just need for instance:

void loop() {
regWrite(2, HIGH);
regWrite(13, LOW);
}

This works without any problems. I just noticed that the pins connected to the second shift register are numbered 0 - 7 and the pins on the first shift register are numbered 8 - 15.

Is there a way to change the code, so that the pins on the first shift register are numbered 0 - 7 (or maybe 1 - 8) and on the second 8 - 15 (or 9 - 16). This way, by adding more shift registers, the numbering would just continue and there would be no need to change the code for the already assigned pins (in the loop).

Again thank you very much for you effort!
Isak

0
dojoklo
dojoklo

Reply 1 year ago

I've run into the same issue with the pin numbers. I added a third register, so that I could use 20 (or up to 24) lights. The pins on the 3rd register become 0-7, and the pins on the 1st register are now 16-23. So I just have to connect the LEDs starting with the last shift register in the chain. It is a little awkward to think through, and you likely couldn't add more registers and lights to a finished project, since your 0 light (which you would want to be the first in the row to illuminate) would then change.

0
KevinH431
KevinH431

Reply 3 years ago

hi,

can you share the code you used for this?

many thanks

kevin

0
dojoklo
dojoklo

Question 1 year ago

I'm trying to modify some of the patterns to come up with my own. I've run into trouble with this one. I have arranged my lights in a circle, and I would like for the LED chase to simultaneously run across the top half of the circle and the bottom half. So basically light 0 and 16 blink together, then 1 and 15, then 2 and 14, etc. Then when they reach 7 and 8, it reverses direction and chases back to the start.

With this code, the bottom row of lights 16 to 8 chase properly, but simultaneously, only one light in the top row of 0 to 7 will illuminate. First light 0 illuminates as the bottom row chases, then light 1 illuminates as the bottom chases again, then light 2 illuminates as the bottom row chases, etc. - following the current, advancing variable value.

void effectA(int speed){
for (int i = 0; i < 8; i++)
for (int k = 16; k > 7; k--){

regWrite(i, HIGH);
regWrite(k, HIGH);
delay(400);

regWrite(i, LOW);
regWrite(k, LOW);
delay(400);
}

for (int i = 7; i >= 0; i--)
for (int k = 8; k < 16; k++){

regWrite(i, HIGH);
regWrite(k, HIGH);
delay(400);
regWrite(i, LOW);
regWrite(k, LOW);
delay(400);
}

LEDcircleChaser-02.jpg
0
rwl7532
rwl7532

3 years ago

I soldered up the project on a prototype PCB. I had to change the MSBFIRST to LSBFIRST to get it to work as intended.

IMG_20191008_095538956_2.jpgIMG_20191008_095728754_2.jpg
0
dojoklo
dojoklo

Reply 1 year ago

Why was this code change necessary? Is it because you used a prototype PCB instead of a breadboard, or it is for another reason?

What Ohm resistors did you use? When I run a simulation with 220 Ohm, it says too much power broke the shift registers (maybe when all the LEDs are on at once?) Also, why are there 2 additional resistors right next to each of the shift registers, are they necessary, and what are their connection points?

0
dojoklo
dojoklo

Reply 1 year ago

Aha! the MSBFIRST to LSBFIRST changes the directions that the LEDs "travel" in the line. Since I have mine in a circle that was going counterclockwise, this changed them to clockwise, as desired. This change might also be needed for the desired direction, if the LEDs are placed on the opposite side of the board as the shift registers.

0
rwl7532
rwl7532

Reply 1 year ago

Sounds like progress!

0
rwl7532
rwl7532

Reply 1 year ago

I can't answer on the code change since this was two years ago. Regarding what appears to be extra resistors, those are 0Ω "resistors" which provided stable solder points underneath to ground. Later I added a dedicated atmega328 and all the LEDs 0805 SMDs.

0
dojoklo
dojoklo

Reply 1 year ago

Thanks for the answers! I assume that the ATmega328 enables you to run the board, lights, and patterns as a stand-alone, without having to connect the Arduino every time? That is my goal!

0
ArifSae
ArifSae

6 years ago

I made my project with 16 RGB leds using shift register.

https://www.instructables.com/id/Sparrow-My-Assista...

220 Ohm in my opinion is a not good choice as you are going to blow your IC if you use all leds lit at same time (7ma approx X8 leds = 56ma, very close to maximum to IC limit) . I used 1k Ohms and now leds are only slight less brighter. I think tutorials should mention this point as new comers might blow ICs and get dishearted.

0
dojoklo
dojoklo

Reply 1 year ago

Would you recommend 1k Ohm resistors for regular single color LED lights (non-RGB lights), as used in the project above?

0
condoralan
condoralan

Question 2 years ago

Hi I have made this and being a novice with the Arduino I would like to know how to slow the program down ie slow the sequence of the led's as it goes to fast, thank you for a nice project.

0
LoS6
LoS6

2 years ago

I'm confused about the effectId statement in the code. Could you explain this??

0
pfeuh
pfeuh

3 years ago

Hello,

And idea concerning time consumption per bit?

0
jianyuyu
jianyuyu

4 years ago

this is a much helpful tutorial on addressing the shift reg independently. thank you so much.