Skip to content

필사 모드: 3.3V vs 5V and Level Shifting: Why Raspberry Pi GPIO Can't Survive 5V

English
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.

Introduction — I Plugged an HC-SR04 Straight Into a Raspberry Pi

The HC-SR04 ultrasonic distance sensor is in almost every Arduino starter kit. Four pins: VCC, GND, TRIG, ECHO. The example code is done in ten lines.

Let's try the same thing on a Raspberry Pi. VCC to the 5V pin, GND to GND, TRIG to GPIO23, ECHO to GPIO24. Logically, nothing looks wrong. You run the script. A distance comes out. It works fine.

Then, a few days later — or a few hours later — GPIO24 dies. The value is always 0, or always 1. Move to a different pin and it works fine again. Then that pin dies too, before long.

The cause isn't the code — it's one simple fact. The HC-SR04 is a 5V part, and its ECHO pin outputs 5V. The Raspberry Pi's GPIO is a 3.3V device, and it can't survive 5V.

This post is about exactly what "can't survive" means, in precise terms. And we'll look at the ways to make it survive, each with its own limits.

What Logic Levels Actually Are — VIH and VIL

The word "digital" is misleading. What actually travels inside a pin isn't 0s and 1s — it's voltage, and 0 and 1 are the result of interpreting that voltage against some reference.

The interpretation reference is written on a datasheet as two numbers.

VIH is the minimum voltage reliably recognized as HIGH. VIL is the maximum voltage reliably recognized as LOW. Between the two is a band where nothing is guaranteed.

There are two matching numbers on the output side too. VOH is the minimum voltage an output guarantees when it's HIGH; VOL is the maximum voltage it guarantees when it's LOW.

Connecting two chips together ultimately comes down to this comparison: is the sending side's VOH greater than the receiving side's VIH, and is the sending side's VOL less than the receiving side's VIL? Communication works only if both are true.

Let's look at real values.

DeviceOperating voltageVIH (HIGH min)VIL (LOW max)Reference
ATmega328P (Arduino Uno)5V3.0V1.5V0.6x / 0.3x
74HC family CMOS5V3.5V1.5V0.7x / 0.3x
74HCT family5V2.0V0.8VFixed TTL-compatible values
BCM2835 (Raspberry Pi)3.3V2.31V0.99V0.7x / 0.3x
ESP323.3V2.475V0.825V0.75x / 0.25x

Both are 5V devices, and yet the ATmega328P sits at 3.0V while the 74HC sits at 3.5V. This 0.5V difference is exactly what splits apart the topic of the next section.

Why a 3.3V Output Is Readable by a 5V Input, and Why the Reverse Isn't

3.3V Sending to 5V — This Mostly Works

When a 3.3V device outputs HIGH, you get roughly 3.2V to 3.3V out of it. If a 5V Arduino receives this signal:

Received voltage 3.3V  vs  ATmega328P's VIH 3.0V
3.3V is greater than 3.0V, so it reads as HIGH.

It reads correctly. The margin is 0.3V — not generous, but it works. That's why circuits directly wiring an ESP32's or Raspberry Pi's output into an Arduino input are actually common, and they mostly work without issue.

Still, I want to stress the word "mostly." Look at the second row of the table above again. A 74HC-family logic IC's VIH is 3.5V. Since 3.3V is less than 3.5V, there's no spec guarantee it'll be recognized as HIGH. It might happily work at room temperature, then suddenly fail once the temperature shifts or you swap in a part from a different production lot. This is exactly what's behind the "it acts weird sometimes" symptom when a 74HC shift register or buffer is wired to a 3.3V board.

The correct fix in this case is to switch to the 74HCT family instead. HCT has its input threshold fixed at the TTL-standard 2.0V, so it accepts a 3.3V input with plenty of margin. Slotting in a single 74AHCT125 buffer is a widely used solution, and when a 3.3V board's signal to a WS2812 LED strip is unstable, this part is usually what fixes it.

5V Sending to 3.3V — Absolutely Not

The reverse direction isn't a recognition problem — it's a destruction problem.

A 3.3V device's datasheet lists an absolute maximum rating. For the Raspberry Pi's BCM chip, the maximum voltage you can put on a GPIO pin is:

Absolute maximum input voltage = VDD + 0.5V = 3.3V + 0.5V = 3.8V

