Go Down

Topic: Random i2c errors, need help to stomp them out please! (Read 5 times) previous topic - next topic

SparksAlot


Those last 2 posts really gave me a lot to look into  :smiley-eek-blue:


Quote
Perhaps it's time to incorporate an I2C extender into your design.  http://ics.nxp.com/products/i2chubs/#Introduction .  I'm guessing that if put a scope on the signals they will look like crap!


I would agree. I think the issue is a bad signal.

There was an excellent document on that site:

http://ics.nxp.com/literature/presentations/interface/pdf/debug.i2c.oscilloscope.pdf

People interested in i2c should give it a look.

A wild guess at my freezing problem would be this quote:

Quote
The SDA line is stuck low because the slave is stuck in the transmitter mode


So an I2C extender really seems like it would solve my problem. But I couldn't find a product I can just start using : (

Can you recommend a product? An I2C extender breakout board for example?



Quote
So the first question is, are you fiddling with interrupts? Like disabling them from time to time?


Nope.


Quote
What you could consider is a "watchdog timer".


Researching a bit shows that to be very tricky. Maybe too tricky for me. Unless there is an easy way to do it without a risk of locking up your Arduino or having to create custom bootloaders.


Quote
Did you try the suggestion of lower pull-up resistors?


I did. I didn't have 1.5k as suggested, but I did try 2.2k and noticed no difference in stability. I will try 1.5k when I get my hands on them.


I'm considering replacing the ribbon cable with a cat 5 between the lights in case that helps keep noise out. Are there any off the shelf adapters with a cat 5 female on one side and a 0.1" 4 or more input female on the other? Or would making 15 patch points add just as much instability?

Also, would putting decoupling capacitors on clock and gnd and data and gnd between each light do anything? Or would that destroy the signal instead of stabilize it?

Thanks for all your help!

Daanii

Another interesting quote from the set of slides you found:

Quote
Problem: Due to the bus 400 pF
maximum capacitive load limit,
sending commands over wire (80
pF/m) long distances is hard to
achieve


That suggests that cables should be shorter than about 15 feet.

Ribbon cable is especially bad. Due both to capacitance and cross-talk, ribbon cable is not recommended for lengths over about 10 feet.

Any way to reduce the i2c clock speed? A slower signal should give better performance.

BenF


The endTransmission shouldn't go into a loop for no reason ....


Quite the contrary, endTransmission is typically where the wire library freezes when there are bus issues. It sits in a loop waiting for the bus to become ready and this may never happen in some circumstances. A reset of the I2C sub-module (or the microcontroller) is often required to recover from this. Sometimes this involves resetting all I2C nodes as you never know which node holds the bus in error.

The fact that it freezes the Arduino is a library issue and ideally it should never happen irrespective of bus issues. It is also the case however that it will probably never be an issue if there are no hardware/bus related hickups.

One way to approach this is to fix the wire library. The following link offers some details on how this can be accomplished.

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1283887406

Nick Gammon


Quote
What you could consider is a "watchdog timer".


Researching a bit shows that to be very tricky. Maybe too tricky for me. Unless there is an easy way to do it without a risk of locking up your Arduino or having to create custom bootloaders.


It's not tricky. No custom bootloaders needed. This example demonstrates:

Code: [Select]
#include <avr/wdt.h>

void setup ()
{
  Serial.begin (9600);
  wdt_enable(WDTO_1S);  // reset after one second, if no "pat the dog" received
}  // end of setup

void loop ()
{
 
Serial.println ("Entered loop ...");

Serial.println ("Point A");
delay (500);
Serial.println ("Point B");
delay (500);

wdt_reset();  // give me another second to do stuff (pat the dog)

Serial.println ("Point C");
delay (500);
Serial.println ("Point D");
delay (500);

while (true) ;   // oops, went into a loop
   
}  // end of loop


This resets the Arduino after 1 second. If you are doing something like flashing LEDs then the occasional pause while it regroups for part of a second won't be too bad.

In the example as shown, you see points A do D printed. Take out the wdt_reset() and it only does A to C (which takes one second).

So you just need the enable in setup, and do a wdt_reset() in the main loop. That way if an I2C communication hangs the program simply restarts automatically.

Quote from: BenF

One way to approach this is to fix the wire library.


