SN74HC164: Hide an LED’s Intermediate States While the Register Shifts

An eight-bit pattern can end in the right place and still flash the wrong lights on its way there. The SN74HC164 exposes each intermediate shift on its output pins. Build one observable indicator channel with an Arduino UNO R3, and repeat the same eight clock pulses twice. In the second pass, interrupt the indicator’s return until the finished pattern is ready. A probe on the register output can still see every change.

Evidence scope. The article gives calculated states and a procedure for collecting measurements. The complete sketch was exercised on a computer with a logic shim. The values below do not come from a built fixture, an optical test or a firmware run on the UNO.

Follow one output before adding a display

A shift register stores bits and moves them one position per clock. On this part, a rising edge at CLK copies the logical AND of inputs A and B into QA. AND means the new bit is high only if both inputs are high. Each old bit moves from QA toward QH. With B tied high, the new bit follows A. Tying B low would insert zeros at successive edges. Taking the active-low CLR input low clears all stages at once, even without a clock.

The parallel outputs connect to the stored stages. After any edge, a connected indicator reflects that intermediate word. Here blanking means disconnecting the LED’s current path during transfer. It leaves the logic pins available for a probe. The related SN74HC595 lesson uses a separate storage register to hold a previous displayed pattern during loading. In this circuit the LED goes dark during loading. It can show the next pattern when its return is connected again.

A practical reason to measure both points is diagnosis. An LED that stays dark could indicate a good blanking circuit, an absent clock, a reversed LED or an accidentally asserted clear input. The QA and gate traces tell those cases apart.

Wire the exact 14-pin register and one indicator

Use the Texas Instruments SN74HC164N, a plastic dual in-line package with 14 pins (PDIP-14). Use the notch and the manufacturer top view to locate pin 1. The table gives the pins for the N package. The controlling board is an Arduino UNO R3 A000066 with its ATmega328P, powered through its USB connector from one regulated 5 V source. With the fixture attached, verify 4.75–5.25 V between the chip’s power pins before proceeding. The UNO and register share this rail and ground. Do not connect a second supply or leave the register unpowered while the UNO is driving inputs.

SignalSN74HC164N pinBench connection
A, B1, 2A to D2 with 47 kΩ to 0 V. B directly to +5 V.
CLK8D3 with 47 kΩ to 0 V.
CLR, active low9D4 with 47 kΩ to 0 V.
VCC, GND14, 7+5 V and 0 V. C1 100 nF ceramic across the pins and C2 10 µF, 16 V or higher, across the local rails. Positive terminal to +5 V for polarized C2.
QA and QB3, 4QA to the indicator resistor and the QA test point. QB to a high-impedance probe if needed.
QC through QH5, 6, 10, 11, 12, 13Leave unloaded. A high-impedance probe can observe them one at a time.

The 47 kΩ resistors give the three UNO-controlled register inputs defined levels while its pins are inputs. The UNO sketch writes low before enabling each output. Keep the direct logic wiring short. The register’s recommended supply range is 2–6 V. The experiment uses the five-volt rail. Stay within 0 V to VCC at its inputs during operation and avoid floating or slowly slewing clock inputs. The recommended operating range is separate from the absolute stress limits.

Connect QA → R1 2.2 kΩ, ±5% → LED anode. Use Kingbright WP7113ID, a red through-hole light-emitting diode (LED). Its cathode connects to the drain of Alpha and Omega Semiconductor AO3400A. That N-channel metal-oxide-semiconductor field-effect transistor (MOSFET) switches the return. On the SOT-23 adapter, wire pin 1 (gate) to D5 through 1 kΩ, pin 2 (source) to 0 V, and pin 3 (drain) to the LED cathode. Put 100 kΩ from the gate itself to 0 V. Verify the adapter pads against the device top view.

Put a Vishay 1N4148-TAP across the LED in the opposite direction. Its banded cathode connects to the LED anode and its anode connects to the LED cathode. The silicon diode clamps a reverse voltage across the LED when a floating return and a falling QA edge would otherwise reverse-bias it. Check both diode directions with power off. The MOSFET switch is an open return for this one LED. It does not drive, store or isolate any QA–QH logic node.

Arduino UNO D2, D3 and D4 drive SN74HC164N A pin 1, CLK pin 8 and clear pin 9. B pin 2 and supply pin 14 share 5 volts. QA pin 3 drives a red LED through 2.2 kilohms with an antiparallel 1N4148. D5 controls an AO3400A in the LED return. Startup pulldowns and supply capacitors return to the same zero volt rail.
One LED branch and two distinct observation points. Probe the logic at QA and the branch voltage across R1. Editable SVG

Check current and clock margins

R1 limits the branch even if the forward drops are ignored. Using 5.25 V and the lowest stated resistance gives 5.25 V / (2200 Ω × 0.95) = 2.51 mA. That stays below the 4 mA output-source load used for the 4.5 V high-level data sheet row. It is a bound for this one branch, not a claim about eight loaded outputs or about brightness. The current comes from QA, not D5. The MOSFET gate’s 1 kΩ resistor limits the initial current from D5. The gate must reach a valid on level. The AO3400A data sheet specifies on-resistance at 2.5 V and 4.5 V gate-to-source, and its threshold voltage is measured at a much smaller current than its load-switch characterization. Measure gate high and low at the actual gate relative to the source.

The TI 4.5 V timing table for the SN74 device across its full rated temperature range gives 25 ns minimum data setup and clear release setup, 24 ns minimum clock high or low duration, 25 ns minimum clear-low duration, and 5 ns data hold. The sketch explicitly requests 10 µs before and during a clock high. A 10 µs instruction is 10,000 ns, so even against 25 ns it sets a 400-fold interval margin in the command sequence. Between edges it requests 80 ms to make intermediate states visible. The exact interval at the pins depends on the UNO runtime, clock and wiring. Check one clean transition per edge on the bench.

