5V Arduino with 3V I2C device


Since I²C is an open-drain bus, wouldn't it be easier to pull the lines up to 3V manually (using external pullups) instead of using a complex bidirectional level shifter contraption on every line?

All I'd need to do is to disable the internal atmega pullups (through PORTD).

Will that be enough to interface seamlessly to a 3V device?

EDIT: Atmega with Vcc=5 V will register 3V as high (threshold being 2.65 V).

Cheq the I2C device max voltage ratings, but i think that you do not have any issue about it. I was at the same situation and i use 5V to conect the I2C pullup-resistors.

Best regards

open-drain bus...pull the lines up to 3V

But for parts of the cycles when a 5V Arduino board is driving the lines, the outputs go from zero to 5 Volts (hard-driven), so it's not just a matter of pull-up resistors.

What I2C device are you using?

If the target device is working with 3 V or 3.3V Vcc and it can't tolerate 5V on its I/O pins, then you should use a level shifter on each of the two lines.

For Arduino 2-wire speeds, the level shifter can be as simple as a single MOSFET transistor with pullup resistors on each side. Reference: http://www.nxp.com/documents/application_note/AN10441.pdf

You can get a 2N7000 in a TO92 package, convenient for breadboarding or hand wiring.

Or you can buy a small module from sparkfun or other vendors..



davekw7x, what do you mean by "when a 5V Arduino board is driving the lines"?

I²C is open-drain, meaning the client/server can only pull the line low (ground it with a transistor). The only "driving" there is is done using pull-ups. ATMega has internal pullups (to Vcc, 5 V in my case), but those can be disabled.

My question was when these internal pullups (PORTD bits 0 and 1) are disabled (PORTD = 0), will it be enough to ensure safe communication? Are there any other voltage sources that I should know about before I fry my magneto? :-)

I'm interfacing with the HMC5843 triaxial magnetometer.

Atmega with Vcc=5 V will register 3V as high (threshold being 2.65 V).

Where’d you get that information?

The datasheet (ATmega 328 Rev. 8025I–AVR–02/09 p 313 “Electrical Characteristics”) says that VIH min is 0.7Vcc, which is 3.5V for a 5V arduino.


@Tare Land:

davekw7x, what do you mean....

My statement was wrong. In I2C mode they are open-drain and do not drive outputs to +5V. I regret the error.



In the 0016 version, the pull ups in I2C could not be disabled. You need the level shifter if your device is not 5V tolerant.

glt, I'm not using the Wiring library at all, so this doesn't apply to me. I'm using avr-libc directly.

kg4wsv, wow, that's interesting. You're right that the datasheet indicates the voltage should be higher. I have however successfully interfaced the magnetometer (running at 2.5 V) with no level conversion. It's running right now. Could it be that there are tolerances built in?


If it works now, it’s pure luck. It may not work if it gets cold. Or hot. Or old. Or attached to a different IC that’s a little less sensitive.

That 0.7Vcc level specified in the datasheet is the minimum voltage that will always provide a logic high over the operating conditions specified (Vcc, temperature, etc).


The datasheet says it's 0.6*Vcc for Vcc=5 V, so maybe that's why I'm getting good results right now. The real Vcc is around 4.7 V, which would push the threshold value down to 2.8 V, and maybe that's why it's working (at 2.5ish... slightly higher).

I'll boost the input voltage to 3V3, that should improve the stability, no?

It's never been clear to me what it really means to be "not 5V tolerant" in the context of pullup resistors.

Would a 3V3 device be unhappy if exposed to 5V via 1 ohm resistor? Probably.

But via a 10M resistor? 100M? Air?

So what about the 4k7 that is typically used on an I2C line?