Blog · 2026-07-05 · Electronics

3.3 V vs 5 V Logic: Level Shifting for Arduino, ESP32 and Raspberry Pi

Half the boards on your bench think "HIGH" means 5 volts; the other half think it means 3.3. Wire them together carelessly and the best case is garbled data — the worst case is a dead pin. Here's the logic-level system, the safe combinations, and the right shifter for each job.

The hobby electronics world is living through a long, slow voltage migration. The Arduino Uno generation and the sensor ecosystem built around it speak 5 V logic; everything modern — ESP32, Raspberry Pi (all of them), Pico, most 32-bit boards, most new sensors — speaks 3.3 V. A robot almost inevitably mixes eras: a 3.3 V brain, a 5 V ultrasonic sensor, servos expecting 5 V-ish signals, an old LCD. Every one of those meetings is a logic-level negotiation, and knowing the rules turns a minefield into a checklist.

What a logic level actually is

Digital pins don't read "5 V" or "0 V" — they read against thresholds. A receiving input has a VIH (minimum voltage guaranteed to register as HIGH) and a VIL (maximum guaranteed LOW); a transmitting output promises at least VOH when driving HIGH. For classic 5 V CMOS inputs, VIH is about 0.7 × VCC = 3.5 V; for 3.3 V parts, about 2.3 V; for 5 V TTL-style inputs, a friendlier fixed 2.0 V. Communication works when the sender's guaranteed HIGH clears the receiver's threshold with margin — and fails, intermittently and maddeningly, when it only almost does.

