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:

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.

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> <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