5 V vs 3.3 V Logic + Level Shifting
Input Limits, Thresholds, Dividers, Buffers, and Bidirectional Buses
The robot hand team grabs a cheap sensor breakout from the drawer. It has four pins, the example code is everywhere, and the product page says "Arduino compatible." The temptation is to plug it into the ESP32 and move on.
That phrase is not an electrical guarantee. Arduino compatibility often means a 5 V world. ESP32-class GPIO lives in a 3.3 V world. A signal can be a perfectly valid logic high for one chip and a damaging over-voltage for the next chip.
Level shifting is not a ceremonial adapter board. It is the discipline of asking what voltage appears at the receiving pin, whether that voltage is a valid logic state, and whether it stays inside the absolute maximum ratings.
By the end, you can
- Separate supply voltage, logic-high voltage, input threshold and absolute maximum rating
- Explain why a 5 V output can damage a 3.3 V GPIO even when the signal is just a digital high
- Choose a one-way divider or buffer for 5 V to 3.3 V inputs
- Recognize when a 3.3 V output may not satisfy a 5 V input's high threshold
- Choose bidirectional translation for open-drain buses and push-pull translators for driven buses
- Use a repeatable pre-connection checklist before mixing boards and modules
Logic is analog before it is digital
A GPIO input does not receive the word "high." It receives a voltage. Inside the chip, input circuitry compares that voltage against thresholds. Below the low threshold it is read as zero. Above the high threshold it is read as one. Between those thresholds the chip is not promising a clean interpretation.
For an ESP32-style 3.3 V GPIO, a useful mental model is:
- Near 0 V is a low.
- Around 3.3 V is a high.
- Around 5 V is not a better high. It is outside the pin's safe input range.
This is the first trap: power input voltage and GPIO voltage are not the same question. A board may accept 5 V on a VIN or USB pin because it has a regulator. The microcontroller pins may still tolerate only 3.3 V logic.
A module is powered from 5 V and its output pin drives directly into an ESP32 GPIO. What is the correct question?
-
Correct. The receiving pin only cares about the voltage it sees and the current that can flow through its protection structures.
-
Arduino compatibility often means a 5 V ecosystem. It is not a safety rating for a 3.3 V GPIO.
-
USB power on the board does not make every GPIO 5 V tolerant.
-
Short wires help signal quality, but they do not fix an over-voltage.
5 V into 3.3 V: reduce the voltage
The easiest case is a one-way signal from a 5 V device into a 3.3 V input. A resistor divider can be enough when the signal is slow and the receiver input current is tiny.
The divider is the same circuit from Lesson #3. Put a top resistor between the 5 V output and the ESP32 input. Put a bottom resistor from the ESP32 input to ground. The pin sees the divided voltage:
For a 5 V input, 10 kOhm on top and 20 kOhm on bottom gives:
Try these moves:
- Start at 5 V,
10 kOhmtop and20 kOhmbottom. The pin lands near 3.33 V. - Lower the top resistor to 1 kOhm and leave the bottom high. The pin can become unsafe.
- Raise both resistors very high. The DC voltage still looks right, but the node becomes easier to disturb and slower with capacitance.
- Lower the input voltage to 3.3 V. A divider may no longer be needed for safety.
A 5 V sensor output goes through a 10 kOhm top resistor and a 20 kOhm bottom resistor
to ground. Estimate the voltage at the ESP32 input and say whether it is below a 3.6 V
absolute maximum.
Show worked solution
The input is 5 * 20 / (10 + 20), about 3.33 V. That is below 3.6 V, so the DC level
is inside the absolute maximum. You would still check edge speed, input leakage and
whether the signal only travels one way.
3.3 V into 5 V: check the receiving threshold
The reverse direction is subtler. A 3.3 V output does not damage a 5 V input. The question is whether the 5 V input recognizes 3.3 V as high.
Some 5 V logic families accept a 3.3 V high easily. Others require a high threshold
closer to a fraction of the 5 V supply. The right answer is in the receiving device's
datasheet as VIH, the minimum input-high voltage.
If VIH is 2.0 V, a 3.3 V output is a clear high. If VIH is 0.7 times a 5 V supply,
the required high is 3.5 V and a 3.3 V output has no margin. In that case you use a
buffer, a translator IC, or run the receiving device at a compatible voltage if the
datasheet allows it.
A 5 V device says its input-high threshold is 0.7 times VCC. With VCC = 5 V, is a 3.3 V GPIO output guaranteed high?
-
Correct. The voltage is safe, but it may not meet the receiving input-high threshold.
-
Some 5 V inputs accept 3.3 V. Others do not. The datasheet decides.
-
A lower drive voltage is not the damage mechanism here. Recognition margin is the problem.
-
The protocol does not change the input threshold.
Bidirectional lines need a different trick
I2C is the perfect warning against oversimplified level shifting. SDA and SCL are not ordinary push-pull outputs. Devices pull the line low and release it high through pull-up resistors. Either side may need to pull low.
That circuit is good for slow, open-drain buses such as many I2C connections. It is not a universal magic block. A fast push-pull SPI clock, a UART TX line, a camera bus or an LED data stream may need a unidirectional buffer, a direction-controlled transceiver or a translator designed for that edge rate and drive style.
For a mixed-voltage board, the choice is a table you apply every time:
- Same voltage on both sides: direct connection may be fine.
- 5 V output to 3.3 V input: divider or unidirectional buffer.
- 3.3 V output to 5 V input: check
VIH; use a buffer if margin is weak. - Open-drain bidirectional bus: MOSFET or I2C translator with pull-ups to each rail.
- Push-pull bidirectional bus: direction-controlled translator or a part designed for auto-direction at the needed speed.
- Analog signal: do not use a digital level shifter. Scale and protect it as an analog input.
Measure before the expensive mistake
The bench workflow is simple and worth doing even when the circuit looks obvious.
- Identify every rail: 5 V, 3.3 V, battery, motor, sensor.
- Identify every signal direction: output, input, bidirectional, open-drain or analog.
- Read the receiving input limits:
VIL,VIHand absolute maximum. - Choose the translator based on direction and edge speed.
- Power the module without the microcontroller connected and measure the signal's idle voltage.
- Connect through the translator and measure the receiving pin.
- Only then run firmware.
You have an ESP32 reading the echo pin of a 5 V HC-SR04-style ultrasonic sensor, and also driving a 5 V addressable LED strip. Pick the likely translation method for each signal.
Show worked solution
The echo pin is a one-way 5 V output into a 3.3 V input, so a divider or unidirectional buffer can be appropriate if the timing still has margin. The LED data line is a one-way 3.3 V output into a 5 V input, so check the LED input-high threshold. If 3.3 V has weak margin, use a fast unidirectional buffer or logic translator powered for the target input level.
Many chips have ESD/protection structures from pins to rails. If you drive a pin above the rail, those structures can conduct current into the chip. Sometimes a circuit seems to work because the pin clamps through protection silicon. That is not safe operation. Limit injection current only when the datasheet explicitly allows it, and do not build a product around accidental clamp behavior.
Key takeaways
- A digital input still receives an analog voltage. Valid logic and electrical safety are separate questions.
- A 5 V high can damage a 3.3 V GPIO. Powering a board from USB or VIN does not make its pins 5 V tolerant.
- A resistor divider is useful for slow one-way 5 V outputs into 3.3 V inputs, but it is not a universal translator.
- A 3.3 V output into a 5 V input is usually safe but may not meet the receiving input-high threshold.
- Open-drain bidirectional buses need translators that let each side pull low and return high to its own rail.
- The pre-connection checklist is rail, direction, threshold, absolute maximum, translator, measurement, firmware.
Level shifting is the difference between "it plugged in" and "it is electrically allowed." The board does not know that the wire came from a sensor, an Arduino example, or a quick prototype. It only sees voltage and current. Train yourself to ask what the receiving pin sees before the wire touches the header, and mixed-voltage systems become routine rather than risky.