A NAND gate with transistors is typically built using Resistor-Transistor Logic (RTL). In this configuration, NPN bipolar junction transistors (BJTs) are wired in parallel. The logic is straightforward: when both inputs are HIGH, both transistors saturate, pulling the shared output node LOW to ground. If either input is LOW, the corresponding transistor cuts off, and a pull-up resistor forces the output HIGH. While modern CMOS ICs like the 74HC00 are cheaper and faster, building a discrete NAND gate remains a foundational bench exercise for understanding transistor switching, biasing, and logic fan-out limitations.
The Anatomy of a Discrete NAND Gate with Transistors
To build this gate, we use standard NPN transistors in a TO-92 package. If you are holding a 2N3904 with the flat side facing you, the pins from left to right are Emitter (E), Base (B), and Collector (C).
In our RTL NAND schematic, the physical pinout maps to the logic function as follows:
- Emitters: Tied directly to the common ground (0V).
- Collectors: Tied together at a single junction. This junction is the logic output.
- Bases: Serve as Logic Input A and Logic Input B. Each base is fed through its own current-limiting base resistor.
- Pull-up Resistor: Connects the shared Collector junction to Vcc (e.g., 5V).
The standard logic symbol for a NAND gate is an AND gate (a D-shaped symbol) with a small inversion bubble at the output. In our discrete circuit, that 'bubble' is physically realized by the inverting nature of the common-emitter transistor switch combined with the pull-up resistor.
Operation Regions and Biasing the RTL NAND Gate
When using BJTs for digital logic, we do not want them acting as linear amplifiers. We must bias them strictly as switches, toggling between Cutoff (OFF) and Saturation (ON). The active/linear region is a forbidden zone for digital logic because it results in undefined output voltages and excessive heat dissipation.
| State | Input Voltage (Vbe) | Base Current (Ib) | Collector Current (Ic) | Vce (Output Voltage) |
|---|---|---|---|---|
| Cutoff (Input LOW) | < 0.5V | 0 mA | ~0 mA | ~5.0V (HIGH) |
| Active (Avoid) | 0.6V - 0.7V | Microamps | Linear (β × Ib) | 0.7V - 4.3V (Undefined) |
| Saturation (Input HIGH) | > 0.7V (Driven) | Calculated for forced β | Max (Vcc / R_pullup) | ~0.2V (LOW) |
How to Bias and Select Base Resistors
To guarantee saturation, we use a technique called forced beta. A typical small-signal transistor has a DC current gain (hFE or β) of 100 to 300. However, hFE drops significantly at higher currents and varies with temperature. To ensure the transistor saturates fully (Vce ≈ 0.2V), we design the base current assuming a forced β of 10.
If our pull-up resistor is 1kΩ, the maximum collector current when the output is pulled LOW is roughly 5mA (5V / 1000Ω). Using a forced β of 10, we need a base current (Ib) of 0.5mA. Assuming a 5V logic input and a Vbe drop of 0.7V, the base resistor (Rb) calculation is:
Rb = (Vin - Vbe) / Ib = (5V - 0.7V) / 0.0005A = 8,600Ω
The nearest standard E12 value is 10kΩ, but for a stronger, noise-immune drive, 4.7kΩ is the preferred bench default. This provides roughly 0.9mA of base current, driving the transistor deep into saturation.
Complete Application Circuit: Dual-Sensor Safety Interlock
Let us apply this to a practical scenario: a safety interlock for a small 5V DC cooling fan. The fan should run unless both enclosure doors are open. We will use mechanical limit switches as inputs. When a door is closed, the switch is pressed, feeding 5V to the gate input.
- Power Rail: Establish a clean 5V DC Vcc and common GND on your breadboard.
- Pull-up Resistor: Insert a 1kΩ resistor from the 5V rail to a central node (this is your Output).
- Transistors: Place two 2N3904 NPN transistors. Tie both Emitters to GND. Tie both Collectors together and connect them to the Output node.
- Base Resistors: Connect a 4.7kΩ resistor from Input A to the Base of Q1. Connect a second 4.7kΩ resistor from Input B to the Base of Q2.
- Input Conditioning: Connect your mechanical limit switches between the 5V rail and Input A / Input B.
- Pull-downs (Critical): Connect a 10kΩ resistor from Input A to GND, and another 10kΩ from Input B to GND.
- Load: Connect the input of your fan relay module or microcontroller GPIO to the Output node.
Bench Scenario: The Floating Input Trap
Theory is clean; the workbench is not. Here is a real-world walkthrough of a common failure mode when building a NAND gate with transistors.
The Setup: I was prototyping the interlock circuit above to feed a 5V-tolerant Arduino GPIO. I used 5.05V from a bench supply, 4.7kΩ base resistors, and a 1kΩ pull-up. The inputs were driven by SPST mechanical micro-switches mounted on an acrylic enclosure.
The Numbers: With both switches closed (Inputs HIGH), the output correctly read 0.18V (LOW). With Switch A closed and Switch B open, the output should have been pulled HIGH by the 1kΩ resistor. Instead, my Fluke 87V multimeter read a fluctuating 2.4V.
The Outcome: The Arduino read this 2.4V as an erratic logic level, occasionally triggering the fan relay when it should have been disabled. The 2.4V sits squarely in the undefined threshold region for 5V CMOS logic (where Vih minimum is typically 3.5V and Vil maximum is 1.5V).
What Went Wrong: I had initially omitted the 10kΩ pull-down resistors on the inputs. When Switch B was opened, it disconnected the 5V source, but it did not connect the Base of Q2 to ground. The base was left floating. A floating BJT base acts like a tiny antenna, picking up 60Hz capacitive hum from nearby mains wiring and accumulating leakage current. This micro-current was enough to push Q2 out of cutoff and into the active/linear region. Q2 partially conducted, dropping the output voltage to 2.4V instead of letting it float to 5V.
The Fix: Adding 10kΩ pull-down resistors from each Base to GND provided a definitive path for leakage current to dissipate. When the switch opened, the base was firmly clamped to 0V. The output immediately snapped to a clean 4.95V HIGH.
Testing, Failure Modes, and Safe Default Part Numbers
Transistors in RTL circuits generally fail due to overcurrent (shorting the output to Vcc without a pull-up resistor) or reverse base-emitter breakdown. The base-emitter junction acts like a Zener diode with a reverse breakdown voltage of only about 5V to 6V. If you accidentally apply negative voltage to the base, the junction will avalanche and destroy the transistor's gain.
How to Test with a Multimeter
You can verify the health of a BJT directly on the breadboard (with power removed) using your multimeter's Diode Test mode:
- Base-Emitter Junction: Place the Red probe on the Base, Black on the Emitter. You should read a forward voltage drop of 0.60V to 0.75V. Swap probes (Black on Base, Red on Emitter); it should read 'OL' (Open Loop).
- Base-Collector Junction: Red on Base, Black on Collector. Expect 0.60V to 0.75V. Reverse probes; expect 'OL'.
- Collector-Emitter Path: Place probes across Collector and Emitter in both directions. Both must read 'OL'. If you read 0.00V or a low resistance, the transistor has suffered a thermal runaway event and is internally shorted.
Safe Default Part Numbers
When sourcing components for discrete logic, stick to these proven, high-availability NPN transistors:
- 2N3904: The undisputed standard for hobbyist and educational RTL. Rated for 40V Vceo and 200mA Ic. It has a predictable hFE curve and costs roughly $0.05 in bulk. (Source: ON Semiconductor Datasheet)
- BC547: The European equivalent to the 2N3904. Rated for 45V and 100mA. Note that the TO-92 pinout for the BC547 is Collector, Base, Emitter (C-B-E) when viewing the flat side—the exact reverse of the 2N3904. Always check the datasheet before soldering.
- 2N2222 (P2N2222A): Use this when your NAND gate needs to sink heavier loads directly (up to 800mA), such as driving a small relay coil without a secondary driver transistor. It is overkill for pure logic signaling but excellent for mixed logic-power stages.
Building a NAND gate with transistors bridges the gap between abstract Boolean algebra and physical electron flow. By respecting forced-beta biasing, conditioning your inputs with pull-downs, and testing your junctions, you can build robust discrete logic that behaves exactly as the truth table demands.






