Hi there, I have 3 I2C sensors (ADXL345, HMC5843, ITG3200) connected on the I2C bus.
In the first implementation of the circuit I used 10K [ch937] as pullup resistor and after 1-2 minutes the I2C communication freezed hanging Arduino.
I then replaced the 10K [ch937] with 2.2K [ch937] resistors and now everything works just fine. I got 20 minutes of working. Anyway, pretty unpredictably the line sometime still hangs.
I'd like to hear your opinions on this. What could cause that and what can I do?
I heard that Wire is quite not tollerant and it would expect a "quite perfect" channel and that it would hangs when there are some communication problems.
Do you guys have any suggestions? Both in software or in hardware?
10k is a bit weak; 2.2k is closer to what I remember the spec calls for.
I read about some device in the past few days (could have been the HMC5843, or one of its cousins) that had it's own pullup resistors. Datasheets for each peripheral should be examined.
The size of the pull-up resistor is a function of the bus capacitance.
A 10K pull-up should be able to handle bus capacitance up to about 120pF. That shouldn't be a problem if all the devices are on the same board right next to each other. You don't say how your bus designed and built. If they are each at the end of a long wire that may be way too high a value.
Do you have an oscilloscope so that you can look at the bus signals? The rise time of the signals is what should dictate your pull-up resistor value.
I must say I am suppressed at this, while 10K is a bit on the high side, I would not have expected a crash. The lower the resistance the more noise immunity you have so you might be in a marginal noise situation. How is the decoupling on the rest of the circuit. If you have none then that is the root cause of your problems.
Thanks guys for the insights. You can have a look at the circuit here. To that circuit I added a 5v -> 3.3v voltage regulator so I'm now taking voltage from the 5V source instead of 3V3.
I'm using homebrew breakout boards for the ADXL345 and ITG3200 (see links for schematics and designs). I'm also using sparkfun HMC5843 breakout board.
Regarding to decoupling, each breakout board has its own decoupling 0.1uF capacitor. Grumpy_Mike, is this what you mean?
Ok, I added the 10uF cap on the Vout from the voltage regulator and things looks even more stable. I also disabled the raw data ready interrupt that the ITG3200 library I'm using was enabling.. It could be the cause?
My guess: the ITG3200 handles bad the interrupts and stops or delay communication which causes missing or delayed bits on the line..
To be more explicit, only use pinMode() to drive the pin - switching it from OUTPUT (and thus LOW) to INPUT (and thus high-impedance).
The paranoid would perhaps use
digitalWrite (pin, LOW) ;
pinMode (pin, OUTPUT) ;
to drive the line low and
pinMode (pin, INPUT) ;
to 'drive' it high (via the external 3V3 pullup resistor.) The worst thing would be to select pinMode (pin, OUTPUT) when the output was high - a 3V3 chip has a good chance of surviving the weak internal pull-up, but accidentally driving it to 5V directly would likely fry something. Ideally external circuitry would protect against this - relying on software integrity to protect hardware from being overdriven is not good. Say you connected it up with the wrong sketch loaded into the Arduino....
This is an example but I don't think those resistor values are proper.
The atmega digital pins are supposed to start in a high impedance state. If it's possible to load the wrong code I'd start the arduino with nothing connected and load the right code. It would be some odd situation where a pullup could be on and the pin is switched to an output as was said by MarkT. If it's going to be permanent get or make the sparkfun circuit or try one of the I2C level shifter chips with two channels.
I do have Sparkfun's logic level converter but as devices where working great without it I never plugged it. Should I? @mrmeval Why do you think those resistors values are wrong?
Moreover, I'm using Analog 4 & 5 for I2C.. I don't think I can do a digitalWrite on them and, given that they are input pins, they should start in high impedance mode by default.
According to the application note from NXP that's out there (sorry I don't have a link) it shows a simple circuit using a 10K pullup on the low voltage side along with a MOSFET that almost matches the Sparkfun logic level converter. On the Sparkfun converter, along with a 10K pullup on the low side, it has an additional 10K pullup on the high voltage side. I'm not sure what impact that will have but if you want to reproduce the exact circuit in the application note you can leave the HV pin disconnected on the converter. Any external pullup you use on the low side should be calculated around the 10K already in place.
You should have a 100nf ceramic or greencap on both the input and out put, as well as the 10uf tantalum or electrolytic cap on the output, other wise the regulator will oscillate like a bitch!
Also remember with linear regulators like the LD1117S33CTR, you need to give it enough voltage to "work" with or it will oscillate like a bitch!