A 74HC595 turns three GPIOs into eight outputs, and chained chips give you as many as you like. It is how people drive LED bar graphs, 7-segment displays and big LED matrices from one board.
On the ESP32 DevKit V1 the chip runs from 3V3, so its inputs match the ESP32’s 3.3 V logic. Data and clock come from the VSPI hardware (D23 and D18), the latch is on D4, and the active-LOW OE pin is driven with PWM from D32 so all eight LEDs fade together. A 10 kΩ pull-up on OE keeps them dark while the ESP32 boots.
Wiring
| ESP32 DevKit V1 | 74HC595 8-bit shift register (DIP-16) | Wire | Notes |
|---|---|---|---|
| — | Q0 | — | To LED 1 via 220 Ω to GND (not drawn) |
| — | Q1 | — | To LED 2 via 220 Ω (not drawn) |
| — | Q2 | — | To LED 3 via 220 Ω (not drawn) |
| — | Q3 | — | To LED 4 via 220 Ω (not drawn) |
| — | Q4 | — | To LED 5 via 220 Ω (not drawn) |
| — | Q5 | — | To LED 6 via 220 Ω (not drawn) |
| — | Q6 | — | To LED 7 via 220 Ω (not drawn) |
| — | Q7 | — | To LED 8 via 220 Ω (not drawn) |
| 3V3 | VCC | red | Pin 16. Powering the chip from 3.3 V makes its inputs match the ESP32’s logic. 100 nF capacitor from VCC to GND at the chip. |
| GND | GND | black | Pin 8. |
| D23 | DS | green | Pin 14, serial data (VSPI MOSI). |
| D18 | SH_CP | blue | Pin 11, shift clock (VSPI SCK). |
| D4 | ST_CP | yellow | Pin 12, latch. |
| D32 | OE | purple | Pin 13, active-LOW output enable, driven with PWM for brightness. |
| 3V3 | OE | red | Via 10 kΩ — Pull-up: holds the outputs off while the ESP32 boots and D32 is still floating. |
| 3V3 | MR | red | Pin 10, active-LOW reset — keep HIGH. |
2–6 V part, 3.3 V board. Power it from the same voltage as your board: 3.3 V on ESP32 and Pico, 5 V on Uno. At 5 V the 74HC595 needs about 3.15 V for a HIGH, so a 3.3 V board driving a 5 V-powered chip is marginal — use a 74HCT595 at 5 V for that.
Board quirks
- Power the 74HC595 from 3V3, not VIN. At 5 V the chip needs about 3.5 V for a HIGH, so 3.3 V signals are marginal. At 3.3 V everything matches; if you need 5 V outputs (for example to drive a 5 V relay board), use a 74HCT595 on 5 V instead.
- At 3.3 V each output drives less current, so this guide uses 220 Ω resistors (about 5–6 mA per red LED). Keep the total under the chip’s 70 mA limit when all eight are on.
- Data and clock use the VSPI hardware at 8 MHz — hundreds of times faster than
shiftOut(), which matters when you chain many chips for a big LED display.SPI.begin(18, -1, 23, -1)leaves MISO (D19) free because the 595 never sends data back. - ESP32 GPIOs float for a moment at power-on, so the 10 kΩ pull-up on OE keeps the LEDs dark until the sketch has loaded known data. Without it you may see a random flash at every reset.
analogWrite()works on the ESP32 in core 3.x (it uses the LEDC peripheral). OE is active-LOW, so the sketch writes255 − brightness.- Chain more chips by wiring Q7S (pin 9) to the next chip’s DS and sharing SH_CP, ST_CP and OE. Then send one byte per chip, last chip first.
Code
// 74HC595 shift register on an ESP32 DevKit V1 — hardware SPI plus PWM brightness on OE.
// VCC → 3V3, GND → GND, DS → D23 (VSPI MOSI), SH_CP → D18 (VSPI SCK), ST_CP (latch) → D4,
// OE → D32 (PWM) with a 10 kΩ pull-up to 3V3, MR → 3V3. Q0–Q7 → LED + 220 Ω each → GND.
#include <SPI.h>
constexpr uint8_t SCK_PIN = 18, MOSI_PIN = 23, LATCH_PIN = 4, OE_PIN = 32;
void writeByte(uint8_t value) {
SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0)); // 8 MHz: far faster than shiftOut()
SPI.transfer(value); // Q7 gets the first bit sent
SPI.endTransaction();
digitalWrite(LATCH_PIN, HIGH); // rising edge copies the 8 bits to Q0–Q7 together
digitalWrite(LATCH_PIN, LOW);
}
// OE is active LOW, so a brighter LED needs a lower duty on OE.
void brightness(uint8_t level) { analogWrite(OE_PIN, 255 - level); }
void setup() {
pinMode(OE_PIN, OUTPUT);
digitalWrite(OE_PIN, HIGH); // outputs off until the register holds known data
pinMode(LATCH_PIN, OUTPUT);
digitalWrite(LATCH_PIN, LOW);
SPI.begin(SCK_PIN, -1, MOSI_PIN, -1); // no MISO: the 74HC595 never talks back, D19 stays free
writeByte(0);
brightness(255);
Serial.begin(115200);
Serial.println("74HC595 on VSPI: running light, then a breathing bar");
}
void loop() {
for (uint8_t i = 0; i < 8; i++) {
writeByte(1 << i);
delay(70);
}
for (int8_t i = 6; i > 0; i--) {
writeByte(1 << i);
delay(70);
}
writeByte(0xFF);
Serial.println("All on, fading with PWM on OE");
for (int l = 255; l >= 0; l -= 5) {
brightness(l);
delay(15);
}
for (int l = 0; l <= 255; l += 5) {
brightness(l);
delay(15);
}
Serial.println("Pattern 0b10101010 = 170");
writeByte(0b10101010);
delay(600);
}// 74HC595 shift register on an ESP32 DevKit V1 — hardware SPI plus PWM brightness on OE.
// VCC → 3V3, GND → GND, DS → D23 (VSPI MOSI), SH_CP → D18 (VSPI SCK), ST_CP (latch) → D4,
// OE → D32 (PWM) with a 10 kΩ pull-up to 3V3, MR → 3V3. Q0–Q7 → LED + 220 Ω each → GND.
#include <SPI.h>
constexpr uint8_t SCK_PIN = 18, MOSI_PIN = 23, LATCH_PIN = 4, OE_PIN = 32;
void writeByte(uint8_t value) {
SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0)); // 8 MHz: far faster than shiftOut()
SPI.transfer(value); // Q7 gets the first bit sent
SPI.endTransaction();
digitalWrite(LATCH_PIN, HIGH); // rising edge copies the 8 bits to Q0–Q7 together
digitalWrite(LATCH_PIN, LOW);
}
// OE is active LOW, so a brighter LED needs a lower duty on OE.
void brightness(uint8_t level) { analogWrite(OE_PIN, 255 - level); }
void setup() {
pinMode(OE_PIN, OUTPUT);
digitalWrite(OE_PIN, HIGH); // outputs off until the register holds known data
pinMode(LATCH_PIN, OUTPUT);
digitalWrite(LATCH_PIN, LOW);
SPI.begin(SCK_PIN, -1, MOSI_PIN, -1); // no MISO: the 74HC595 never talks back, D19 stays free
writeByte(0);
brightness(255);
Serial.begin(115200);
Serial.println("74HC595 on VSPI: running light, then a breathing bar");
}
void loop() {
for (uint8_t i = 0; i < 8; i++) {
writeByte(1 << i);
delay(70);
}
for (int8_t i = 6; i > 0; i--) {
writeByte(1 << i);
delay(70);
}
writeByte(0xFF);
Serial.println("All on, fading with PWM on OE");
for (int l = 255; l >= 0; l -= 5) {
brightness(l);
delay(15);
}
for (int l = 0; l <= 255; l += 5) {
brightness(l);
delay(15);
}
Serial.println("Pattern 0b10101010 = 170");
writeByte(0b10101010);
delay(600);
}Expected serial output
74HC595 on VSPI: running light, then a breathing bar
All on, fading with PWM on OE
Pattern 0b10101010 = 17074HC595 on VSPI: running light, then a breathing bar All on, fading with PWM on OE Pattern 0b10101010 = 170
Common errors
LEDs flash randomly at every reset
The OE pull-up is missing. Add 10 kΩ from OE to 3V3.
Nothing lights
MR is LOW or floating (tie it to 3V3), or the latch on D4 isn’t connected. Without a rising edge on ST_CP the outputs never change.
LEDs are very dim
Check the resistor values, and that the chip is a 74HC595 and not a 74HCT595 on 3.3 V (HCT parts are specified for 5 V).