In this Enginursday, we'll explore some of the problems that can creep up when connecting I2C devices
When it comes to microcontrollers, it’s easy to run out of IO pins before you run out of programming space. Back in 1982, NXP Semiconductor (formerly known as Philips Semiconductor) came up with a solution called Inter-Integrated Circuit, or I2C. With this technology, designers are able to connect up to 127 devices using just two pins for clock and data. I2C not only frees up I/O pins but also maintains the measurement from the source to the device reading the measurement. With analog outputs, the output is susceptible to noise, which will need to be filtered through hardware or software. Because I2C is digital, noise can often be ignored, but that doesn’t mean it’s problem free, and there are design considerations that need be addressed — no pun intended.
One of the first things to look at is the speed to communicate between the microcontroller, known as the master, and the device that is being controlled, known as the slave. For Arduino, the Wire library defaults to 100kHz, but depending on the master and the slave device, you could communicate as low as 10kHz (low-speed mode), to as fast as 3.4MHz (high-speed mode). The faster you communicate, the less amount of capacitance is tolerated on the line, due to the increased rise time of signals. The standard maximum capacitance for I2C lines is around 400pF.
What creates the capacitance, though? There is some capacitance from the devices themselves (around 20pF), but the bulk of the capacitance comes from the wires to connect the devices together. On a circuit board, capacitance isn’t that big of a concern, but there is some created just by having the traces run closely to the ground plane. On cables, however, you could create 40–120pF per meter. For example, with CAT5 cable used for wired internet connections, the capacitance must not exceed 50pF per meter. Shielded cable is higher at 114pF per meter.
What does this mean for the real world? I set up a test using two cables. One was 6 inches long, and the other was 6 feet long. In order to see the effect of cable length more clearly, I removed the pull-up resistors that are normally required for I2C communication.
With the 6-inch cable, the SDA line (in yellow) sort of looks like a square wave with a rise time of 3.8us. In the 6-foot line, however, the data line looks more like a saw-tooth wave than a square wave with a rise time of around 11us. This is a result of the capacitance of the wires, and grounding the other wire of the twisted pair from the CAT5 cable would increase the rise time even more.
The second half of the design is the pull-up resistors used. I2C uses open-drain technology, meaning that the devices are able to pull the signal down to ground, but are not able to pull the signal high. For that reason, all of our boards that use I2C have pull-up resistors on them. The resistors need to be of a certain value, though. If the resistor value is too high, the rise time of the signals can be too large to be read.
6-inch cable with a 100 kΩ pull-up resistor
6-foot cable with a 100 kΩ pull-up resistor
And if the value is too low, oscillations known as ringing can be large enough that the master or slave devices misread the data on the lines. Too small of a resistor value can also prevent the signals from reaching a low enough voltage to be read as a logic 0.
6-inch cable with 100Ω pull-up resistor
6-foot cable with 100Ω pull-up resistor
Looking at the waveforms, we can see the ringing when the signals switch from low to high, as well as some crosstalk on the data line when the clock line switches. We can also see that when the signal is low, the voltage is around 1.2V. If our sensor were powered off of 3.3V, that voltage could be too high to be read as a logic 0.
Here at SparkFun, most if not all of our boards use 4.7kΩ pull-up resistors. The value doesn’t need to be too specific, 1kΩ to 10kΩ would work just as well. With 4.7kΩ, though, you can connect a couple devices together without having to disable the pull-ups. But if you’re planning on using a few or more boards on the same I2C bus, make sure you disable the pull-ups on all but one of the boards using a hobby knife.