4
\$\begingroup\$

I have 64 i2c devices wired together. They all seem to work correctly until randomly between 30s-1m of sending signals, the bus will hang.

Here is how I have it wired:

bus topology diagrams

It's currently wired as diagram A. Do I need a configuration like B? Is there anything else that would cause a device at random and a random time to pull the bus low?

\$\endgroup\$
4
  • 4
    \$\begingroup\$ That's a lot of devices for one bus. How fast are you trying to run it, and what kind of pullups are you using? \$\endgroup\$
    – Dave Tweed
    Dec 26, 2012 at 19:00
  • \$\begingroup\$ I agree. That's a lot and it might cause tremendous loading. Have you tried running a logic analyzer? You might have to resort to using I2C expanders to separate them. What kind of devices are they and at what speed are you running them? \$\endgroup\$ Dec 26, 2012 at 19:04
  • \$\begingroup\$ What value pull ups are you using, and have you measured the capacitance on the bus? \$\endgroup\$
    – Passerby
    Dec 26, 2012 at 19:10
  • \$\begingroup\$ Each device is blinkm type unknowndomain.co.uk/blog/2009/02/19/…. Each blinkm is mounted on a pcb. I thought that the Arduino had internal pull-up resistors to take care of i2c. Do I separate resistors on the SCL and SDA? Still all new to this stuff. Thanks for everyone's help so far. \$\endgroup\$
    – kelly
    Dec 27, 2012 at 1:54

3 Answers 3

7
\$\begingroup\$

The shape of the bus doesn't matter as much. What usually matters the most is the total capacitance of the bus. A good conservative approach is to keep the capacitance below 400pF. Sometimes, it's possible to run I2C bus at higher capacitance, if you lower the speed. Stiffer pull-ups [fewer Ω] help too, but if they are too stiff, the buss will not work.

Typically, high bus capacitance is addressed with (1) buffering and/or (2) switching.

  1. There are specialized ICs for buffering I2C capacitance. PCA9515, for example.

  2. Each branch of the bus by itself has a low enough capacitance. But if all branches are connected together, their combined capacitance becomes too high. Add a multiplexor such that you can connect one branch at a time. The master will "see" the capacitance of only a single branch.

Handy application note: Troubleshooting I2C Bus Protocol. It shows both methods.

Diagnostic tip. Reduce the size of the bus (perhaps, by a half, if you can) and see if it hangs less or the same.

More info would help. The pictures in the O.P. don't show: mechanical dimensions, how your circuit is constructed (PCB, or cables, or breadboard).
An oscilloscope screen shot would help too.

\$\endgroup\$
6
  • \$\begingroup\$ Each device is mounted on a PCB. It's a similar design to unknowndomain.co.uk/blog/2009/02/19/…. I don't own a oscilloscope, but may pick one up. Right now, I don't have any additional pull-up resistor besides the internal Arduino resistors. I'll look into measuring capacitance. I have a multimeter, but still new to all of this. Thanks for your help. \$\endgroup\$
    – kelly
    Dec 27, 2012 at 2:02
  • \$\begingroup\$ I should also note that the the total the 64 devices are in a matrix that is 30in x 30in. Worried that the long wire length is also giving me issues. \$\endgroup\$
    – kelly
    Dec 27, 2012 at 2:06
  • \$\begingroup\$ @kelly Internal pull-ups in the ATmega are 20kΩ. This is way to weak for I2C pull-ups. This may be the main source of your woes. Add external pull-ups. I would start with value of 2.2kΩ (also, what Olin said). \$\endgroup\$ Dec 27, 2012 at 2:42
  • \$\begingroup\$ @kelly I2C was designed for communication within one circuit board. 30in x 30in (0.75m x 0.75m) would result in the total bus length of 6.75m. You're pushing it. But, you might get away with it. \$\endgroup\$ Dec 27, 2012 at 2:45
  • 1
    \$\begingroup\$ The 2.2kΩ resistors worked perfectly. Thanks again for your help! \$\endgroup\$
    – kelly
    Dec 30, 2012 at 0:32
6
\$\begingroup\$

