Lesson 101: Using shiftOut()
Learn how shiftOut() sends serial bits to external devices like shift registers, including bit order and practical output control flow.
Progress indicator
Lesson 101 of 101
Learning Objectives
- Understand what shiftOut() does and how serial bit sending works.
- Learn shiftOut() syntax with data, clock, bit order, and value.
- Understand MSBFIRST vs LSBFIRST while transmitting bytes.
- Use shiftOut() with shift registers for multi-output expansion.
- Decode and design output patterns using binary byte values.
- Avoid common latch/clock/data timing mistakes in output control.
Concept Explanation
What is shiftOut()
shiftOut() sends one byte (8 bits) serially from your ESP32/Arduino to an external chip.
It is commonly used with output shift registers to control many LEDs or digital outputs using fewer MCU pins.
shiftOut() Syntax
shiftOut(dataPin, clockPin, bitOrder, value);
dataPin: output pin that carries each bit.clockPin: clock pulses that move each bit into target device.bitOrder:MSBFIRSTorLSBFIRST.value: byte to send.
Example: shiftOut(23, 18, MSBFIRST, B10101010); sends alternating 1/0 bits to the external register.
How shiftOut() Works
- Selects the first bit according to bit order.
- Writes that bit on data pin.
- Toggles clock pin to push bit into receiver.
- Repeats until all 8 bits are sent.
- Receiver stores byte and updates outputs after latch.
Think of it as moving 8 boxes onto a conveyor belt, one box per clock pulse.
Serial Data Sending Concept
Serial sending means transmitting one bit at a time over a data line with timing pulses.
This lets one microcontroller control many outputs through expansion chips while using fewer GPIO pins.
Practical advantage: instead of needing 8 direct output pins, you can control 8 outputs with just data, clock, and latch pins.
Bit Order (MSBFIRST vs LSBFIRST)
MSBFIRST: sends the most significant bit first.LSBFIRST: sends the least significant bit first.
Wrong bit order causes wrong output mapping even if all wires are correct.
If LED pattern appears mirrored/reversed, bit order mismatch is usually the first thing to check.
Using shiftOut() with Shift Registers
Shift registers (like 74HC595) receive serial bits and expose them as parallel outputs.
Typical flow: pull latch LOW -> shiftOut byte -> pull latch HIGH to apply new output state.
You can chain multiple shift registers to control 16, 24, or more outputs by sending multiple bytes in sequence.
When to Use shiftOut()
- Driving many LEDs from limited MCU pins.
- Controlling digital output banks through shift registers.
- Building scalable output panels and indicator arrays.
- Expanding relay/control channels in embedded prototypes.
Example Code
This example sends alternating byte patterns to a shift register output stage.
const int DATA_PIN = 23;
const int CLOCK_PIN = 18;
const int LATCH_PIN = 5;
byte patternA = B10101010;
byte patternB = B01010101;
void setup() {
pinMode(DATA_PIN, OUTPUT);
pinMode(CLOCK_PIN, OUTPUT);
pinMode(LATCH_PIN, OUTPUT);
Serial.begin(115200);
}
void loop() {
digitalWrite(LATCH_PIN, LOW);
shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, patternA);
digitalWrite(LATCH_PIN, HIGH);
Serial.println("Sent patternA");
delay(500);
digitalWrite(LATCH_PIN, LOW);
shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, patternB);
digitalWrite(LATCH_PIN, HIGH);
Serial.println("Sent patternB");
delay(500);
}Example Code Explanation
- Define data, clock, and latch pins used by shift register connection.
- Create two output patterns (
patternAandpatternB). - In setup, configure pins as OUTPUT and start Serial debugging.
- Set latch LOW before writing so outputs do not flicker during transmission.
- Send one full byte using
shiftOut(..., MSBFIRST, patternA). - Set latch HIGH to apply transmitted byte to output pins at once.
- Serial log confirms which pattern was sent at each step.
- Repeat for second byte pattern to demonstrate output changes over time.
- Alternating patterns help beginners verify bit order and channel mapping quickly.
What Happens Inside
- Program chooses next bit from byte.
- Bit level is written on data pin.
- Clock pulse tells external chip to accept that bit.
- After 8 pulses, full byte is in internal shift register buffer.
- Latch transition updates visible output pins together.
- Loop repeats and keeps streaming new patterns to outputs.
Common Mistakes with shiftOut()
- Wrong bit order leads to unexpected output mapping.
- Missing latch LOW/HIGH sequence causes unstable output updates.
- Swapped data/clock wiring produces random or no output.
- Sending values without validating bit patterns in Serial logs.
- Leaving latch HIGH during transmit and getting visual output glitches.
- Not documenting bit-to-output mapping, causing maintenance confusion later.
Best Practices for shiftOut()
- Always confirm bit order from external chip datasheet.
- Use latch control to avoid visible output glitching.
- Keep wiring short and clean for reliable clock/data timing.
- Log byte values in binary during bring-up and troubleshooting.
- Use named bit masks/constants for readable output control logic.
- Create simple test patterns (all ON, all OFF, alternating bits) during wiring checks.
Try it now
Open the simulator workspace and test serial output byte patterns with latch/clock flow.