2

How do you do this? I've been digging around and I can see that I should do this and supply my own external pull up resistors but I don't know exactly how to disable them. The pages I've been reading never explicity state how.

I'm trying to enable I2C between a leonardo and an uno, but I think the i2c bus is slowing down considerably because of the internal pullups. I want to switch to two 4.7k resistors but I can't figure out how to disable the internal ones. I know that the Wire library enables the internals by default, but how do I edit the library or disable the pullups in my sketch?

Maybe I just haven't been reading the right forums or articles, but if anyone could point me in the right direction that would be much appreciated.

EDIT: So the problem is probably with my setup or code, I'll put it down here. Everything I have before setup is importing libraries and variables like my mac, ip, placeholders for output, pwm, etc.

Master:

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  while(!Serial){
  }

  Wire.begin();

  Ethernet.begin(mac, ip);
  delay(1000);

  server.begin();
  if(server.available()){
    Serial.println("Client Available");
  }
}

void loop() {
  // put your main code here, to run repeatedly:

  ethernetwrite();

}

void ethernetwrite() {      
  EthernetClient client = server.available();
  while(client) {
    if(client.find("P")) {
      output = client.parseInt();
      pwm = client.parseInt();

      Serial.println("Begin Transmitting");
      Wire.beginTransmission(14);
      Wire.write(output);
      Wire.write('\t');
      Wire.write(pwm);
      Wire.endTransmission();
      Serial.println("Done Transmitting");

      Serial.print(output);
      Serial.print('\t');
      Serial.println(pwm);

    }
  }
}

Slave:

void setup() {
  Wire.begin(14);
  Wire.onReceive(wirewrite);

// *   - Base frequencies:
// *      o The base frequency for pins 3, 9, 10, and 11 is 31250 Hz.
// *      o The base frequency for pins 5 and 6 is 62500 Hz.
// *   - Divisors:
// *      o The divisors available on pins 5, 6, 9 and 10 are: 1, 8, 64,
// *        256, and 1024.
// *      o The divisors available p1on pins 3 and 11 are: 1, 8, 32, 64,
// *        128, 256, and 1024.

    // Leg 1
    pinMode(leg[1], OUTPUT); setPwmFrequency(leg[1],8); analogWrite(leg[1], offset);

    // Leg 2 
    pinMode(leg[2], OUTPUT); setPwmFrequency(leg[2],8); analogWrite(leg[2], offset);

    // Leg 3
    pinMode(leg[3], OUTPUT); setPwmFrequency(leg[3],8); analogWrite(leg[3], offset);

    // Leg 4
    pinMode(leg[4], OUTPUT); setPwmFrequency(leg[4],8); analogWrite(leg[4], offset);

    // Mirror
    pinMode(leg[0], OUTPUT); setPwmFrequency(leg[0],clkdivisor); analogWrite(leg[0], 255);
}

void loop() {


    int time = 10;
    time = time*128/clkdivisor;

    // box(time, 255, 1); // box(delay time, radius pwm, pwm step size);
    // autodisplay(); 
    updateL();

}



void updateL(){
  if (output == 0) pwm = 255 - pwm;
  switch (output) {
    case 1: pin =  3; break;
    case 2: pin =  9; break;
    case 3: pin =  10; break;
    case 4: pin =  11; break;
    case 0: pin = 5; break;
  }
  //if (output < 5) {
    analogWrite(pin, pwm);
  //}
}

void wirewrite(int numBytes) {
  String message;
  while(Wire.available()>0) {
    char c = Wire.read();
    message.concat(c);
  }
  output = Wire.parseInt();
  pwm = Wire.parseInt();
}

When I send data to the master, on the serial monitor it freezes in the first wiring transmission or in the next few, and my slave doesn't seem to respond to the message being sent over i2c. My controls for my device and setup worked prior to my attempts with the Wire library, so there's no problem there.

EDIT: I also am sending a message that looks like this: "P1 103" every .4 seconds or so, but I usually can't get past the first transmission between the arduinos

4
  • 1
    Why bother to disable the internals? Say the internal is 50K - leaving it enabled and adding the 4k7 would end up with an equivalent of 4.2962K
    – Majenko
    Jul 14, 2015 at 20:57
  • I think the i2c bus is slowing down considerably because of the internal pullups; I2C is clocked, so it's speed is not dependent on the external resistor. You have to set the I2C clock to a higher frequency, if you want more speed.
    – Gerben
    Jul 15, 2015 at 8:18
  • 1
    Just out of curiosity, why do you want do (disable the resistors)? I think the i2c bus is slowing down considerably because of the internal pullups - no, it isn't. if anyone could point me in the right direction that would be much appreciated - if you could post your code that would be much appreciated.
    – Nick Gammon
    Jul 15, 2015 at 10:29
  • 1
    My bad then, I was misinformed or just misinterpreted what I was reading. I was trying to read up on i2c for a project I'm working on and I'd been seeing a lot of disabling of the internal pullup resistors for people's projects involving i2c, sorry for the ignorance
    – David Tran
    Jul 15, 2015 at 12:59

2 Answers 2

4

Let's go back to basics. A low-value pull-up resistor actually improves the shape of the I2C clock and data.


One internal pull-up:

I2C with one internal pull-up resistor


Both ends with the internal pull-up:

I2C with two internal pull-up resistors


10 k external pull-up:

I2C with 10 k external pull-up


4.7 k external pull-up:

I2C with 4.7 k external pull-up


2.2 k external pull-up:

I2C with 2.2 k external pull-up


As Majenko pointed out, leaving the internal pull-ups enabled would give you a pull-up between 4.7 k and 2.2 k. And as my screenshots show, that is perfectly acceptable.

In fact, it is probably better. See the nice square signals?


So your hypothesis that the pull-up is responsible for it running slowly is not supported.

You need to post your code, and other details, such as the length of the cable runs.

I think the i2c bus is slowing down considerably ...

What do you mean "slowing down"? Compared to what? What are your figures? What is the transmission time? What do you expect it to be? Some facts please.


Reference

My page about I2C

4

From the datasheet:

Note that the internal pull-ups in the AVR pads can be enabled by setting the PORT bits corresponding to the SCL and SDA pins, as explained in the I/O Port section.

To disable the internal pull-ups:

digitalWrite(A4, LOW);
digitalWrite(A5, LOW);

or

digitalWrite(2, LOW);
digitalWrite(3, LOW);
2
  • 2
    It looks like SDA and SCL are constants, so safest would be to do a digitalWrite(SDA, LOW); digitalWrite(SCL, LOW); to avoid worrying about which pin they are on which board.
    – Nick Gammon
    Jul 14, 2015 at 21:55
  • Just to clarify, as the quote from the datasheet talks about enabling the pullups: These commands disable the pullups. Jul 14, 2018 at 23:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.