Uncategorized

I2C bus fails after a few sensor reads

@RobH. I just saw that you are using Rpi3B+, and there is a big problem. It was some two years ago I found a rpi pro complaining that he could not set his Rpi3B+ I2C speed to higher or lower than that default flat 100kHz. So I joined in the swearing discussion group that I also discovered the bug, verifying by three Rpi3B+ and my oscilloscope.Then the Rpi “experts”, including one who claimed that he “participated” in the “foundation”. All experts then said according to official doc, Rpi (3B+), you could change the frequency, by this doc, this and dtoverlay statements. Me and other angry swearers of half the galaxy verified and verified to concluded that Rpi3B+, also confirmed by some insiders that ...the official doc was misleadingly wrong. Anyway, it was only when Rpi4B and buster came along that the “system bug” was fixed. In other words, if you are using Rpi3B+ and you thought you were changing the I2C speed to 50k, 400k, whatever, and if you had a scope you can immediately verified that you were a fool, cheated by the official doc and other elites and experts (just reading the doc without any practical I2C experience).If you skimmed by long list of posts there, you might also found me complaining that not just for Rpi, but also a couple of famous brands do “sometimes” created bugs in there hardware devices, well they called “special features”, and won’t disclose them until the developers press hard enough then they would admit.Thank you for reading my long paragraphs. What I want to say/repeat is the following: “RPI3B+ HAS A SYSTEM BUG, AND CANNOT CHANGE I2C SPEED”. Cheers.

I2C bus fails after a few sensor reads

Ask QuestionAsked todayActive todayViewed 74 times1

I’m building a small home automation hobby project for which I try to connect 4 temperature/humidity sensors (AM2320) to an I2C bus on the Raspberry Pi. When initially connecting the sensors they work fine, but after a few calls (10 to 50) with 4s interval, the reading fails with a “OSError: [Errno 6] No such device or address”. After that, a call to i2cdetect on the bus results in a very slow respons where each probed address takes around 1s (equal to the problem described here). After this i2cdetect fails to detect the sensor.

Physically disconnecting and reconnecting the sensor resets the bus.

I think the root of the problem is in the capacitance of the connecting line between sensors and Pi, however I can’t wrap my head around why. Hopefully someone can clarify what the problem is.

Details of the setup

I am using 4 identical sensors connected to a single Raspberry pi. Each sensor is connected to it via a stripped Cat5 cable (4 wires (2 twisted pairs) per sensor, shielding and outer isolation removed) of approximately 2m length.

As the sensors are rather simple and cheap, they do not have a configurable I2C address. Each has address 0x5c. To accommodate 4 of them I configured some GPIO pins to give me 3 additional I2C buses next to the standard bus number 1. This is done by adding the following lines to the config file. (As per this instructable.)

dtoverlay=i2c-gpio,bus=5,i2c_gpio_delay_us=1,i2c_gpio_sda=23,i2c_gpio_scl=24
dtoverlay=i2c-gpio,bus=4,i2c_gpio_delay_us=1,i2c_gpio_sda=17,i2c_gpio_scl=27
dtoverlay=i2c-gpio,bus=3,i2c_gpio_delay_us=1,i2c_gpio_sda=4,i2c_gpio_scl=18

All sensors are powered from the 3.3V rail on the Pi. All SDA and SCL lines have a pull-up resistor of 3.3 kOhm. Only for the ‘standard’ I2C bus number 1 I rely on the 1.8 kOhm resistors that are on the Pi itself.

I read the sensors by means of this Python script: https://github.com/Gozem/am2320/blob/master/am2320.py.

Things I have tried

I have tried the following things, by themselves and various permutations of these things. Non appears to have any noticeable positive or negative effect.

  • Different timing parameters for waiting in the Python script.
  • Different I2C speeds (from standard 100 kHz down to 50 kHz, 25 kHz, 10 kHz, 5 kHz and 0.5 kHz).
  • Different pull-up resistor values: 150 Ohm, 230 Ohm, 1.8 kOhm, 3.3 kOhm, 10 kOhm, and Inf (no pull-up). As well as the Raspberry Pi build in pull-ups.
  • Different number of sensors (connecting only 1, connecting 2, connecting all 4)
  • Different sensors on different buses (various permutations).
  • Untwisting the wires: For one sensor I untwisted the wires to attempt and reduce the capacitance between them.
  • Software resetting the bus (via this method) does not resolve the problem. Only a physical disconnect/reconnect works.
  • Rebooting the RaspBerry Pi sometimes resets the bus, but not always.

