Saturday, 7 February 2015

i2c - Arduino: Reliable and practical way to connect an I²C device (1 m away)



This is a combined mechanical/electrical question. It is mainly about getting the I²C connection reliable; this question does not concern itself with the software side (i.e., how to handle an I²C fault on the microcontroller).


I have an Arduino (Pro Micro) and an I²C slave device (an MPU 6050 sensor). The Arduino is already there (happily doing other stuff, connected to a PC via USB) and around 1 m away from where the slave will be placed. The slave is the usual small board similar to https://www.sparkfun.com/products/11028. It provides some capacitors and 10k I²C pull-up resistors.


So far, so good. In the good old "get'er done" spirit, I have hacked everything together with some RJ45 connectors and a 1 m Cat 5 cable I had lying around (carrying VCC, GND, INT, I²C). It kind of works, until it does not. The I²C communication breaks down regularly (after a few hundred or sometimes thousand transactions).


I admit that I still have to figure out who exactly the culprit is; i.e., I will connect the slave directly to the PCB and see if it still happens (that would rule out the cable connection). The software side is probably fine; said problem happens with several different firmware, even the most trivial ones. I have played around with the pull-up resistors (i.e., with/without the additional Arduino pull-up resistors; and with extra external 4.7 Ω resistors), and that did not change anything. The environment is not particularly noisy, I think. I unfortunately have no equipment to measure what goes on on the lines.


Meanwhile: Can you suggest a practical and reliable way to do such a connection? What I thought about:



  • The "easiest" one would be to get a second Arduino, place it right next to the slave, connect it with USB directly to the PC; that would eliminate the whole problem, but I would really prefer not to do that if I can avoid it.

  • Try to split the SCL/SCA lines into differential pairs; I don't see how that would work with the I²C open-drain protocol though. I don't want to stick with I²C necessarily; there is no need to fix that if there is an easier alternative.

  • P82B715PN line buffers

  • Something like CAN or RS-485 would likely force me to add at least two more chips, or even more per side (for protocol conversion and drivers).



Is there a practical (for a hobbyist), simple, go-to solution for this kind of problem (which seems to crop up once in a while...)? I'm really open to anything here.


I checked my cables... I previously had (INT+nothing), (SCL+nothing), (SDA+nothing), and (VCC+GND). I have added the GND to all pairs, so it's now (INT+GND), (SCL+GND), (SDA+GND), and (VCC+GND) as per @FiddyOhm 's answer. Unfortunately, no change whatsoever :( That wasn't it.



Answer



Your 1 meter connection should work fine if you take the following precautions for your particular situation.


A. A good ground connection between the two boards is essential. You may be able to fulfill this requirement with your CAT-5 cable. If you run into problems after trying all of the following, run an extra 20 AWG wire along side the CAT-5 cable ( tie wrap it in one or two places.


B. It is best that you use one source of Vcc ( I assume this is 5 volts in your application). You imply this in your description with the inclusion of "Vcc" in the CAT-5 wiring description. The worst thing you can do in this respect is to tie two separate sources of Vcc together with the cable. Indeed, this may be your whole problem to begin with. Voltage drop across the 1 meter cable carrying the Vcc could be an issue. You will need to test this with a DVM at the load end of the cable to make sure it is in range of your peripheral device.


C. DO NOT twist I2C Clock and Data lines together! Twist each with a ground wire, but not with each other. In other words, choose the twisted pairs within your CAT-5 cable carefully. Allow the ground wires to serve double duty as additional power grounds as well - i.e. connect them to GND on the respective boards at both ends. (If problems persist, try clipping these lines one-by-one.)


D. DO twist Vcc and GND wires together. If you have two extra pairs after doing "C" above, use two twisted pairs of Vcc & GND and connect them in parallel at both ends ( i.e. on the respective PCBs. )


E. Use the smallest pull-up resistors possible. This is likely 1.0 K. If you have an O-Scope, you can perform a simple test to determine the lowest practical resistor for your specific application. Scope the signals as the app is running and decrease the resistor value until the signal shows signs of being loaded down below acceptable logic levels ( approx. 3.2 volts for a 5 volt system). You may find that CLK and DATA will tolerate different values of resistors, this is OK.



F. If communication speed is not an issue, run the I2C link at as low a frequency which is practical for your application. 100 KHz clock is generally the "low" frequency for I2C, but it can run at any speed because it is a synchronous protocol. I have run I2C at 1 KHz in some circumstances.


G. Make sure you have adequate Vcc-to-Gnd bypass caps at both ends of the cable. One 4.7 tantalum and one 0.1 or 0.01 mfd at least on the load end is about right. If worst comes to worst, repeat these caps at the supply end of the cable.


H. If all of this doesn't work, as a last Act of Desperation, slice open the CAT-5 cable and separate the various twisted pairs from each other about 1 inch. Don't untwist the wires, just separate the pairs. Hold them apart with masking tape or similar. If this works, you are dealing with some sort of inter-pair coupling problem (not likely in my experience with this length of cable). In this case you will need to shield the Data and Clock twisted pairs (each twisted pair within its own shield - e.g. braid you scavenge from a coax cable or microphone cable). Ground the shields only at one end, preferably the Arduino end.


If these points don't solve the problem, I'd guess there's something unusual about your set-up, or something you are not knowledable enough to recognize as a problem, and are therefore not describing in your otherwise excellent description of your set-up and problem.


No comments:

Post a Comment

arduino - Can I use TI's cc2541 BLE as micro controller to perform operations/ processing instead of ATmega328P AU to save cost?

I am using arduino pro mini (which contains Atmega328p AU ) along with cc2541(HM-10) to process and transfer data over BLE to smartphone. I...