DUE + I2C Resiliency?

Hi all,
I am working on a project with multiple DUE's talking to each other over I2C. The crux of the problem is that in between the DUE's are a set of slip rings that can add ~5 mOhm resistance to the wires as the slip ring completes 1 rev (I also use about 2m of shielded cable between the DUEs). After changing my I2C to SDA1 & SCL1 so that I could put my own pull-up resistors on, and reducing the clock speed to 25k, I found that I could get some communication by having a pull-up resistor on either end of the cable for a total resistance ~18kOhm.
When the slip rings are stationary, the communication is fine. However, after about 10 seconds of them rotating the I2C receives a NACK (either during data transmit or address transmit). If I manually restart the DUE, then it usually works again for a few seconds.
My questions:

  1. On the hardware side, what can I do to ensure that I2C hangs less? It seems like the SCL line is that one that is very susceptible to noise. I have some ferrite beads coming in the mail. Make an RC filter with cutoff frequency much higher than clock speed? I know the SAM3X data sheet says C<400pF.
  2. On the software side, what can I do so that if there is an error in the transmit process, I can still keep transmitting. Ideally if there is a NACK I would just like to reset and try again. I tried many different variations in the source code to be able to automatically reset, but what ended up sort of working is:
uint8_t TwoWire::endTransmission(uint8_t sendStop) {
	uint8_t error = 0;
	// transmit buffer (blocking)
	TWI_StartWrite(twi, txAddress, 0, 0, txBuffer[0]);
	if (!TWI_WaitByteSent(twi, XMIT_TIMEOUT))
		error = 2;	// error, got NACK on address transmit
	
	if (error == 0) {
		uint16_t sent = 1;
		while (sent < txBufferLength) {
			TWI_WriteByte(twi, txBuffer[sent++]);
			if (!TWI_WaitByteSent(twi, XMIT_TIMEOUT))
				error = 3;	// error, got NACK during data transmmit
				TWI_Reset(twi); //get out of this while loop
		}
	}
	
	if (error == 0) {
		TWI_Stop(twi);
		if (!TWI_WaitTransferComplete(twi, XMIT_TIMEOUT))
			error = 4;	// error, finishing up
	}

	txBufferLength = 0;		// empty buffer
	status = MASTER_IDLE;
	return error;
}

where I copied from TWI_Stop to write TWI_Reset:

void TWI_Reset( Twi *pTwi )
{
    assert( pTwi != NULL ) ;

    pTwi->TWI_CR = TWI_CR_SWRST;
}

but the I2C still hangs! I know that someone wrote a more resilient code for the older chips:Arduino Playground - SoftwareI2CLibrary, but I haven't been able to find anything of that sort for the SAM3X.
Any thoughts on either of these questions would be much appreciated.
Sam

I have posted some mods to the wire library for multi-master mode (still needs more testing).

I doub't it will fix your issue (but have a look anyway).

I have to know - what the ^&* is a slip ring?

Stan

:slight_smile:
It allows the wires to rotate without getting tangled: Slip ring - Wikipedia.

Thanks for that - now I know :slight_smile:

All the best

Stan

FWIW - the mods I posted may assist - due to the switching between master/slave mode - if you want, give it a try!

http://forum.arduino.cc/index.php?topic=267447.0

What about using I2C driver chips (P82B96 et al), they have a lot more grunt which may help.


Rob

Yes, thank you. In fact I came to the exact same conclusion last night! I ordered some from DigiKey and I should be able to try them out next week. If people are interested I can update on the progress.
I'm glad we're on the same frequency. :slight_smile:

I can update on the progress.

Please do, it creates an entry for people to find in future should they be doing something similar.


Rob

Somewhat related question in which the O.P. is also running I2C through slip rings and struggling. I2C bus is convenient, but it's also one of the least resilient when it comes to glitches and interference.