12c communication over long wires?

I have been working on a school project for the past year involving a submersible robot. There are 3 wires from the controller (Raspberry pi) on the surface to the robot (arduino uno) in the water.

In testing, all of my electronics have worked perfectly. (using 3 small wires as the cable between the ROV and the controller). However, when I increased the length of wires to about 20 feet communication between both boards stopped.

The weird part is that the connection works when one long wire is used with one short wire. (regardless of which wire or pin is used).

It should be noted that the Raspberry pi is the master and the Arduino is the slave device so no logic level converters are involved.

I find this problem pretty funky and i'm not sure what to do from here so any ideas are welcome.

Thanks in advance for ideas or solutions.

I believe the issue is related to your overall communications length...

length = added capacitance, and I2C busses have a maximum capacitance they can tolerate at certain speeds.

However before we get there...

What speed are you running this at?
Are you using any sort of twisted or shielded wires?

Check out this post here for more information:

Thanks for the help cbocatto

I'm using twisted wire salvaged from a CAT5 cable.

I'm running at 9600 baud. From what I've read, that is a pretty stable speed, and 20 feet doesn't seem like it should have that much of an impact.

The problems with protocols like I2C include the fact that they're not differential and are thus susceptible to noise, even when run along twisted pair (which is kind of pointless since the signals are not differential...). As well, being single-ended they rely on the transmitter and receiver being at the same ground potential. Long wires can cause voltage drops, noise can cause ground bounce etc.

As well, the pins on a microcontroller don't typically have the same sort of drive capability (so falling edges get sloppy with added capacitance) and ESD-protection that a dedicated line driver would so the pins are at risk unless you add external TVS diodes. I2C relies on pull-up resistors so rising edges can be degraded by the inductance and resistance of longer lengths of cable.

IIC was intended for intra-board or intra-system comms, not distance communications. If it works for you, cool. But keep in mind it may not be reliable.

Thanks Blackfin this answers my questions.

I think pull-up resistors are what i'm missing. The cable will be completely submerged underwater so hopefully that will also help shield the wires from interference .

Chucko11,
Are you using I2C or serial? You asked about I2C but this:

I'm running at 9600 baud.

Suggests serial.
I would expect serial to work over 20 feet.
I have I2C working over about 30m. Many people on here will tell you I2C won't work over 30m. Well, it might not have been designed for 30m, but if you run it slowly it works perfectly well.

I²C extender board:

Would using screened cable help?

I seem to remember that only one end of the screen should be connected to ground?

This might have been to avoid circulating currents in mains voltage applications though.

877:
Would using screened cable help?

No. The added capacitance (wire to shield) could make things worse.

Best to use a twisted pair for SDA/GND and a twisted pair for SCL/GND.

I suppose you have the right value pull up in place, at both ends.
Don't know the limitations of a Pi (standard I2C or FM+), and I assume the Pi is 3.3volt logic.
Then both sides need to be pulled up to 3.3volt (also the 5volt UNO).
Minimum resistor value (max pull up) could depend on the Pi. The Arduino can do FM+ (30mA/4000pf).

You could have had better answers if you would have posted according the forum rules.
You can find them on top of every main page.
Leo..

Wawa:
No. The added capacitance (wire to shield) could make things worse.

Best to use a twisted pair for SDA/GND and a twisted pair for SCL/GND.

I suppose you have the right value pull up in place, at both ends.
Don't know the limitations of a Pi (standard I2C or FM+), and I assume the Pi is 3.3volt logic.
Then both sides need to be pulled up to 3.3volt (also the 5volt UNO).
Minimum resistor value (max pull up) could depend on the Pi. The Arduino can do FM+ (30mA/4000pf).

Makes sense regarding the screening. Glad I read this.

Some of the sensors I used for i2c have their own onboard pull up resistors, worth checking.

PS what is FM+ ?

Chucko11:
Thanks Blackfin this answers my questions.

I think pull-up resistors are what i'm missing. The cable will be completely submerged underwater so hopefully that will also help shield the wires from interference .

