How to disable internal Arduino ATMEGA pullups on SDA and SCL with I2C bus

Last updated on Wed, 2011-12-07 13:50. Originally submitted by fabio on 2011-06-23 00:29.

Wire, the library available in the Arduino apis to communicate with devices on the I2C bus, as of the 022 version of the Arduino IDE, by default enable the internal pullups of the ATMEGA microcontroller.

As all 16MHz ATMEGA runs at 5V this means that with pullups enabled signals will have a 5 volt as logic level. Unfortunately, as many I2C devices runs at 3 Volts and aren't 5Volts tolerant, sending 5V signals to them is clearly a very bad idea. You may shorten your device life or even damage them irreparably.

As Wayne demonstrated with practical scope tests, internal pullups performs extremely bad in terms of signal quality and bus speed.

I personally don't understand why the guys who wrote Wire enabled the internal pullups by default, that's why I opened an issue on Arduino bug tracking website.

Unfortunately, it looks that not many people care about this issue so we probably will have this issue for some time more.. meanwhile you have two possibilities.

In sketch program code disabling

Just use the following code to disable the internal pullups in any code after you initialized Wire (using Wire.begin()). This is a good solution to implement in your Arduino library code.

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
  #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega328P__)
    // deactivate internal pull-ups for twi
    // as per note from atmega8 manual pg167
    cbi(PORTC, 4);
    cbi(PORTC, 5);
  #else
    // deactivate internal pull-ups for twi
    // as per note from atmega128 manual pg204
    cbi(PORTD, 0);
    cbi(PORTD, 1);
  #endif

In Wire library disabling

Another possibility is to modify the Wire library of your Arduino environment install so that it won't enable the pullups by default anymore.

If you are using Arduino-023 or previous, just find the Arduino IDE files and open the file twi.c under libraries/Wire/utility/. Locate and comment out or delete the following lines:

#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega328P__)
    // activate internal pull-ups for twi
    // as per note from atmega8 manual pg167
    sbi(PORTC, 4);
    sbi(PORTC, 5);
  #else
    // activate internal pull-ups for twi
    // as per note from atmega128 manual pg204
    sbi(PORTD, 0);
    sbi(PORTD, 1);
  #endif

Instead, if you are using Arduino 1.0 IDE or later, search for the following lines and comment them out:

  // activate internal pullups for twi.
  digitalWrite(SDA, 1);
  digitalWrite(SCL, 1);

Your pullups will be disabled by default now.

Posted in:

Very helpful

Submitted by Dominic Clifton (not verified) on Tue, 2013-02-12 00:39.

Thanks for taking the time to post the information and raise the bug report.

I was getting really bad communication errors between an Arduino (home made ATMega328 board) and a Raspberry Pi and disabling the Arduino's Pull Up resistors after Wire.begin() fixed the problems I was having.

I was struggling to find the cause by looking at code and I have no 'scope here.

not work on Arduino Mega2560

Submitted by CAF (not verified) on Tue, 2012-10-30 20:09.

I tried this solution on Arduino Mega2560 (Sda/Scl i2c on pin 20/21) but dont work, this pin is ever to 5V.... :-(

I reply to me: Atmega2560

Submitted by CAF (not verified) on Wed, 2012-10-31 00:14.

I reply to me, posted also in the arduino forum:

Wow ! after 2 days i found the problem, the Mega2560 board have 2 hardware resistors pulled to +5v , therefore is impossible to disable it by software, you can see in the schematic here http://arduino.cc/en/uploads/Main/arduino-mega2560_R3-schematic.pdf in the upper right.

On the board the resistors is a four-pack right to the On led.

This has caused several problems, because I disabled the pull-up in Wire.h library(without effect), and pull up I2c with external resitors to +3v3, but with the unknowed resistors to +5v I added serial resistors from 5v to 3v3 line via SDA/SCL, therefore extra volts to the 3v3 line(4,5v mesured) , and generate unstability.
Caution with Mega board an 3v3 devices, is easy to have tosted....

I hope this help to others.

Thanks.

That is because the Mega

Submitted by fabio on Tue, 2012-10-30 20:27.

That is because the Mega board has on board pullups to 5V. You will have to unsolder them in order to disable them.

internal pullups

Submitted by as3.1415rin (not verified) on Thu, 2012-07-19 21:39.

as far as I understand, the 5V/3.3V is the only reason to switch them off. if that's not the point, internal + external pullups should be fine, then the activated internal ones are not doing any damage

Extremely helpful

Submitted by Vincent (not verified) on Sat, 2012-02-11 04:21.

I had lots of trouble to communicate through I2C with my Arduino Mega2560. The documentation is so patchy. Turn out the pull-up resistors' value, both internal and external, was the main issue. Thank you so much for the information.

please help....

Submitted by Anonymous (not verified) on Sun, 2012-07-29 17:11.

hey
i also facing same issue ...i am using twi in at2560.i ma using two 2560 and try to make them communicate...leaving the rest of d code alone...i am not getting this pull up part shud i disable or enable internal pull ups and do i have to attach external resistor then what shud b the value of resistance ...pls pls help .....

TWI pull-ups hardware in Arguino Mega's, but...

Submitted by Arty (not verified) on Sun, 2014-01-12 14:16.

It's true that each SCL/SDA (PD1/PD0) pin have a hardware 10KR resistor.

Schematics show that clearly : +5V ---> 10KR ---> SDA/PD0, same thing for SCL/PD1 pin.

These can't be disabled by means of software, but one might think about another approach using the "equivalent resistor" thing using 2 resistors, parallel wired.

So, it MAY be possible to add another resistor to get a smaller equivalent resistor value.

Does anyone remember that simple electronics thing ? Req = (R1*R2)/(R1+R2)

Supposing you want to get a "global" 1.5KR for each SDA or SCL pin, the equivalent can be 1.68KR (1KR + 680R, in series). This gives an equivalent resistor of 1.438KR, close enough to the wanted 1.5KR .

Maybe something like this :

+5V --> 10KR ---> SDA/PD0 (original hardware pull-up res.)
+5V --> 1KR --> 680R --> SDA/PD0 (added pull-up, parallel)

This is only theory, but seems to make sense some way.

Maby yes maby not, it dependent

Submitted by xpts (not verified) on Sun, 2014-06-01 12:48.

Hello, i come here from the search in google for an away to disable the internal pullup, in my case i am using a teensy 2.0 and it work really great thx for the info help now, the theory of 2 resistor could work but for example i am using a mpu6050 thats it a 3.3v chip, you are assuming both 5v, so for case where you need 3.3v would not work as the description thus why this post even exits.

very helpful~~thks~~:)

Submitted by xzp21st (not verified) on Tue, 2011-07-05 11:38.

very helpful~~thks~~:)

Post new comment

The content of this field is kept private and will not be shown publicly.
If you have a personal or company website insert its address in the form http://www.example.com/ .
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <pre> <small> <del> <img> <h2> <h3> <h4> <b> <video> <sub> <sup>
  • Lines and paragraphs break automatically.
  • Images can be added to this post.
  • You may use [inline:xx] tags to display uploaded files or images inline.
  • You may insert videos with [video:URL]
  • Each email address will be obfuscated in a human readable fashion or (if JavaScript is enabled) replaced with a spamproof clickable link.

More information about formatting options