ShiftRegister74HC595 Arduino Library
The ShiftRegister74HC595 Arduino Library simplifies shift registers usage. It allows you to set single pins of your shift register either high or low, just like normal Arduino pins. It thereby removes the overhead of shifting out bytes that were created with complicated bit-wise operations. Setting for instance the second pin of your shift register would simply look like sr.set(2, HIGH);
Getting Started
Download the library and install it.
Connect the shift register to your Microcontroller as shown in Figure 1.

Open up a new project in the Arduino IDE and import the library with the following code:
#include <ShiftRegister74HC595.h>
Create an instance of the ShiftRegister74HC595
class with:
int numberOfShiftRegisters = 1; // number of shift registers attached in series int serialDataPin = 0; // DS int clockPin = 1; // SHCP int latchPin = 2; // STCP ShiftRegister74HC595<numberOfShiftRegisters> sr(serialDataPin, clockPin, latchPin);
Note: When using the pins 0
and 1
, they cannot be used for the serial connection anymore. If you want to use statements like Serial.println
, you should connect the shift register to other pins, e.g. 2
, 3
, and 4
.
If you want to use multiple shift registers in series, connect them as shown in Figure 2 and increase the numberOfShiftRegisters
variable accordingly. To operate multiple shift registers in parallel, keep numberOfShiftRegisters = 1
and instantiate multiple ShiftRegister74HC595
objects with different pins.