Since it works for a while, it sounds like it is basically hooked up right but you are getting data corruption. When it hangs, the slave address probably got corrupted at the receiver, it didn't happen to be a address any of the other devices think is theirs either (whether it really was or after corruption), no ACK is sent, and the transmitting firmware hangs. It is surprising how poor most IIC firmware implementations are in dealing with no ACK received. There is a lot of irresponsible IIC firmware out there.

If the above guess is correct, then two things need to be fixed. First, the firmware needs to behave responsibly when no ACK is received at any time it is expected. This could be to a address or data byte. Second, the bus corruption needs to be fixed.

64 devices is a lot, but should be doable if all devices are on the same board. Taking IIC off board is asking for trouble, and with many devices doubly so. The exact topology of how the bus is connected shouldn't matter much since in any case it should be much shorted than the shortest wavelength of interest.

Put the stiffest pullup allowed somewhere on the bus. The maximum a IIC node needs to sink to drive the line low is 3 mA if I remember correctly. Make sure that is not exceeded, but otherwise use about the lowest pullup resistor allowed. For example, let's assume 3.3V power. 3.3V / 3mA = 1.1 kΩ. In theory a 1.1 kΩ pullup should be OK, but in this case I'd make it 1.2 kΩ. That's still almost the same pullup ability, and leaves a little margin against the maximum pulldown current. If the bus is mostly linear, you could put a 2.4 kΩ resistor at each end, although that will be a minor improvement, if any.

Take a look at rising and falling edges with a scope and see how long they take, then make your bit rate slow enough so that everything nicely settles within a bit time. All those nodes will add capacitance, which will slow the edges, particularly the rise time. There will be some bit rate limit you can't exceed due to this. It may not be possible to run the IIC bus as fast as the devices are otherwise capable of. That's a tradeoff you made when you decided to put 64 devices on the bus.

If you are still having problems after all the above is addressed, I would implement the IIC master in firmware without using any built in IIC hardware. I have seen some implementations from well known manufacturers have race conditions. Such implementations are particularly susceptible to a relative slew rate difference between SCL and SDA. My firmware-only implementations guarantee that never more than one thing happens per bit time. There is a minimum delay between every action that guarantees the bus has settled. This may run the bus slower than the hardware peripheral would, but makes for a good robust implementation. In fact, I usually use a firmware-only IIC master for robustness unless speed is critical.

\$\endgroup\$
4
  • 1
    \$\begingroup\$ I second the "I have seen some implementations from well known manufacturers have race conditions". It's amazing how such a relatively simple protocol gets implemented so casually and then fails at the customer's end. I had some fail on me and I had to fix the library after finding the issue. \$\endgroup\$ Dec 26, 2012 at 19:47
  • \$\begingroup\$ @Olin The race condition you're referring to was a result of the I2C hardware or the I2C firmware library that the manufacturer provided? \$\endgroup\$
    – NickHalden
    Dec 26, 2012 at 20:19
  • \$\begingroup\$ @Nick: The race condition was in the hardware, which the manufacturer eventually acknowledged. I have seen some really bad firmware implementations too. I guess the problem is that IIC looks pretty simple overall (which it actually is), so every moron thinks they can do it and too many try. \$\endgroup\$ Dec 26, 2012 at 21:06
  • \$\begingroup\$ @OlinLathrop Yeah that's probably the problem. \$\endgroup\$
    – NickHalden
    Dec 26, 2012 at 21:22
1
\$\begingroup\$

I suggest taking a look at the busses with the oscilloscope. I've seen similar issues even with less devices. With an oscilloscope you can look at the rise time of the signal and see whether the waveform violates the spec of any chip on the bus. I2C is a game of RC constants basically and you can't run it faster than what this creates. Make 100% sure that all devices will be happy with the waveform and give yourself some room as far as speed, otherwise heat and other effects might cause what might otherwise was successful communications to fail. If you need it absolutely foolproof, I'd even use some canned spray to cool and some hot air blower on the board.

One of the best approaches I've seen that anyone running these interfaces should do is to run statistics by communicating to all devices for a long period of time (hours) and reading some registers. Record any failures (and any possible causes) in some counter variables and then come back and look at them. There should be no failures. Using this method I've never had an issue.

\$\endgroup\$

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.