I2C Bus Hanging on 8 daisy chained Arduinos

I have chained 8 ATMega328 (slaves) with an Arduino (master). They are connected on an I2C hub. Each ATMega is connect to the next with a 3ft Cat5 cable, which passes not only the I2C signals (SCL+SDA) but also power to the next ATMega. I also have an I2C Bus extender on each ATMega to extend the length of the signal (http://www.ti.com/product/P82B715).

Each ATMega has a servo connected to it (with a different power supply) and I am trying to control the servos using the Master Arduino.

Slave Code:

Servo mys; int servoVal = 0;

void setup() {
Wire.begin (0X8); // join i2c bus with address #8 Wire.onReceive(receiveEvent); // register event mys.attach(6); pinMode(led, OUTPUT); }

void loop() {

delay(50);
mys.write(servoVal);

}

void receiveEvent(int howMany) { servoVal = Wire.read(); }

Before the holidays, I had tested the system and it was working just fine no issues at all. But after coming back from break, the I2C bus seems to hang and becomes unresponsive. It seems to work fine when I have a max 4-5 ATMegas anything beyond that it seem to work for a bit and then becomes unresponsive.

Any advice?

I don't see how it is going to work at all. You didn't call Wire.onReceive(receiveEvent) to set the receive function.

You are using a different slave address for each device, correct?

Sorry the code above it a little jumbled up. But yes I am called Wire.onRecieve. And yes each slave has a unique address

#include <Wire.h>
#include <Servo.h>

Servo mys;
int pos = 0;

void setup() {
Wire.begin(18); // join i2c bus with address #18
Wire.onReceive(receiveEvent); // register event
mys.attach(6);
}

void loop() {
delay(10);
mys.write(pos);
}

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany) {
int x = Wire.read(); // receive byte as an integer
pos = x; // print the integer
}

Use code tags please. They are explained at number 7 on this page : http://forum.arduino.cc/index.php/topic,148850.0.html

Your ‘pos’ should be volatile.

volatile byte pos = 0;

If you want ‘pos’ to be an integer, then you have turn off the interrupts if you use ‘pos’ in the loop().

What about ground currents ? How is the ground of the servo motor connected to the ground of the Arduino ?
Perhaps the ground current of the servo decides to use the GND of the I2C bus.

What about pullup resistors for the I2C bus. Do you use a single pullup on the extended bus, or pullups at every module, or only the first and the last one ? And pullups on the SDA and SCL for every module ? How did you connect the two twisted pairs ? just as in the datasheet of the P82B715 ? Are you sure ?

Sorry about that!!

Koepel: Use code tags please. They are explained at number 7 on this page : http://forum.arduino.cc/index.php/topic,148850.0.html

The servo has a separate power supply, but the grounds are common.

Koepel: What about ground currents ? How is the ground of the servo motor connected to the ground of the Arduino ?

Why would this cause an issue?

Koepel: Perhaps the ground current of the servo decides to use the GND of the I2C bus.

I have 4.7K on the short side i.e. from P82B715 to the ATMega and 470ohms on the long side i.e. from P82B715 to the bus. Something like this: https://tronixstuff.files.wordpress.com/2010/10/i2cbufferedss.jpg

Koepel: What about pullup resistors for the I2C bus. Do you use a single pullup on the extended bus, or pullups at every module, or only the first and the last one ? And pullups on the SDA and SCL for every module ? How did you connect the two twisted pairs ? just as in the datasheet of the P82B715 ? Are you sure ?

So you have 470 ohm at the beginning and at the end of the daisy chain, and not in between ? That's okay.

Grounds can be connected in hundred different ways. When you say "the grounds are common", I think you have a single wire for the ground ? That could be a problem. But also having two ground wires and they are connected in two places, that can be a problem as well.

Ground currents can be funny things. If you would have thick wire for the servo motor and a thin wire for the I2C bus, then the ground current of the servo motor might still prefer the thin wire.

A servo motor could require a current of 0.5A when it starts turning. It can even be 1A. That peak of current could mess up the ground voltage, and maybe wires next to it get a voltage spike. That means that the extended I2C is no longer a clean signal, but it might be very noisy.

The ideal situation is when you have a central unit where the grounds are connected. The grounds are not connected somewhere else. The ground for the extended I2C and for the Arduinos can be the same. The servo motors would have their own ground. Every Arduino would use an opto-coupler for the servo motor.

Could you at least split the grounds ? Or if you have a few unused wires, use them all for the ground. Perhaps adding a 1000uF capacitor to the power next to every servo motor might help to reduce the current peaks in the cable. What happens if you disconnect the servo motors, and use just a led or so ?