3.8V. 5V exceeds this by 1.2V. And "absolute maximum rating" doesn't mean "performance degrades past this point" — it means "damage may occur past this point, and the manufacturer guarantees nothing."

What exactly gets damaged is the subject of the next section.

What Happens Inside the Silicon When 5V Hits a 3.3V Pin

Inside a CMOS input pin is an ESD protection circuit. It's structured like this:

        VDD (3.3V)
          ▼  Upper clamp diode (conducts pin → VDD)
  pin ────┼──── to internal gate
          ▼  Lower clamp diode (conducts GND → pin)
         GND

Once the pin voltage rises above VDD by the diode's forward-voltage drop, the upper diode starts conducting — meaning current flows from the pin into the 3.3V rail. This is the intended behavior. It's built this way specifically to safely discharge a several-thousand-volt static electricity pulse from a human hand.

The problem is how long that pulse lasts. Electrostatic discharge happens on a nanosecond timescale. The clamp diode is designed to survive that brief instant of high current — not to carry sustained current continuously.

Let's calculate what happens when you connect the HC-SR04's ECHO output. When ECHO is HIGH it outputs 5V, and that output transistor's resistance is roughly 50 ohms. Taking the diode's forward voltage as 0.7V:

Current through the diode = (5V - 3.3V - 0.7V) / 50 ohm
                           = 1.0V / 50 ohm
                           = 0.02A = 20mA

20mA keeps flowing continuously through the clamp diode into the 3.3V rail. This diode is a thin structure only a few micrometers wide and can't sustain 20mA continuously. Repeat it enough times and electromigration occurs — atoms in the junction between silicon and metal traces get physically dragged along by the current flow — until the connection eventually breaks or shorts.

This is only the first path to damage. The second one is worse.

That injected 20mA goes into the 3.3V rail. A regulator is built to source current outward, not to absorb it. If nothing else on that rail is consuming the equivalent amount, the 3.3V rail's voltage climbs. Every device connected to that rail then receives an out-of-spec voltage. This is why the damage doesn't stop at just the one GPIO pin.

The third path is the decisive one: latch-up.

Inside every CMOS structure there's always an unintended parasitic transistor pair the designer never meant to create. The alternating p-type and n-type regions naturally form a pnpn structure — which is a thyristor. Normally it's off, but inject enough current through a pin and it turns on. And by the nature of a thyristor, once it turns on, it doesn't turn itself back off until power is removed.

The moment it turns on, a low-resistance path opens between supply and ground. Hundreds of milliamps to amps of current tear through the inside of the chip. The symptoms: the Raspberry Pi suddenly gets hot, hangs, and needs a power cycle to come back. And when it does come back, there's often already melted wiring left behind in there.

To sum up, three things can happen when 5V hits a 3.3V pin: the clamp diode wears out slowly and breaks, the 3.3V rail gets pushed up and drags other parts out of spec along with it, or latch-up kills the chip instantly. All three are irreversible.

One more thing worth adding: it's precisely because this damage doesn't show up immediately that it's so dangerous. When a circuit that's been running fine for days suddenly dies, you don't go looking at the wiring for the cause. The fact that it worked fine from the start is not proof that the wiring was correct.

Logic Level Table by Board

Knowing which side your board falls on is the starting point. Here, the third column is the core of this article.