It went into a loop for a reason. The reason was no interrupt received. But I agree that the suggested fix of adding a timeout would be one way out of it. Still, if you are going to timeout in the middle, and maybe reset the I2C hardware anyway, then the watchdog timer would effectively do that anyway.
http://www.gammon.com.au/electronics

SparksAlot

It looks like the watchdog timer only has a range of 1-8 seconds?

Is there a way to get more time? I would prefer 3-4 minutes.

I need big lengths of time in my code for motor movements for example. There are many long delays in my code longer than 8 seconds. Plus many little ones that add up.

Would prefer not to bust up my code into little 8 second chunks if possible.


I put in one decoupling capacitor and the 1.5k resistors. It did seem to help, but still get freezing. Just after longer periods :~

I put in the decoupling capacitor before the RTC but after the pull up resistors. Can I put another capacitor before the pull up resistors? That would seem to give a clean signal to the i2c clock and data lines maybe?

Can I put as many capacitors as I like all over? Or are there problems in doing so?

To ask again, would putting decoupling capacitors on clock and gnd and data and gnd between each light do anything? Or would that destroy the signal instead of stabilize it?

And again, does anyone know where to buy an i2c extender breakout board?

Thanks  : )

Nick Gammon

I wouldn't put capacitors on the SDA/SCL lines at all. The whole point of the pull-ups is to get a nice square wave, like this:



The capacitor would round it off. Possibly your long cable runs are having the same effect anyway, so you don't want to add to it. The capacitors would be useful on the Vcc lines at various places (like, each LED) to ensure that the chip gets a clean power signal. But not the data lines.

As for the timer, one approach is to simply reset it in any loop where you know "things are happening" (like moving motors). You don't need to break them into 8 second chunks.

Another would be to simply enable/disable it when you actually are doing the I2C stuff. Something like this, but I haven't tested it:

Code: [Select]
wdt_enable(WDTO_1S);
Wire.endTransmission ();
wdt_disable ();


Since it hangs in the endTransmission, that is the only place you really care about being "saved" from.
http://www.gammon.com.au/electronics

Ulli

Hello,
I encountered some I2C problems, too. The reason was a 5m cable and its capacity.
In your case, I would decouple the I2C between the RTC (internal) and the LED part (external). There are very nice possibilities to do it with, for example, the ISL3301. So you can have I2C lines buffered and this may help to keep the internal signals clean.
The reason of I2C problems is oftenly that you have to charge the cable via pull ups, that means passive. But don't make the pullups too small, it's not the optimal solution. Accelerators such as the ISL use current sources for that job. This is much better...
2b || !2b
Shakespeare, Hamlet

Daanii



I put in one decoupling capacitor and the 1.5k resistors. It did seem to help, but still get freezing. Just after longer periods :~

I put in the decoupling capacitor before the RTC but after the pull up resistors. Can I put another capacitor before the pull up resistors? That would seem to give a clean signal to the i2c clock and data lines maybe?

Can I put as many capacitors as I like all over? Or are there problems in doing so?

To ask again, would putting decoupling capacitors on clock and gnd and data and gnd between each light do anything? Or would that destroy the signal instead of stabilize it?



Just to reiterate -- capacitance is the probable problem, not the solution.

The reason why you want to put capacitance on the power lines is that to smooth them out. Nice steady power is good. Any spikes or changes are harmful noise -- you want to get rid of them.

With your signal, on the other hand, you don't want to smooth out the transitions. The transitions are not noise; they are signal. Capacitance will smooth the transitions and harm your signal. In fact, your 5 meters of ribbon cable probably exceeds the 400 pF maximum capacitance that the i2c standard permits. So although the device works, there are occasional problems.

The problem seems likely to be either noise or sloppy signal, or both. From the fact that your device freezes every now and then, I suspect noise. Ribbon cables are not good for noise. Using a Cat5 cable with signal and ground wires in twisted pairs will help combat noise. 

But the rather long, rather high-capacitance ribbon cable seems to point to sloppy signal instead of noise. If you have access to an oscilloscope, that might tell the tale. It would be interesting to see if you have a squarish type signal or more of a sawtooth.

As people have mentioned, a buffer might help. Sorry that I don't know of any i2c buffer breakout boards. Good luck with the project.

CrossRoads

You had asked about RJ45 connector for the receive end?

6-pin & 8-pin:

http://www.gravitech.us/rjbrbo1.html
http://www.gravitech.us/rjbrbo.html
Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Go Up