Insert the normal setup
and loop
function.
Congratulations! Now you have additional output pins (Fig. 3 – series resistors are left out for clarify reasons). You can access them with a bunch of methods, some of which are explained below:
Set a specific pin of your shift register on high:
int pin = 0; sr.set(pin, HIGH);
Set all pins:
// either on high ... sr.setAllHigh(); // ... or low sr.setAllLow();
Sets all pins at once (pin 0 low, pin 1 high, …):
uint8_t pinValues[] = { B10101010 }; sr.setAll(pinValues);
Set multiple pins at once when using two shift registers in series:
uint8_t pinValues[] = { B00011000, B10101010 }; sr.setAll(pinValues);
You can also read the current state of a pin:
int pin = 0; uint8_t state = sr.get(pin); // 0 = LOW, 1 = HIGH
An example sketch can be found here.
Contribute
Since the initial release of the library in November 2014, five people have contributed to the library with pull requests on GitHub. If you miss features or have ideas for improvements please consider contributing them by forking the repository and opening a pull request. Be sure to test the changes thoroughly beforehand.
Sample Project
Below is a sample project I have implemented using the shift register library. If you want your shift register library project to be featured here feel free to email me.
Your library is excelent, work with 74hc164 only with two lines, data and clock and deleting latch.
Thanks, glad to hear that! The latch pin can be indeed set to be the clock pin, if the use-case does not suffer from having short glitches which will then occur while shifting new data into the register.
would have liked if you gave an example of how to read the binary number from an a pot and update it it real time on an 8 bit LED strip….That’s what I am trying with your library…I must say I love it…Not sure if that would be possible for you to put in the documentation. Basically I want in the end to display a thermocouple reading to a display
I am trying to compile downloaded code that seems to be using a non-template version of the library, e.g.
“ShiftRegister74HC595 shift(3, 13, 14, 15);”
Is the broken compile related to a change December 20, 2019?
Is there a way to get the backwards compatible API, or am I forced to modify the code to get it to compile?
If there is a non-backwards compatible change, then it would be nice to document it. Thanks for all your efforts making this library!
Hey Carl, you are right, the change made in this PR was not backwards compatible. The version should have been increased to 2.0.0 probably. In your example you are good by changing
ShiftRegister74HC595 shift(3, 13, 14, 15);
toShiftRegister74HC595<3> shift(13, 14, 15);
. I’m not sure if there is a way to change the code such that old versions will not break, however, I think the change is so small that people will be able to upgrade easily.Hey Denk,
I’m using the ti SN74HC595 in an arduino project, based on the datasheet pin 13(OE) is active low.
since the arduino takes some fraction of a millisecond for the arduino code to start the moment the
circuit is powered on, the 74hc595’s leds are HIGH until the arduino code starts to drive the OE HIGH
hence turning off the outputs.
Is there any clever wiring i could implement to keep the OE HIGH thus disabling the outputs long enough for the arduino to be on to drive the IC??
connecting the OE directly to vcc will do the trick but it wouldn’t make sense since i wouldn’t be able to enable it
every time i turn the circuit on, the leds immediately flashes on and off in a blink before
things starts going.
I only want to prevent this from happening.
Regards,
Chase
Hey Chase,
you might want to look into pull-down/pull-up resistors. Here is a link on that topic.
Let me know whether it helps. 🙂
Best, Timo
Can you give an code example for assigning pins to a 2nd 74hc595.
Sure, you might do something like that:
which will let you make calls like
srA.set(1, HIGH)
orsrB.set(1, HIGH)
, addressing two different shift register pins.Hi Timo, I am hoping using 4 x74HC595 daisy chained and an Arduino Nano for sequentail turn signals and have it working, the issue is i need to have an input on the nano activate the 74HC595’s to run the sequence
For example if I want to flash once it will compete 1 sequence or if I want it to flash 10x thats thats 10 complete sequences
Thanks
Hi,
I was using your library to make a scoreboard. If you push a button some leds on a stip will light up.
It work just fine but my led stip is made of a blue led a red and a green one but the blue leds are not working. Any idea what I should do ?
Looking for some help here. I have this setup with 2 shift registers i want to be able to start at 0 0 and count up and down using switches. Anything you can suggest to get me going on the right track?
Hi Timo ,
can i use this library also for the dm13A ???
Peter
First of all my compliments for the perfectly working library, which I’m presently using with 4 x TPIC6C595N in series.
I was asking myself if the library would work also with a mix of TPIC6C595N and 74HC595: Have you ever tasted such a configuration ?
There is any limitation in the number of shift register in series ?
Is it possible to define multiple instances of serial registers as, for instance:
Thanks for your kind comment. I have never tested the library with another shift register. If you happen to do it, it would be very nice if you could let me know how it went.
Secondly, there is no limitation on the number of shift registers you can operate in series other than the memory of the microcontroller.
You can use shift registers in series and in parallel at the same time. In fact I am working on a project right now where I use three shift registers in series and another stack of four shift registers in series and it works without any problems.
IF i have to use 3 74hc595 , if i need to use this function sr.setNoUpdate(0, HIGH);
what is the number of the pin 7th output of the 3rd 74595
sr.setNoUpdate(22, HIGH);
is it true or false ???
What you’re saying is correct. The indices just continue counting up. The first shift register is from 0 to 7, the second from 8 to 15, the third from 16 to 23, and so on.
thank you very much
Dear Timo
is there library for 74165 can do the opposite function of 74595?
Thanks to you, Timo, for the prompt answer !
Yes, your library works perfectly also with the TPIC6C595N, which is shift register with open drain outputs (https://www.ti.com/lit/ds/symlink/tpic6c595.pdf?HQS=TI-null-null-digikeymode-df-pf-null-wwe&ts=1593491135208)
Hi, thank you so much for this library. It works amazing with 18 of the 74HC595 daisy chained together. Very simple, lightweight, and effective.
I’m having difficulty using the OE pin and PWM though. When I have the duty set to 0 it all works as it should. As soon as I apply any other duty at all (say i use 26 or 10%), it activates all the of the pins at once. I can not seem to figure out why.
Do you know why using PWM would suddenly set all pins HIGH on all shift registers?
Hi.
For pin ZERO led turned ON then automatic turned OFF. For all other pin it works well.
Board-ESP32
The problem is most likely caused by the double pin-allocation of pin 0 and 1 when using the
Serial
output. To resolve the problem you can either stop usingSerial.begin(9600);
or place the shift register on any digital pin other thanD0
andD1
.I have updated the article accordingly.
Hi Timo
Thanks for this library.
Can you advise how the decimal points are accessed?
Hi and thanks! The library is agnostic to what you connect. If you work with a seven-segment display, you might just use pin 8 of the shift register for the decimal dot.
Thanks Timo
I’ll explore that suggestion
I build a test circuit for the 74HC595 and run the example code. I dont know if im using it right, but for every loop in loop function everything stops for 5-10s.
Hi Timo,
I’m a beginner on Arduino and I’m trying to control the light intensity of several LEDs according to the value of potentiometers (each potentiometer has an assigned LED).
I use a 74HC4051 for the potentiometers (it works very well).
I also tried the 74HC4051 for the LEDs but I always get a residual voltage that turns on the LEDs that shouldn’t be.
Can you tell me if it is possible to use a 74HC595 to do this (Actually i tried it but i didn’t manage to do it well) ?
Thank you
This vworks fine, thanks! I have four of them chained, and I can drive four 7 segment digits, but one question remains: when I press reset, or send a new code to the Arduino, it doesn’t start to run the routine of counting 1 to 9999 but gives me 8 in the last digit while the others work fine.
Hi Timo,
Thanks for sharing this library! It makes things so much quicker and easier. I was wondering, is it possible to use the sr.setAll(pinValues) to change just the second shift register in the series without affecting or needing to update the current state of the first shift register in the series or any shift registers after in the series? If it is not possible this way, is there another way you can suggest? I am trying to use shift registers in a series to individually control 4 separate 7 segment displays that are in pairs of 2 and each pair counts from 0 to 99. Thanks again for your efforts!
Hi Nick! I appreciate your friendly comment! 🙂 The library’s API doesn’t offer what you ask for, however, you can consider building your own helper function. It would, given a byte and the index of the shift register that you want to update, call the library’s
setNoUpdate
function eight times (once per bit). Afterwards a single call toupdateRegisters
would change the targeted shift register’s outputs. Hope that helps!Loving the library. It is saving me lots of work. Something strange is happening though.
I have 20 daisy-chained shift registers. They work as expected with sr.setAllHigh(), sr.setAllLow(), and looping through them in order – they all turn on.
It gets weird when I try to set them using an array. All on or all off works but when I leave Qa off (pin 15: B11111110) several of the daisy-chained registers also leave Qb (pin 1) off. And I have tried the opposite (B01111111) with similarly strange results. There seems to be a ‘shift’ happening somewhere down the line…Am I missing something?
Hey Cameron, thanks for your nice comment! 🙂 I think there is a misunderstanding about the API. The
setAll
function requires a byte array with one entry per pin. If you have 20 shift registers chained, you have to provide $8\times20$ values. Hope that helps! PS: Can you share a photo of 20 chained shift registers? Sounds cool!Thanks. Yes, I was only including examples of the byte arrays for each register. My array for updating the 20 registers has a length of 20.
I am building a relay controller – in the image you can just see the shift registers and an LED array I am using for testing: https://ibb.co/qDp7QLz
I think some of the problems I am seeing are somehow related to ground connections. Not that they are absent, but the shift registers really behave strangely when the ground route of the outputs (LEDs) are not relatively direct to the chip ground connections (i.e.: to the end of breadboard on 1 rail and across to the other side seems too long). I have never used the 74hc595 before – does this sound about right?
Thanks for this very useful library!
Is it possible to use two parallel (!) connected shift registers with a common data and a common latch pin for both, and only different clock pins for each of them?
Additionally I want to suggest the following:
Could you please also add setAllLowNoUpdate() and setAllHighNoUpdate(), so that I can i.e. prepare all registers to 0, then set all I want to 1, and then update the output?
Hi,
Just wanted to let you know that you library does work fine with ST2221C 16 bit LED drivers..
I have some LED sign panels that have 40 on each PCB (giving 40 columns of 16 LEDs for a total of 640 LEDs per panel)..
And there are 3 panels connected in series…
One small issue is that the library seems to use only 8 bit data types which mean I can only individually address up to 255 of the 640 LEDs using sr.set (or at least I can’t seem to address anything over 255).. Ideally I’d like to be able to address any of the 1920 LEDs…
Here is a video of the test code from your example:
https://vimeo.com/549518213
Fine work! Very useful.
Hello,
Keep in mind I am relatively new to programing so I might be wrong, but I think there is an inherent problem with the library.
By declaring pins as int (int serialDataPin, int clockPin, int latchPin) you assume that those pins can only be digital pins and not analogue pins (eg A0, A1 etc) assigned as digital pins.
Just letting people know in case they wonder why this code works for some pins (digital pins) while it does not work for some others (analogue pins used as digital).
Thanks
Hi, Timo. I have just started doing projects in ESP8266 NodeMCU board, as I was doing my project I started to run out of I/O pins in my microcontroller. When I was searching for a solution I came across many expensive solution as to use a I/O Expansion Board (PCF8574). When I discovered that 74HC595 shift registers can do the trick. I started to look at example codes to understand it. It was very touch for me to understand binary values and was searching for a easier way to address the I/O pins individually. That’s when I came across your blog. When I looked at your library example I started to burst out in happiness as this was exactly what I was searching for all these days. Man you really are a life saver. Keep up the good Work and Happy Electronics ⚡.
What a lovely comment to read on a Wednesday evening! Thank you so much for the genuine compliment and have fun with the library! 🙂
Hi, Timo. Your welcome 😁. I have used your library in all the ways that I would use a GPIO pin and it works well. I am trying to create a water level Indicator with my jsn sr04t water proof ultrasonic sensor to drive 5 leds to represent the level of water available in the tank by finding the distance from top of the tank to the level of water. I am facing a problem while using the Library in an else if condition statement. The pins remain high and does not change according to the measured distance. I genuinely don’t know if my code is wrong. Kindly please help me to resolve this issue.
My code is :
#include
#define echoPin 4// attach pin D2 of Esp8266 NodeMcu to pin Echo of HC-SR04
#define trigPin 5//attach pin D1 of Esp8266 NodeMcu to pin Trig of HC-SR04
// defines variables
long duration; // variable for the duration of sound wave travel
int d; // variable for the distance measurement
ShiftRegister74HC595 sr(3, 1, 10);
void setup() {
pinMode(trigPin, OUTPUT); // Sets the trigPin as an OUTPUT
pinMode(echoPin, INPUT); // Sets the echoPin as an INPUT
Serial.begin(9600); // // Serial Communication is starting with 9600 of baudrate speed
}
void loop() {
// Clears the trigPin condition
digitalWrite(trigPin, LOW);
delayMicroseconds(5);
// Sets the trigPin HIGH (ACTIVE) for 10 microseconds
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
// Reads the echoPin, returns the sound wave travel time in microseconds
duration = pulseIn(echoPin, HIGH);
// Calculating the distance
d = (duration * 0.034 / 2)+ 3; // Speed of sound wave divided by 2 (go and back)
// Displays the distance on the Serial Monitor
Serial.print(“Distance: “);
Serial.print(d);
Serial.println(” cm”);
delay(1000);
if (d200){
uint8_t pinValues[] = {B00011111};
sr.setAll(pinValues);
delay(1000);
}
else if(d=25){
uint8_t pinValues[] = {B00011110};
sr.setAll(pinValues);
delay(500);
}
else if(d=48){
uint8_t pinValues[] = {B00011100};
sr.setAll(pinValues);
delay(500);
}
else if(d=72){
uint8_t pinValues[] = {B00011000};
sr.setAll(pinValues);
delay(500);
}
else if(d=105){
uint8_t pinValues[] = {B00010000};
sr.setAll(pinValues);
delay(500);
}
}
Hi, Timo. When I was searching for many days a solution to drive 60 relays with 74HC595 to individually control speakers in different classes in a school. When I came across your blog ,there is no words to express my happiness this was exactly what I was searching for all these days. The library example was very simple to understand .Thank you very much and Keep up the good Work .
Greetings from Sri Lanka.
Hi Nagarajah, your message really made my day! Thanks for the kind words, it’s amazing to see one’s work have an impact on others. I’ll ping you, if I happen to be in Sri Lanka once! 🙂 Have a great day!
Any help will be highly appreciated
I’m using SN74HC595
the code:
ShiftRegister74HC595 sr(SR_DATA, SR_CLOCK, SR_LATCH);
loop
uint8_t _aa[] = {0xAA,0xAA};
uint8_t _55[] = {0x55,0x55};
sr.setAll(_aa);
digitalWrite(13, HIGH);
delay(2000);
sr.setAll(_55);
digitalWrite(13, LOW);
delay(2000);
the signal:
https://ibb.co/mThtGcw
the result:
https://www.youtube.com/watch?v=2VXcj2hXppw
Hi Timo. I made a modification to the src files so it can work with SPI hardware communication, perhaps that’s something you’d like to add?
Only thing I changed is:
* included SPI in header file,
#include
* changed arguments of constructor, because now it only needs a latch Pin (CS pin in SPI terms)
ShiftRegister74HC595(const uint8_t latchPin)
* private variables are now only
uint8_t _latchPin;
uint8_t _digitalValues[Size];
* in .hpp file:
ShiftRegister74HC595::ShiftRegister74HC595(const uint8_t latchPin)
{
// set attributes
_latchPin = latchPin;
// define pins as outputs
pinMode(latchPin, OUTPUT);
// set pins low
digitalWrite(latchPin, LOW);
// allocates the specified number of bytes and initializes them to zero
memset(_digitalValues, 0, Size * sizeof(uint8_t));
updateRegisters(); // reset shift register
}
And to make it shift with SPI hardware
void ShiftRegister74HC595::updateRegisters()
{
for (int i = Size – 1; i >= 0; i–) {
//shiftOut(_serialDataPin, _clockPin, MSBFIRST, _digitalValues[i]);
SPI.transfer( _digitalValues[i]);
}
digitalWrite(_latchPin, HIGH);
digitalWrite(_latchPin, LOW);
}
For my application I wanted to do this because I have many components using the SPI bus, so I reutilize the data line (MOSI) and the clock line.
SPI.transfer(_digitalValules, Size); there is 2 methods in SPI.h
https://github.com/arduino/ArduinoCore-avr/blob/master/libraries/SPI/src/SPI.h#L244
Hi Timo, congratulations for the work done;) I have a question, first of all I’m noob and this is my first project so I could have done something wrong.
I am trying to use your library but I have a strange behavior, in the sense that the pin calls you indicate from 0 to 7, so from what I understand to call the first pin I should call the number 0 but it does not happen to me nothing, to call the first pin I have to call pin number 1 (and the test led lights up), they all work from 1 to 7.
Now I have continued by inserting another shift in cascade (I should add another 8 theoretically) and here it makes me even stranger, theoretically I should call pin number 8 to turn on the first pin of the second shifter but nothing happens, to turn it on I have to call pin number 9.
Basically to summarize the operating ranges of the pins are {1,7} and {9,15}.
Where be so the operation or did I do some bullshit?
I made the connections following your schemes;)
Hi Timo, I have found a new hobby; interfacing Flightgear flight sim with Arduino. Your library and your simple explanations are fantastic for me a auto-didact 60yr hobbyist.
Greetings from Lausanne.
Sounds like a fun hobby and thanks for that nice comment! Do you want to share a photo of your setup? Greeting back from Zurich 🙂