I2C Wire Shielding

Hi everyone,

I’ve built a balancing drone, akin to a falcon 9 first stage. It’s radio Controlled but stabilised by the STM32, and eventually will have some degree of autonomy.

I ran into an issue when I moved the MPU9250 from the top to the CG. After about 1 minute (it varies) of use the controller would freeze. The signals to both motors and both servos would stick at whatever value they were at. Not so great if the motor was running fast.

It reads 14 bytes of data from the IMU @500Hz with an I2C clock speed of 400kHz.

I’ve realised that I’m getting interference down the 4-strand wire I’m using to communicate with it. Before this wire was much shorter as the sensor was at the top and didn’t cause an issue. If I disconnect the motors and servos it runs fine, so I don’t think it’s a capacitance problem, only when the motors and servos are active does it crash.

I’ve read some posts online and I know I2C shouldn’t be used for large distances but mines cuurrently 62cm and I could probably shorten that so about 50cm if I route it directly. It would seem that shielded cable is the way to go but I still have a few questions I was hoping someone could help me out with.

How many cores?
It looks like I shouldn’t shield Vcc but then some people wrap Gnd with the data wires in twisted pairs.

Over 50cm will twisting the SCL & SDA wires cause an issue?

Do you ground the shielding at 1 end or both?
I keep finding contradicting information.

Will reducing the clock speed to 100kHz help reduce EMI interference?

Would a simple 2-core shielded cable , microphone or headphone, work for SCL and SDA with the shield grounded at both ends?

Many thanks!

What value are the I2C pullup resistors? Stronger pullups, along with the other remedies, may help.

They have 10k pull-up resistors on the IMU, I tried adding 4.7k ones and that had no effect.

So you have a power cable and a signal cable is that right? If so, I would screen both of them, terminate the screen on both ends of the power cable and terminate at the load end of the signal cable, that way any interference should run back along the power cable to ground.

I'm no electronics guru but I've seen it done this way in industry.

So the I2C protocol uses 4 wires, Vcc, Gnd, SDA, SCL. I've bought some 2-core shielded cable and will try that on just the data lines to begin with. I'll also shorten the wires to around 0.5m and see if that helps. Cheers, it does seem grounding the shield at both ends is the right way to go but I've read lots of differing opinions on it.

I always grounded shields only at the instrument end. Grounding both ends invites ground loops.

Video of the problem. I was thinking of buying some shielding tape and use it to cover the servos. Anyone with experience with that?

groundFungus:
I always grounded shields only at the instrument end. Grounding both ends invites ground loops.

Exactly...

groundFungus:
I always grounded shields only at the instrument end. Grounding both ends invites ground loops.

If you are using shielded cables, the shield should be the required ground connection between the two devices.

I2C is limited by cable capacitance, so shielding I2C is not the correct solution. It might work, but it isn't right.
Your video raises a question- why is the servo so far from the motors? Have you tried shielding the wires to the servos? Have you used a scope to see what the interference looks like?

I2C is unreliable no matter what you do. IMHO your robot should be able to quickly recover from any I2C error AND the MCU should be able to recover from most other errors. In other words activate BOD, Watchdog with a short timeout and some monitoring of the I2C.

The setup I had before which worked was the IMU was on the level above the servos. I can only assume that the shorter length of the I2C wire and the fact that the wire was not near the servo reduced interference.

The servos are high up in the frame to help keep the CoG as high as possible. The IMU really needs to stay where it is as that is the CoG location and therefore will experience pure rotation.

I’ll see if the shielding works this week but the other options are move the servos up or down.

If they go up, I’ll need new carbon tubes, which may start to become flimsy and the servo motor may still interact with the I2C wires as the wires need to pass nearby the servo which I think is the cause of the interference.

Moving them down would lower the CoG, not ideal and they would have to move 2 ‘levels’ down as the next one down is occupied by the IMU. Vehicle would be slightly less stable but I2C wires wouldn’t route near the servos.

I did a test and held the IMU and data lines near the servo wires but not near the servo itself and that seemed to be ok.

Note that while you need to keep the capacitance down in the I2C wiring, it is important in respect of interference that you run all four wires together wherever they go. :grinning:

I think it is a poor design to have code that cannot deal with I2C noise (if this is truly the problem). By moving/shielding the wires you do not fix it, merely hide it. You are very lucky you get this error rate. Imagine that your shielding reduces it from well noticeable once per minute to once per hour. You will get mysterious very hard to trace failures.

jaddion82052:
I've bought some 2-core shielded cable and will try that on just the data lines to begin with.

Wise to keep wire capacitance on SCL and SDA the same.

I never had issues with Cat-5/6 Ethernet twisted pair for I2C.
One pair for SDA/GND and one pair for SCL/VCC.

I would start with ~3k3 pull up on both ends of the cable.
Added resistance values depends on what's already there.
Leo..

Smajdalf:
I think it is a poor design to have code that cannot deal with I2C noise (if this is truly the problem).

I'm not sure how I can make the code much different, it's just standard MPU6050 code reading at 500Hz. I didnt know there are ways to make it more fault tolerant.

Wawa:
I never had issues with Cat-5/6 Ethernet twisted pair for I2C.
One pair for SDA/GND and one pair for SCL/VCC.

I did read somewhere about twisted pairs. If SDA & SCL are both twisted with GND, What is best practice for the VCC line?

Thanks all for your suggestions.

jaddion82052:
I'm not sure how I can make the code much different, it's just standard MPU6050 code reading at 500Hz. I didnt know there are ways to make it more fault tolerant.

On a 328, the I2C is in the hardware and it can get into a hung state. You can always reset the Wire module before you do the read [e.g. Wire.begin()] which imposes a known state into the registers. To get out of the hung state, you need a WDT reset or some other mechanism.

jaddion82052:
I did read somewhere about twisted pairs. If SDA & SCL are both twisted with GND, What is best practice for the VCC line?

I gave you the most economical way, so you only use two of the four pairs, and have spare wires for other things.
But you can of course pair both with ground, and use another wire (any) for VCC.
Do calculate pull up on both ends for 3k3.

Did you try default I2C (100kHz).
Leo..

Twisted-pair wires only adds capacitance to the I2C lines. Not advisable.

You don't say which IMU you are using, but if it is like the GY-86, then I suspect that magnetic compass in the IMU is getting bad data from the unshielded servo motors. You could be trying to fix a non-issue with wire shielding.

I don't know what code you are using but IIRC Arduino examples wait until I2C finishes. It is an endless loop when I2C becomes stuck. You should wait at most a few milliseconds (using mills/micros, not delay) and when the time expires without result go to an error recovery routine (try to reset I2C, the module, maybe log the problem and if it persists turn off motors). This way you will know for sure the cause (from log), how often it happens and make your robot much safer. You should have similar checks for all situations you know that may result in an endless loop and a WDT for the others.