The only thing that did seem to solve the problem: Was when I moved one sensor closer to the Pi. With a twisted pair wire of ~0.2 m length it appears to work fine (tested for ~half an hour). This indicates to me that wire length, and thus likely wire capacitance or wire resistance is the issue. However when looking at the way to compute the maximum allowed values (as per this TI document), and looking at the characteristics of Cat 5 cable (wiki) I would think I should be well below the maximum 400 pF capacitance, and should have hit a suitable termination resistance somewhere given all the various resistor values and communication speeds I have tried.

(I unfortunately don’t have an oscilloscope to measure the signals on the line directly.)

So to summarize the question: I’m at my wits end and hope that there is someone who can explain me what’s going on.

Edits based on comments:

(2021-01-11 16:00)

I’m using a Raspberry Pi 3B+ I had the cables in twisted pairs as ((V;GND) and (SDA;SCL)).

I have now reduced the complexity of the setup. I only have 1 sensor connected directly to the Pi I2C bus 1 (GPIO 2 and 3), with only the Pi pull up resistors. The wires between are untwisted ~2m long. I’ve disabled all extra I2C buses. I’ve added a 4.7 nF and a 47 uF capacitor between the V+ and GND on the sensor side (As per suggestion from Justme to add some. I’ve chosen the cap values rather arbitrarily). This seems to work without issue(!) (Over 400 cycles, 4s interval. Stopped and started the script some times in between.).

From this point I extended to include one more sensor. I added an I2C bus number 3 on GPIO 17 and 27 with 3.2 kOhm pull-ups. Added a second sensor to this. The sensor also has 4.7 nF and 47 uF capacitors added at the sensor end. This is still connected via twisted wire pairs. The second sensor malfunctioned after ~200 cycles. At that point i2cdetect also only read addresses ‘in slow mode’. Sensor on bus 1 happily continued on. I swapped the two sensors around. Same result after ~330 cycles: Sensor on bus 3 (untwisted pair) failed, sensor on bus 1 (twisted pair) continued on. So either it’s the difference in pull-up resistors (next to investigate), or it’s indeed that the extra I2C bus is unstable for some reason (as suggested in the comments by tflong01).

(2021-01-11 17:30)

Bus 3 is unstable with whichever sensor and whatever pull-up resistor. Sometimes it works for 100+ cycles, sometimes it fails on the first try. Any sensor on bus 1 however, is rock steady now that the caps are added to the sensor.raspberry-pii2cparasitic-capacitanceShareEditFollowFlagedited 8 hours agoasked 15 hours agoRob H.1122 bronze badges New contributor

add a comment

Chats

I2C bus fails after a few sensor reads

