I2C Long cable

So i've been working in the past just few simple projects with I2C between 2 or 3 arduinos
without any pull up resistors just simple 10cm jumper wires thru arduinos.

Lately I got a project in my mind and came up to use I2C again and because I'm not 100% familiar
or experienced with I2C i'd like to ask some questions about what im trying to build.

I want to use more than 5 arduinos thru I2C Single Master and many slaves the problem is that
i saw many people talking about the length of the wire I2C can use, and my question is how long
maximum the wire can be to use I2C between 2 or many arduinos?

I'm thinking to use like 1~2meters of wire, in the picture bellow you can see approx what I want to
build.

So is that possible? Ideas/suggestions.

D.60

I2C is open collector. It won't work without pullup resistors. If it's working for you it must be because you are using some modules that have the pullups built onto the board. Turn off the power and measure the resistance from SDA to 5V and SCL to 5V. Post the values.

A meter should be fine.

google i2c extender if you need more length or it does not work.

Maybe a silly question, but why don't you use RS485 for communication between Arduinos (sensors is a different story)? It was designed for long distances.

raschemmel:
I2C is open collector. It won't work without pullup resistors. If it's working for you it must be because you are using some modules that have the pullups built onto the board. Turn off the power and measure the resistance from SDA to 5V and SCL to 5V. Post the values.

Not according to the master/slave tutorial; no pullups for unknown reason but it does work :wink: I did not look at the library; it might enable the internal pullups for the slave?

I2C is open collector. It won't work without pullup resistors. If it's working for you it must be because you are using some modules that have the pullups built onto the board. Turn off the power and measure the resistance from SDA to 5V and SCL to 5V. Post the values.

I don't remember putting a pullup resistor, i made homemade PCB's and they worked preaty good without
pullup resistors, no joking.

A meter should be fine.

Yea but I'm not sure yet i will need only a meter or more so I want to find a way to be safe with my
project not to redo everything :smiley:

google i2c extender if you need more length or it does not work.

I didn't knew that kind of things exist :smiley: it's like power line amplifiers, nice I know how they work
theoretically but need to give a better look on them so see exactly how they work.

Maybe a silly question, but why don't you use RS485 for communication between Arduinos (sensors is a different story)? It was designed for long distances.

Never worked with it so I don't know many things about it.

Looking at it right now I understand why people use it, double shield, nice way / protection from noise
and enough cables to work with, I will keep it in mind about this cable.

Not according to the master/slave tutorial; no pullups for unknown reason but it does work :wink: I did not look at the library; it might enable the internal pullups for the slave?

I build my own PCB's 3x atmegas connected together without pullup resistors for some reason it worked
probably internal pullups not sure, but I will keep in mind to put pullups next time.

Btw a question:

How exactly I determin the value of the resistors by the length of the wire?

Giving a 2nd look to I2C extender will be nice to use it because in that way i can make my modules
portable and plug and play any time.

D.60

Google "I2C - LEARN SPARKFUN"
Read the explanation of "bus contention"
Would a company the size if Sparkfun recommend pullup resistors if they weren't necessary ?
Would a company the size of Texas Instruments have a Bus Pullup Resistor Calculation tutorial if pullup resistors were unecessary ?

OR

"I2C BUS PULLUP RESISTOR CALCULATION TEXAS INSTRUMENTS"

Technically , it's called "open drain" but if you answered "open collector " on an interview test it would be considered close enough.

It's possible the Wire Library has Internal pullups built into the library code.

Standard value is 4.7 k ohm

Google "I2C BUS PULLUP RESISTOR CALCULATION TEXAS INSTRUMENTS"

It's possible the Wire Library has Internal pullups built into the library code.

From twi.c (included by the Wire library):

void twi_init(void)
{
  // initialize state
  twi_state = TWI_READY;
  twi_sendStop = true; // default value
  twi_inRepStart = false;
  
  // activate internal pullups for twi.
  digitalWrite(SDA, 1);
  digitalWrite(SCL, 1);

That would explain why it worked for the OP.

Hi!

I have a Rasperry Pi connected to a Arduino with a 6 meter long cable (shielded network cable).
The cable is obviously too long and I get a lot of errors when transfering over I2C.

I have solved it in software with a CRC. If the CRC is wrong I just send the data again.

/Olof

I wonder if anyone has tried using RS485 to extend an I2C bus. Not sure how that would work out.
The CRC thing is a great idea. Do you have any links people can use to learn how to do that ?
(people who aren't programmers)

I don't remember from which site I borrowed the CRC8 function.
I have not seen any guide how to use a CRC.

But basicly you only do the following:

Sender

  1. Construct a "data package"

unsigned char DataToSend[3]; //Some bytes to send, fill with data

  1. Use the CRC8 function (or CRC16) to calculate the CRC.

uint8_t CRC = CRC8(DataToSend, sizeof(DataToSend));

  1. Send data + CRC byte with I2C or other proctol.

Receiver

  1. Get data package + CRC byte.

  2. Compare the CRC

if (CRC == CRC8(RecivedData,sizeof(RecivedData))) //Compare CRC, if true everthing is ok

uint8_t CRC8( unsigned char *data, int len)
{
  unsigned crc = 0;
  int i, j;
  for (j = len; j; j--, data++) {
    crc ^= (*data << 8);
    for (i = 8; i; i--) {
      if (crc & 0x8000)
        crc ^= (0x1070 << 3);
      crc <<= 1;
    }
  }
  return (uint8_t)(crc >> 8);
}

/Olof

You can also use / adjust the crc example from the eeprom crc tutorial

There is more than one I2C standard.
The common/old one is 3mA/400pf.
An Arduino can do the enhanced I2C FM+ standard (30mA/4000p).
Read the datasheets of the slaves.

3mA is related to the pull up resistor (combined minimum resistance of 1.67k).
400pf is related to the cable + device capacitance.
If you use low capacitance cable, you can go further.

I use ~6meters of CAT-6 (53pf/m) between a Mega and two PCA9685 chips 24/7 without any hickup.
Clock and data are (must be) on separate pairs, only shared with ground (or VCC).
Leo..

Thanks for the CRC info !