But will add tons of extra capacitance and loss. Saltwater in particular is not compatible with ordinary
wires, you require silicone insulation as hydrogen and choride ions diffuse through most plastics and attack
the copper.

So what are the alternatives to i2c over distance?

I’m thinking maybe a wireless link, not sure how that would fare underwater.

For non-underwater applications, would either a non-i2c sensor, other wired protocol or a slave arduino connected wirelessly be the option?

Wireless doesn't work underwater. At least not the wireless hardware you can get your hands on. Military technology can send data to submerged submarines but the baud rate is extraordinarily low.

You can get I2C "booster" chips that will push the signal over longer distances. I've tried them but quickly abandoned the idea for other reasons.

I2C is particularly difficult to boost because it's bidirectional. Any booster you use must be able to recognise which end is pulling the line down and send that information to the other end. By the time you've implemented that, you may as well implement some other recognised standard communications. RS232 can go hundreds of meters and RS485 goes kilometers, with a little bit of care.

The real difficulty I've seen with I2C is the cross-capacitance. Viewing the signals on the scope, you see that each transition on the clock drags the data line with it. This can be avoided by not putting the wires close together. (Likely why the experiment with one short wire worked.) If I'm putting I2C or SPI onto a ribbon cable, I always put a ground or power wire between clock and data. That acts sort of like a barrier. Never ever put clock and data onto one pair of a twisted-pair cable.

For the original request, I would recommend RS232 Serial. Get MAX232 converter chips for both ends of the long wire. Then read Robin2's post on serial communication between Arduinos. You can test without the MAX232 chips - you may find that it will work over the desired distance without the converters. Make sure to test in the presence of interference - something like the motor on your support boat might interfere with the communications.

I've tested I2C over a Cat5 ethernet cable to 75 feet. I had the SDA and SCL each twisted with a ground wire (but reading above, maybe it is useless to do so?) It repeatedly failed until I had pullup resistors at both ends of the cable run. Also, the maximum speed was something like 300 kHz, but using a slower speed worked well and seemed reliable.

This might be an option to boost reliability: SparkFun QwiicBus - EndPoint - COM-16988 - SparkFun Electronics

Also, it might be helpful to look into other protocols: CAN bus, RS 485, ect. I don't know enough about these to recommend one, but there are transceivers available that can interface with an arduino.

Serial over 485 might the way to go.

877:
Some of the sensors I used for i2c have their own onboard pull up resistors, worth checking.

PS what is FM+ ?

But this is a master/slave situation (Pi/Arduino), so you must use pull up.
Equal pull up on both sides also helps terminating the cable (reflections).

There is more than one I2C standard. The original one is 100khz/400pf/3mA.
FastMode+ (FM+) allows for 4000pf/30mA wiring/pull up.
That can be used to increase speed (400khz and up) and/or cable length/capacitance.
Not every device can do FM+. Read the datasheets.
Leo..

RS485 gives the distance and the ability to add addressable devices to the RS485 bus (like I2C)

Hi,
I think you miss the purpose of I2C, it is supposed to be a local, almost PCB level two wire comms system.
Not designed for long, capacitive cables.

RS485 may be best as it uses balanced current transmission and is designed for long distance cable use.

http://www.windmill.co.uk/rs485.html

Tom.... :slight_smile:

So changing the electronics setup isn’t really an option for me at this point, although it would be the ideal solution.

Maybe I could add something to the software? I don’t know exactly how this would be done but it would look something like this:

if (raw signal < .5V){
raw signal = LOW;
}
else { raw signal = HIGH; }

Essentially the same function of a pull up but software based.

Chucko11:
So changing the electronics setup isn't really an option for me at this point...

Then forget about the project.
There is no software replacement for I2C pull up resistors for that distance.
I2C is a short-distance protocol, and you're already pushing it with 20 feet of wire.

Do you know if there are already any resistors in place, and what their values are.
Without them, I2C over that distance shouldn't work at all.

What is the minimum distance you're aiming for.
Leo..