Rob H.I’m building a small home automation hobby project for which I try to connect 4 temperature/humidity sensors (AM2320) to an I2C bus on the Raspberry Pi. When initially connecting the sensors they work fine, but after a few calls (10 to 50) with 4s interval, the reading fails with a “OSError: [Err…raspberry-pii2cparasitic-capacitanceJustmeHow are the twisted pair wires paired? I hope SDA and SCL are not paired together. Rob H.45

Unfortunately they are. (Vcc + GND one pair, and SDA + SCL another). Would that give them sufficient mutual capacitance to disrupt any communication you think? The problem also appears with a sensor where I completely untwisted the wires. (So it’s just 4 dangling single wires now.) Justme45.7k

Yes, it could, because now the capacitance is between SDA and SCL. So a falling edge on one wire would capacitively couple to be a falling edge on the other wire too, as it is only weakly held high by a resistor. You might also be missing supply bypass caps on sensor end of the wire. Rob H.

So that could also be an effect if both wires are no longer twisted but separated by a few cm of air? I did not add extra components to the sensor side yet. The bypass cap would be between V+ and GND? Justme

It would not effect untwisted wires much. Yes cap between supply and ground. 

tlfong0149557:36@ Rob H, Welcome and nice to meet you. Just a quick reply, more replies to follow in the next couple of days.

(1) The instructable you mentioned: instructables.com/Raspberry-PI-Multiple-I2c-Devices. is NOT trustworthy.

Rpi4B has official instructions to do up to 5 I2C buses. I tried but found that using two I2C buses (1 and 3) is OK, but three or more is not reliable.

Some two years ago I played with AM2302 (similar to AM2320). You might like to read my old posts to see how I did I2C troubleshooting.

Testing AM2302 – Rpi.org.forum raspberrypi.org/forums/…. Please feel free to ask me any related questions. Cheers.

My AM2302 is outdated. Perhaps I should try AM2320 later. kandrsmith.org/RJS/Misc/Hygrometers/calib_many.html.You might like to read my old post on I2C frequency and multiport setting. As I said earlier, three or more I2C ports even for Rpi4B and buster is NOT reliable.

What is Rpi’s I2C Maximum Speed? – Rpi SE raspberrypi.stackexchange.com/questions/108896/….

And have you ever heard of the I2C Address MUX? TCA9548A 1-to-8 I2C multiplexer! learn.adafruit.com/….

One way to improve I2C performance is the up shift 3V3 logic to 5V0. You might have noticed in my I2C projects that I am using Logical Level Shifter/Converter TSX/TBX0102/4/6/8 with chip enable.

This is also sort of I2C MUX that eg, with one I2C bus you can have as many as same address sensors, BUT not at the same time.Ref: TSX0108 adafruit.com/product/395

Rob H.Thanks for the welcome and for all the suggestions guys. I’ll try around some more with components I have available and update in the post.

If it does not work out I’ll indeed probably have to go for a level shifter, muxer, or maybe some other sensors altogether. 

Pete W343 at work so can’t read all this, but general advice for i2c with extended distance:

(0) if you have an oscilloscope, look at the signal! (1) series resistance, ~50-100 ohm.

(2) replace R pull_up with constant current pull-up. works wonders.

perhaps install on both ends.

find the sweet spot, excessive pull-up current just makes more noise.

(3) don’t put caps on signal lines

(4) if >5m, cable construction can be a factor too, but prob shouldn’t be i2c then 

Rob H.45Hello Pete.

(0) Unfortunately not available

(1) So you suggest each of the lines between slave and master should have a series resistance between 50 and 100 ohm? Why exactly?

(2) I can imagine that would help indeed. I don’t have that readily available though.

(3) I didn’t and I won’t.

(4) <5m check. 

Bruce Abbott“I unfortunately don’t have an oscilloscope to measure the signals on the line directly.” – time to get one! 

Pete W343

@Rob — (4) good (3) good (2) up to you, but it is not hard with a current mirror, which is a dual-transistor and one resistor; it adds one extra discrete package per line.

(1) the resistance will form an RC filter with the bulk capacitance of the wire, and will slow down the rise/fall of the signal. Terminates too. Slowing down the dV/dt, less crosstalk between SDA/SCL. (assuming that is the problem, which is just a guess.)

If on the other hand the power/ground are bouncing around, you would fix it a different way.

(0) if you could observe it directly, it would be easier to diagnose the causeto be clear, the current pull-up is a little bit unconventional, but I have found it tremendously useful for exactly your situation

 Justme45.7k7:36

Pete is right about the 100 ohm resistors. Wires have inductance, and in fact since it is CAT5 cable the pair is a 100 ohm differential transmission line, and in fact the end pulling low is a short circuit and the other end is open, so there could be reflections.

The 100 ohm series resistors would slow down falling signal edges. As the Raspberry Pi also has configurable IO pin driver strength, make it as weak as possible, or at least weaker. 

Rob H.45

Alright, I can try the series resistor and/or configuring the driver strength tomorrow. Specifically the second one requires me to read into it a bit.

Question out of curiosity on the suggested current driver: That does seem counteractive to the suggested resistor right? Using a current driver would speed up dV/dt? So either could be a solution, but likely not both?(btw: The Pi has been sampling bus 1 at 10s intervals for almost 5hrs now without a single hick-up.

That one seems pretty solid. (Single sensor, GPIO 2 and 3, no other buses enabled, via twisted pairs Cat5 cable, standard Pi 1.8 kOhm pull-ups, sensor side bypass caps of 4.7 nF and 47 uF, no added series resistors or any other tricks)

I have the feeling the issues with the other buses may instead be in the Pi / i2c_gpio?) 

Pete W343@Rob, re: constant current vs series R … they attack the problem of crosstalk and V_DD/GND noise in different ways.

The series R does 2 things: (1) reduces dv/dt, which reduces magnitude of induced voltage on adjacent line in the cable.

(2) terminates reflections when the open-drain output is turned on….… . The constant current source does other things.

(3) allows lower pull-up current to be used, which can reduce noises on local GND from the dI/dt of the chip pulling low against the line’s capacitance

(4) despite this, “responds” faster than a resistor pull-up. The crosstalk scenario for i2c is when a negative spike (or rising GND) comes along, while SCL is supposed to be staying high. In this case the resistor doesn’t start to counteract this induced spike (source current to pull back up) until some meaningful voltage has already dropped.

The CC pull-up immediately sources current.there are two caveats with the series R. Firstly, the “low” level will rise — due to the voltage divider formed by R_series vs R_pullup. (similar effect with I_pullup). So you can’t make the R_series too big.

Secondly, you don’t want to slow down the signal too much. But I wouldn’t worry about that in practice.Now if you had a scope, you could really see all these things vividly, and figure out just how much fooling around with the circuitry you need =)

In terms of making the thing reliable — if you suspect intermittent/marginal signal quality relating to the length of the 2m cable, then get a 5m cable or 10m cable, and make it work for that. Then you will be really confident.  The last message was posted 2 hours ago.

Categories: Uncategorized

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.