BoardLogic voltageSurvives 5V input?Max current per pinTotal GPIO combinedADC
Arduino Uno R3 / Nano / Mega5VN/A (it's 5V itself)20mA (absolute max 40mA)200mAYes
Arduino Pro Mini 3.3V3.3VNo20mA200mAYes
Arduino Due3.3VNo3mA (recommended), 15mA (max)130mAYes
Raspberry Pi 40-pin header3.3VNo16mA50mANo
Raspberry Pi Pico3.3VNo12mA50mAYes
ESP32 DevKit v13.3VNo12mA120mAYes
ESP8266 (NodeMCU)3.3VNo12mANot documentedYes (1 channel)
Teensy 4.x3.3VNo4mA (recommended)LimitedYes

Three things to flag.

First, not a single 3.3V board on this list survives 5V. Older Teensy 3.x boards and some STM32 families used to have 5V-tolerant pins, but on the boards commonly used today, it's safest to assume that's the exception, not the rule.

Second, the Raspberry Pi's lack of an ADC causes accidents constantly. Connecting an analog-output sensor to a Pi requires an external ADC like the MCP3008; not knowing this and wiring an analog sensor straight into GPIO gets you no reading at all, and if it's a 5V sensor, you lose the pin too.

Third, having a 5V power pin doesn't mean the GPIO is 5V. Pins 2 and 4 on the Raspberry Pi header output 5V, but that's meant to power components. The instant you wire that component's signal line straight into GPIO, you're right back at the first paragraph of this post.

If you've drawn out your wiring and want to check whether this combination is safe, drop your board and parts into this site's circuit wiring validator. A part like the HC-SR04, which only runs on 5V and only outputs 5V logic, connected to a 3.3V board triggers a logic-level-risk error, and it also calculates per-pin current and per-rail totals alongside it.

Resistor Voltage Dividers — Cheap, But Input-Only, and They Collapse on Fast Signals

The cheapest fix is two resistors — the same voltage divider from the earlier post.

5V signal ──[ R1 ]──┬── input pin on 3.3V board
                   [ R2 ]
                    GND

The output voltage works out to:

Output = Input × R2 / (R1 + R2)

Take R1 as 1 kilohm and R2 as 2 kilohm:

Output = 5V × 2000 / (1000 + 2000) = 5V × 0.667 = 3.33V

3.33V — a safe value for a 3.3V pin. Another commonly used pair is 1.8 kilohm and 3.3 kilohm:

Output = 5V × 3300 / (1800 + 3300) = 5V × 0.647 = 3.24V

3.24V, comfortably above the Pi's VIH of 2.31V, so it reads reliably as HIGH.

The advantage of this approach is clear: just two resistors, parts that cost pennies, and you can plug it straight onto a breadboard. For the HC-SR04's ECHO pin, this method is practically the standard solution.

The downsides come in three, and each one is worth understanding precisely.

Downside 1 — It Only Works in One Direction

A divider can only step a higher voltage down — it can't step a lower voltage up. In other words, it's only useful for a 3.3V board to receive a 5V part's output. If a 3.3V board's output needs to reach a 5V part, this circuit doesn't help at all.

Fortunately, in most cases the reverse direction works without any shifting at all. The HC-SR04's TRIG pin recognizes a Pi's 3.3V output just fine as-is. But, as in the 74HC example above, if the receiving side's VIH is high enough, it won't work.

Downside 2 — It Draws Standing Current

While the signal is HIGH, current keeps flowing continuously through R1 and R2.

1 kΩ + 2 kΩ → 5V / 3000 ohm = 1.67mA

1.67mA is negligible on USB power, but with eight of these circuits on a battery-powered device, that's 13mA, and now it's not negligible.

Try to cut the current by raising the resistor values, and the next downside gets worse. The two are a direct tradeoff.

Downside 3 — It Collapses on Fast Signals

This is the most important and most frequently overlooked downside.

The resistance the circuit sees looking back from the divider's output — its output impedance — is the parallel combination of the two resistors.

1 kΩ || 2 kΩ = (1000 × 2000) / 3000 = 667 ohm

Add the roughly 30 picofarads of capacitance from the input pin and its wiring, and you get an RC low-pass filter.

Time constant = 667 ohm × 0.00000000003F = 0.00000002 second = 20 nanoseconds

The time for the signal to rise from 10 percent to 90 percent is 2.2 times the time constant.

Rise time = 20ns × 2.2 = 44 nanoseconds

The HC-SR04's ECHO signal changes on a millisecond timescale, so 44 nanoseconds is nowhere near a problem — which is why this particular combination works fine.

Now let's raise the resistor values. If you used 10 kilohm and 20 kilohm to save current:

Output impedance = 10000 || 20000 = 6667 ohm
Time constant     = 6667 × 30pF = 200 nanoseconds
Rise time         = 440 nanoseconds

440 nanoseconds. A single bit on a 1MHz SPI signal is 1000 nanoseconds long, so by the time the signal is only halfway up, the next bit has already started. The waveform smears into triangles and the data corrupts. This is why you don't use a resistor divider for SPI or fast UART.

To summarize, here's where a resistor divider is and isn't a fit:

SignalApproximate frequencyResistor-divider suitability
Button, relay stateA few HzVery well suited
HC-SR04 ECHOHundreds of HzSuited
UART at 9600bps9.6kHzSuited
UART at 115200bps115kHzPossible with low resistor values
I2C at 100kHz100kHzUnsuited (open-drain, different structure)
SPI at 1MHz and up1MHz+Unsuited
WS2812 data800kHz, strict timingUnsuited

MOSFET Bidirectional Shifters and Dedicated ICs

The BSS138 Two-Resistor Circuit

The most widely used bidirectional shifter is built from a single N-channel MOSFET and two pull-up resistors. Inside most four-channel level-shifter breakout boards you'll find, this is the circuit doing the work.

Understanding how it works also makes its limits clear. The MOSFET's gate is fixed at the lower voltage, 3.3V; the source connects to the 3.3V-side line, and the drain connects to the 5V-side line. Each side has its own pull-up at its own voltage.

With both lines left alone, the 3.3V side rises to 3.3V and the 5V side rises to 5V, each on its own. Since gate and source sit at the same voltage, the MOSFET is off.

Pull the 3.3V side LOW and the source drops to 0V. Since the gate is at 3.3V, that puts 3.3V across gate and source, turning the MOSFET on, and it drags the 5V side down along with it.

Pull the 5V side LOW instead, and first the MOSFET's parasitic body diode conducts, pulling the 3.3V side down to around 0.7V; that creates a gate-source voltage, which turns the MOSFET fully on. Both sides end up LOW either way.

Whichever side starts it, LOW propagates across, and HIGH is made by each side's own pull-up. There's no need to specify a direction.

The limitation shows up right here. This circuit is fundamentally open-drain in nature. How fast it rises to HIGH is set entirely by the pull-up resistor and the capacitance — the MOSFET contributes nothing to that process. With a 10k pull-up and 50 picofarads, the rise time exceeds 1 microsecond. So the practical ceiling is roughly 400kHz to 1MHz. Perfect for I2C, but unusable for high-speed SPI.

Dedicated Level-Shifter ICs

When you need speed or lots of channels, you go to a dedicated IC. Each part has a distinctly different personality, so you need to know the criteria for choosing.

PartDirectionOutput typeApproximate speedI2C useNotes
Resistor dividerUnidirectional (step-down)PassiveUnder 100kHzNoCheapest, two parts
BSS138 circuitBidirectionalOpen-drain400kHz–1MHzSuitedNo direction to specify
74LVC245Unidirectional (pin-selectable)Push-pull100MHz+No8-channel, very fast
74AHCT125Unidirectional (upward)Push-pull50MHz+NoFor pushing 3.3V up to 5V
TXB0104 / TXB0108Auto direction sensingPush-pullTens of MHzUnsuitedConflicts with pull-ups
TXS0102 / TXS0108Auto direction sensingOpen-drain compatibleA few MHzSuitedNearly I2C-dedicated
PCA9306BidirectionalOpen-drain400kHzSuitedI2C-dedicated, 2-channel

The row you absolutely must remember from this table is the TXB family. The TXB0104 has automatic direction sensing, which sounds convenient, but you must never use it for I2C. This chip has a built-in circuit that detects the moment a signal changes and briefly pushes it hard — and an I2C bus's pull-up resistors interfere with that detection, scrambling the direction decision. The datasheet explicitly says not to use it on open-drain signals. The same manufacturer's TXS family is built for exactly that purpose. The names differ by a single letter while the use cases are opposite, so be careful when ordering.

Why I2C Is Different — The Open-Drain Bus

I2C gets its own section because this bus starts from a different premise than every method above.

I2C's SDA and SCL are open-drain. No device on the bus ever pushes the line HIGH. Devices only pull it down or let go, and HIGH is made entirely by the pull-up resistor.

That immediately exposes one issue. Whatever voltage the pull-up is tied to decides the voltage of the entire bus. A 5V sensor module often already has a 5V pull-up built right onto its board. Wire that module straight into a Raspberry Pi's SDA and SCL, and both lines sit at 5V even while the bus is idle. That means 5V is applied to the Pi's GPIO2 and GPIO3 continuously — the clamp-diode story from earlier isn't just happening when a signal is present, it's happening all the time.

So level shifting on I2C isn't optional. And the available methods are limited too. You can't use a resistor divider — put a divider on an open-drain line and that resistor interacts with the pull-up so the LOW voltage never drops all the way to 0V. You can't use a push-pull shifter either — that's the TXB-family problem from above. What's left is a BSS138 circuit, the TXS family, or the PCA9306.

Calculating the Pull-Up Resistor Value

There's one more calculation worth knowing when working with I2C: the upper and lower bounds on the pull-up resistor value.

The lower bound is set by how strongly a device can pull the line down. The I2C spec requires that an output can sink 3mA while holding LOW below 0.4V.

Minimum pull-up resistance = (3.3V - 0.4V) / 0.003A = 967 ohm

Use a pull-up smaller than 967 ohms and a device can't pull the line low enough.

The upper bound is set by rise time. Standard mode at 100kHz allows a maximum rise time of 1000 nanoseconds, and assuming 100 picofarads of bus capacitance:

Maximum pull-up resistance = 1000ns / (0.8473 × 100pF) = 11803 ohm ≈ 11.8 kΩ

At 400kHz fast mode, the allowed rise time shrinks to 300 nanoseconds, so:

Maximum pull-up resistance = 300ns / (0.8473 × 100pF) = 3541 ohm ≈ 3.5 kΩ

That's why 4.7 kilohm has settled in as the convention for standard mode, and 2.2 kilohm for fast mode. It's not an arbitrary habit — it's the midpoint of this exact calculation.

A Common Pitfall on the Raspberry Pi

The Pi's GPIO2 and GPIO3 have a fixed 1.8 kilohm pull-up soldered onto the board. Commercial I2C modules typically also carry their own pull-up. All of these sit in parallel with each other.

Connect two modules, each with a 10 kilohm pull-up:

Combined resistance = 1 / (1/1800 + 1/10000 + 1/10000) = 1 / 0.000756 = 1324 ohm
Current needed to hold LOW = (3.3V - 0.4V) / 1324 ohm = 0.00219A = 2.19mA

2.19mA, inside the 3mA spec. It works.

Now connect four modules, each with a 4.7 kilohm pull-up:

Combined resistance = 1 / (1/1800 + 4/4700) = 1 / 0.001406 = 711 ohm
Current needed = (3.3V - 0.4V) / 711 ohm = 0.00408A = 4.08mA

4.08mA — over spec. Some device can't pull the line below 0.4V, and the bus intermittently breaks. The symptom looks like "fine with three devices, weird starting at the fourth." The fix is to physically remove the pull-up resistors on the modules. On most modules, that resistor is a small part sitting right on the board, and desoldering it with an iron does the job.

What It Looks Like in Actual Code

Let's go back to the HC-SR04. Once you put a 1k/2k divider on ECHO, the code turns ordinary.

# Connect an HC-SR04 to a Raspberry Pi.
#
# Wiring:
#   VCC  -> 5V (pin 2)
#   GND  -> GND (pin 6)
#   TRIG -> GPIO23  (takes the Pi's 3.3V output directly. No shifting needed.)
#   ECHO -> through a 1k resistor to GPIO24, then GPIO24 to GND through a 2k resistor
#
# Divider result: 5V * 2000 / 3000 = 3.33V
# Connect ECHO directly to GPIO24 and the pin gets damaged.

from gpiozero import DistanceSensor
from time import sleep

sensor = DistanceSensor(echo=24, trigger=23, max_distance=2.0)

while True:
    # distance is in meters.
    print(f"{sensor.distance * 100:.1f} cm")
    sleep(0.2)

There's no trace of the divider in the code at all. From the software side, nothing happened — which is exactly why hardware problems end up getting hunted for in code. Broken wiring, and the code still looks correct, and can even appear to work correctly.

Conclusion — The Power Pin's Voltage and the Signal Pin's Voltage Are Different Numbers

This post's conclusion is short. Before connecting a part, you need to check two things separately: what voltage does this part operate at, and what voltage is the signal this part outputs.

The two are usually the same, but not always. The HC-SR04 runs on 5V and outputs 5V. The PIR sensor HC-SR501 runs on 5V but outputs 3.3V. Both are 5V parts, and one kills a Pi while the other is safe. What you need to check on the datasheet isn't the supply voltage — it's the output logic level.

And this check can't be substituted by whether the circuit appears to work. A circuit with a 5V ECHO wired directly into a Pi works fine at first. Hardware has a region where "it works" is not proof of "it's safe," and logic levels are one of the most representative spots for exactly that trap.

Next time, we move from voltage to current as the source of trouble: why a board reboots the instant you connect a motor to GPIO.

현재 단락 (1/166)

The HC-SR04 ultrasonic distance sensor is in almost every Arduino starter kit. Four pins: VCC, GND, ...

작성 글자: 0원문 글자: 18,019작성 단락: 0/166