Works reliably: V_OH (sender) > V_IH (receiver), with margin
Damages hardware: V (sender) > V_max (receiver's absolute rating)

Those are the two separate questions for every connection: will it register, and will it survive. They have different answers in each direction.

Direction one: 3.3 V output → 5 V input

Safety is free here — 3.3 V can't hurt a 5 V pin. The question is threshold. Against a TTL-type input (VIH = 2.0 V): 3.3 V clears it easily, and this is why so many 3.3 V-to-5 V connections "just work" — much of the 5 V ecosystem uses TTL thresholds. Against a full 5 V CMOS input (VIH = 3.5 V): 3.3 V falls short of the guarantee. It often works anyway at room temperature — real thresholds sit below the guaranteed worst case — which produces the classic trap: a marginal connection that works on the bench and fails in the field, in the cold, or on the next batch of chips. If the receiving datasheet says CMOS thresholds, shift properly; "it worked when I tested it" is not a level-shifting strategy.

Direction two: 5 V output → 3.3 V input

Here the threshold is trivially cleared and the danger is real: most 3.3 V pins have an absolute maximum around VCC + 0.3 = 3.6 V, and 5 V exceeds it by a comfortable, destructive margin. Sometimes the failure is instant; more often it's cumulative — the pin's protection diodes shunt the overvoltage into the 3.3 V rail, slowly cooking the pin (and weirdly back-powering the board) until one day the input just stops inputting. The exceptions are 5 V-tolerant pins: some chips (many STM32 pins, the Raspberry Pi Pico's RP2040 GPIOs under specific conditions, various peripherals) are explicitly rated to accept 5 V on inputs while running at 3.3 V. "Explicitly rated" means the datasheet says so; the ESP32 is not 5 V-tolerant despite persistent forum folklore, and the Raspberry Pi's GPIOs emphatically are not — the Pi has no protection worth mentioning, and 5 V on a GPIO can kill the SoC itself.

The rule that prevents all of it: before connecting any two boards, ask of every signal wire — who drives it, at what voltage, and what does the receiver tolerate? Thirty seconds per wire. The ultrasonic sensor's ECHO pin (5 V output) into an ESP32 is the canonical robot example: it needs shifting; the TRIG pin (ESP32 3.3 V output into the sensor's input) usually doesn't.

The shifting toolbox

The voltage divider — for one-way signals downward. Two resistors scale 5 V to ~3.2 V; 1 kΩ over 1.8 kΩ is the classic pair. Perfect for that ECHO pin, serial RX into a 3.3 V board, any modest-speed unidirectional line. Its limits: one direction only, and the RC formed with pin capacitance rounds off fast edges — above a few MHz (fast SPI), dividers start eating signal integrity. Design pairs properly with the Voltage Divider Calculator, and see the divider deep-dive for the impedance reasoning.

The MOSFET bidirectional shifter — for I²C and anything two-way. One small N-channel MOSFET (BSS138) plus two pull-ups per channel, sold as the ubiquitous 4- and 8-channel red/blue modules for pocket change. It shifts both directions automatically, which matters because I²C's data line genuinely travels both ways — a divider physically cannot serve it. This module is the default answer for I²C sensors across a voltage boundary and for any line whose direction you'd rather not think about. Speed comfortable through 400 kHz I²C and beyond.

Dedicated buffer ICs — for speed and many channels. The 74AHCT125/74HCT245 family running at 5 V with TTL inputs makes a superb 3.3→5 V booster (that's how 3.3 V boards drive 5 V WS2812 LED strips reliably); TXB/TXS auto-direction chips handle multi-line buses. These are the tools when dividers are too slow and MOSFET modules too few-channeled.

The zero-component shifts. Open-drain trick: configure the 3.3 V side's pin as open-drain with a pull-up to 5 V (only on a 5 V-tolerant pin!) and the line swings the full 5 V. And the best shifter is none: buying the 3.3 V-native version of a sensor — which for almost every common part now exists — deletes the problem at the catalogue stage.

SituationRight tool
5 V sensor output → 3.3 V pinVoltage divider (1 k / 1.8 k)
I²C across voltagesBSS138 MOSFET module
3.3 V board → WS2812 5 V strip74AHCT125 buffer
Fast SPI across voltagesTXB0104-class IC
Servo signal from 3.3 V boardUsually direct (see below)
New design, sensor choice openBuy the 3.3 V-native part

The robot's usual suspects

Servos: powered at 5–6 V but their signal input is high-impedance and, in most modern servos, happily reads a 3.3 V pulse — try direct first; if a servo jitters or ignores commands from a 3.3 V board, a buffer channel fixes it. (Power still comes from a BEC, never a logic pin — the power distribution guide's standing rule.) Ultrasonic HC-SR04: divider on ECHO, direct TRIG, or buy the 3.3 V-capable variants. WS2812/NeoPixels: the data input wants ≥ 0.7 × its 5 V supply = 3.5 V, making 3.3 V marginal-by-design — the AHCT buffer is the known-good fix. I²C sensor mixes: one MOSFET module, both sides' pull-ups accounted for (too many parallel pull-ups from stacked modules stiffen the bus — aim for ~2–4.7 kΩ effective per side). Motor drivers: most modern driver ICs specify logic-input thresholds compatible with 3.3 V — check VIH in the table; the crusty L298N wants ≥ 2.3 V and is fine, while some MOSFET gate-drive boards designed around 5 V PWM switch weakly at 3.3 V and run hot as a result. That last failure — a driver that works but heats because its gates only half-open — is the subtlest logic-level bug on a robot.

Quick answers

Is a 1.8 V device the same story again?

Exactly the same physics one shelf down — modern IMUs and camera modules increasingly run 1.8 V cores, and 3.3 V is to them what 5 V is to a Pi. The same toolbox applies, with the divider and TXB-class shifters doing the work.

Can I use diodes to drop 5 V to 3.3 V?

A series diode drops ~0.7 V regardless of signal shape, giving 4.3 V — still over-limit — and stacked diodes make edges mushy and levels temperature-dependent. It's a supply-rail trick, not a logic-level technique. Use a divider; it's the same part count done right.

Why does my sensor work with short wires and fail with long ones?

Marginal levels plus wire capacitance and noise pickup: a signal that barely cleared the threshold on the bench loses its margin to a longer, noisier run. Proper shifting restores margin; twisted wiring and grounds per the wiring guide protect it.

Diagnosing a suspected level problem

When a cross-voltage connection misbehaves, a multimeter answers most of it. Measure the signal line's HIGH state at the receiver's pin, under real conditions: if it reads below the receiver's VIH, you've found the fault; if it reads above the receiver's absolute maximum, you've found a slower-burning one. A line idling at a strange in-between voltage (say 4.1 V on a "3.3 V" bus) usually means two devices with pull-ups to different rails are sharing it — a classic on I²C, and a sign the bus needs a proper shifter rather than shared pull-ups. For fast signals a meter shows only the average; a cheap logic analyzer or oscilloscope reveals the rounded edges of an overloaded divider or the runt pulses of a marginal drive. And when a "dead" input is suspected, test it in isolation: jumper it directly to its own board's 3.3 V and ground and read it in code — a pin that can't see its own rail has already been a casualty, and the lesson it teaches is the cost of skipping the thirty-second per-wire check.

Two questions per wire — will it register, will it survive — and four tools that cover every answer. Design the divider cases in the Voltage Divider Calculator, and for the full story of what those two resistors can and can't do, read Voltage Dividers in Robotics.