With QA as bit 0 and QH as bit 7, the new word after a clock is ((old_word << 1) | bit) & 0xFF. A leading 0x denotes hexadecimal. Start at zero and send 0xA7 most significant bit first. The eight stored words are 01, 02, 05, 0A, 14, 29, 53, A7. QA therefore sees 1, 0, 1, 0, 0, 1, 1, 1. Both trials have these states. The last high remains while the clock stops. The pattern was chosen so reversing the transmission order changes the result to 0xE5.

Eight clock edges advance from hexadecimal 01 to A7. QA goes high at edges one, three, six, seven and eight. The live LED follows those levels. In the blanked trial the indicator stays disabled through all eight edges, then lights after the separate reveal.
Calculated timing. Clock widths are enlarged in the drawing. Real edge and current shapes depend on the circuit and probe. Editable SVG

Measure logic and LED current in separate passes

  1. With power off, check IC orientation, rail continuity, the 1N4148 band and LED polarity. Start with short leads and a current-limited USB supply. Use 10×, high-impedance scope probes in DC coupling. Clip all probe grounds to the fixture’s 0 V. A grounded probe clip on a floating LED node would create an unintended return.
  2. Load the supplied sketch onto the UNO with the Arduino toolchain. Check the rail and observe CLK, CLR and the gate before relying on an LED observation. Confirm CLR goes high before the first clock and the clock starts low. A board with its gate always low cannot show the live trial.
  3. Capture CLK and QA first. Use a time base that includes the eight rising edges and the one-second displayed state. A short separate capture of one edge lets you check pulse width and ringing. A slower acquisition that misses the narrow clock-high pulses can still show QA; use a suitable sample rate and inspect the scope’s acquire mode before counting clock edges.
  4. Capture the gate and QA together on another run, or use additional channels. In the first pass the gate is already high when the first clock arrives. In the second pass it stays low through the eight edges and the final 80 ms delay. QA should follow the same sequence. Observe the indicator during both passes, then independently estimate branch current using I = (VQA − VLED_A) / R1_measured. To get the difference, place one probe tip at each end of R1 and subtract the channels, leaving both ground clips at 0 V. Use matched probe factors. Use settled samples away from edges, since R1 also carries any reverse-clamp transient. Where the difference is close to channel noise, record an upper bound at your noise floor rather than reporting an exact zero.
  5. Record the actual rail, measured R1, edge count, Q and gate states, calculated current or bound and any anomalies in the blank worksheet. Distinguish the dark waiting interval from a stopped or cleared register. If the LED flashes in the blanked pass, compare gate voltage to the source, check for a grounded scope lead on the cathode or a shorted MOSFET, and inspect the reverse clamp’s polarity. If QA only reads zero, verify the high level at B, the logic at A, CLR release and a clean clock.

Compare the SN74HC595 storage-register experiment and trace the AO3400A low-side return path.

Run the complete UNO sketch

Open hc164_blanking/hc164_blanking.ino, select Arduino UNO, and upload it in the Arduino IDE. Each trial starts with the LED disabled and a fresh clear. It sends the same constant and repeats in the same order. No extra libraries or serial input are needed. If you need to pause, remove power before moving probes or changing wiring.

#include <Arduino.h>

// UNO R3 and SN74HC164N share 5 V and ground. B is hard-wired HIGH.
constexpr uint8_t kData = 2;
constexpr uint8_t kClock = 3;
constexpr uint8_t kClear = 4;      // Active low; clears every stored bit.
constexpr uint8_t kLedEnable = 5;  // HIGH connects only the test LED return.
constexpr uint8_t kPattern = 0xA7;

void setup() {
  const uint8_t pins[] = {kData, kClock, kClear, kLedEnable};
  for (uint8_t pin : pins) {
    digitalWrite(pin, LOW);
    pinMode(pin, OUTPUT);
  }
}

void runTrial(bool blankDuringShift) {
  digitalWrite(kLedEnable, LOW);
  delay(1);
  digitalWrite(kClear, LOW);
  delayMicroseconds(10);
  digitalWrite(kClear, HIGH);
  delayMicroseconds(10);

  if (!blankDuringShift) {
    digitalWrite(kLedEnable, HIGH);
    delay(1);
  }
  for (int bit = 7; bit >= 0; --bit) {
    digitalWrite(kData, (kPattern & (1u << bit)) ? HIGH : LOW);
    delayMicroseconds(10);
    digitalWrite(kClock, HIGH);
    delayMicroseconds(10);
    digitalWrite(kClock, LOW);
    delay(80);
  }
  if (blankDuringShift) {
    digitalWrite(kLedEnable, HIGH);
  }
  delay(1000);
}

void loop() {
  runTrial(false);
  runTrial(true);
}

Blank observations CSV · Complete source, diagrams and host tests ZIP

Run python3 test_host.py from the extracted archive with a C++17 compiler named c++. The test shim interprets the emitted pin writes and delays, then checks the startup state, the two eight-edge sequences, the clear and gate ordering, the requested timing and repetition. The shim has no electrical noise, load or propagation delay model.

Challenge

Could you keep CLR low during the first seven clocks, release it just before the eighth and still show the same word? What would you see on QA and QH?

Check your reasoning

No. CLR holds all eight stages at zero. Only the last transmitted bit, a one, enters QA on the eighth edge after release. The word is 0x01, so QA is high and QH is low. One LED on QA looks the same at the end in both cases. Observe QH, or reconstruct the eight-edge sequence, to distinguish the completed 0xA7 from 0x01.

Primary references