Can't communicate with MPU6050 - Strange bus activity

Hey all,
I'm banging my head against the wall with this one. I'm using a GY-521 breakout board for the MPU6050 to communicate 3 axis gyroscope values to a Mega 2560 along 1 meter of CAT6E cable with the I2C protocol. The SDA and SCL lines are each twisted with ground to reduce coupling between the two. The I2C bus is isolated (and level shifted to 3.3V) between the Mega and the sensor by a Texas Instruments TCA9517 bus buffer on a PCB I spun up for this purpose.

My issue is that when I set up the MPU6050 on a breadboard with an Adafruit bidirectional logic level converter, I can read sensor values just fine. When I go through the CAT6E and my PCB, the sensor does not communicate and I end up reading all zeros. The Mega is being supplied with 5V, the GY-521 is being supplied with 3.3V (the onboard LDO regulator will produce 3.3V from as low as ~2.1V input), and the TCA9517 utilizes both voltages. I2C level on the Arduino side is 5V and logic level on the sensor side is 3.3V. The sketch I am using is Jeff Rowberg's MPU6050_raw example, attached at the end of this post.

My first thought was an improper pinout between the Mega, my PCB, and the MPU6050, but I rung everything out with a multimeter and all is well. The CAT6 wiring from the MPU6050 matches that of other sensors I have gotten to work with this setup (DS3231, SSD1307, MCP9808, MAX30102), and my power supplies are stable. My second thought was improperly sized pullup resistors on the I2C bus, since any length of cabling is going to increase bus capacitance. I replaced the pullup resistors on both the 5V high side and 3.3V low side with values to set the sink current between 2 and 3 mA. This is within datasheet limits for all of the devices, under the I2C spec limit of 3 mA, and much stronger than the <1mA current the original values offered. Still no results from the sensor.

I got the I2C bus on a scope, and I'm pretty confused by what I'm seeing. My rising edges look good, so whether or not the pullup values were a problem before, they aren't now. The clock line looks great with or without the MPU6050 present on the bus. The data line looks great ("SDA_Open.jpg") without the MPU6050 on the bus. However, when the sensor is added to the bus ("SDA1.jpg" and "SDA2.jpg"), it seems to me that the sensor is attempting to communicate but is holding the line at .3V rather than releasing it to 3.3V. I replaced the TCA9517 thinking I may have damaged it, and tried a second MPU6050 with the same results. Other sensors that I have wired in this manner communicate without issue on this same bus. If anybody has suggestions, I would very much appreciate them. I've attached the part of the PCB schematic that relates to this comms line, a schematic for the GY-521, and some cellphone captures (sorry, didn't have a flash drive on me). Has anybody seen this before?

Jeff Rowberg's code:

// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class
// 10/7/2011 by Jeff Rowberg <jeff@rowberg.net>
// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
//
// Changelog:
//      2013-05-08 - added multiple output formats
//                 - added seamless Fastwire support
//      2011-10-07 - initial release

/* ============================================
I2Cdev device library code is placed under the MIT license
Copyright (c) 2011 Jeff Rowberg
===============================================
*/

// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files
// for both classes must be in the include path of your project
#include "I2Cdev.h"
#include "MPU6050.h"

// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
// is used in I2Cdev.h
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
    #include "Wire.h"
#endif

MPU6050 accelgyro;
//MPU6050 accelgyro(0x69); // <-- use for AD0 high

int16_t ax, ay, az;
int16_t gx, gy, gz;


#define LED_PIN 13
bool blinkState = false;

void setup() {
    // join I2C bus (I2Cdev library doesn't do this automatically)
    #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
        Wire.begin();
    #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
        Fastwire::setup(400, true);
    #endif


    Serial.begin(38400);

    // initialize device
    Serial.println("Initializing I2C devices...");
    accelgyro.initialize();

    // verify connection
    Serial.println("Testing device connections...");
    Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");

    // use the code below to change accel/gyro offset values
    /*
    Serial.println("Updating internal sensor offsets...");
    // -76	-2359	1688	0	0	0
    Serial.print(accelgyro.getXAccelOffset()); Serial.print("\t"); // -76
    Serial.print(accelgyro.getYAccelOffset()); Serial.print("\t"); // -2359
    Serial.print(accelgyro.getZAccelOffset()); Serial.print("\t"); // 1688
    Serial.print(accelgyro.getXGyroOffset()); Serial.print("\t"); // 0
    Serial.print(accelgyro.getYGyroOffset()); Serial.print("\t"); // 0
    Serial.print(accelgyro.getZGyroOffset()); Serial.print("\t"); // 0
    Serial.print("\n");
    accelgyro.setXGyroOffset(220);
    accelgyro.setYGyroOffset(76);
    accelgyro.setZGyroOffset(-85);
    Serial.print(accelgyro.getXAccelOffset()); Serial.print("\t"); // -76
    Serial.print(accelgyro.getYAccelOffset()); Serial.print("\t"); // -2359
    Serial.print(accelgyro.getZAccelOffset()); Serial.print("\t"); // 1688
    Serial.print(accelgyro.getXGyroOffset()); Serial.print("\t"); // 0
    Serial.print(accelgyro.getYGyroOffset()); Serial.print("\t"); // 0
    Serial.print(accelgyro.getZGyroOffset()); Serial.print("\t"); // 0
    Serial.print("\n");
    */

    // configure Arduino LED pin for output
    pinMode(LED_PIN, OUTPUT);
}

void loop() {
    // read raw accel/gyro measurements from device
    accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);

    // these methods (and a few others) are also available
    //accelgyro.getAcceleration(&ax, &ay, &az);
    //accelgyro.getRotation(&gx, &gy, &gz);

    #ifdef OUTPUT_READABLE_ACCELGYRO
        // display tab-separated accel/gyro x/y/z values
        Serial.print("a/g:\t");
        Serial.print(ax); Serial.print("\t");
        Serial.print(ay); Serial.print("\t");
        Serial.print(az); Serial.print("\t");
        Serial.print(gx); Serial.print("\t");
        Serial.print(gy); Serial.print("\t");
        Serial.println(gz);
    #endif

    #ifdef OUTPUT_BINARY_ACCELGYRO
        Serial.write((uint8_t)(ax >> 8)); Serial.write((uint8_t)(ax & 0xFF));
        Serial.write((uint8_t)(ay >> 8)); Serial.write((uint8_t)(ay & 0xFF));
        Serial.write((uint8_t)(az >> 8)); Serial.write((uint8_t)(az & 0xFF));
        Serial.write((uint8_t)(gx >> 8)); Serial.write((uint8_t)(gx & 0xFF));
        Serial.write((uint8_t)(gy >> 8)); Serial.write((uint8_t)(gy & 0xFF));
        Serial.write((uint8_t)(gz >> 8)); Serial.write((uint8_t)(gz & 0xFF));
    #endif

    // blink LED to indicate activity
    blinkState = !blinkState;
    digitalWrite(LED_PIN, blinkState);
}

MPU6050_Comms.zip (1.58 MB)

The I2C bus was designed for chip-to-chip communication on a single PCB, so expect major problems with wires longer than a few cm.

A much better idea is to use a small Arduino (e.g a $2 eBay Pro Mini) at the sensor location to collect the data, and send it elsewhere using a more robust transmission method.

jremington:
The I2C bus was designed for chip-to-chip communication on a single PCB, so expect major problems with wires longer than a few cm.

A much better idea is to use a small Arduino (e.g a $2 eBay Pro Mini) at the sensor location to collect the data, and send it elsewhere using a more robust transmission method.

Thanks for the reply. You're absolutely correct, the I2C protocol was indeed intended for on-board communication ("inter-integrated" after all), but anecdotally hobbyists regularly get 10-12 feet out of a bus without any buffering, and up to 100 feet with buffering. The largest concern with going off-board is the capacitance on the bus, seeing as the spec sets an upper limit of 400pF on the bus - not much. The stronger pullups and bus repeater combat this issue. I also chose CAT6E specifically over other networking cables because of its limited capacitance of a few pF per foot. See this 2017 article on Hackaday:
Taking The Leap Off Board: An Introduction To I2C Over Long Wires | Hackaday.
The comments section in particular is full of success stories at much greater distances without the need for differential communication.

My bus has proved itself for these "short" (it's all subjective and relative, I understand) distances, and this is not the longest transmission line on the bus. Each connection that goes off-board has its own TCA9517 to isolate that cable run. I have run this setup with 5 I2C devices simultaneously at varying lengths from the board, and have had no problems. My issue as far as I can tell is with the MPU6050 itself, as it can't communicate even when it is the only device hooked up. If anybody has insight as to what is happening on the line to prevent comms with the MPU6050, I would love insight there.

Please don't post zip files, it makes it harder to help you.

What pull up resistor values are you currently using?

Have you tried the TCA9517 locally without the CAT6 cable?

Can you post schematic for your TCA9517 board? Not as a zip, as an image?

anecdotally hobbyists regularly get 10-12 feet out of a bus without any buffering

A few do. Others regularly complain on this forum, and then find better solutions.

MarkT:
Please don't post zip files, it makes it harder to help you.

What pull up resistor values are you currently using?

Have you tried the TCA9517 locally without the CAT6 cable?

Can you post schematic for your TCA9517 board? Not as a zip, as an image?

Sure thing, just trying to get around the 2 MB maximum attachment size. Attached is the schematic for the I2C section of my board. Also attached is one of the SDA scope shots showing the problem I'm running into. Another apology for the quality of the scope capture - nothing on hand to store the file directly.

Pullups on the 5V side are 2.4k (3.3k in parallel with the 10k hardware pullups on the Mega 2560), pullups on the 3.3V side are 1.2k. The TCA9517 locally works as expected. It also functions fine with other I2C sensors with longer cabling. It's just the MPU6050 that causes problems.

Maybe it's obvious to others, but I'm struggling a little to understand your CommsBoard.png diagram.

Am I right in thinking that the I2C master MCU is connected through the TCA9517 to the MPU6050's AUX_SCL and AUX_SDA lines? Why the AUX lines and not the normal SCL and SDA?

arduarn:
Maybe it's obvious to others, but I'm struggling a little to understand your CommsBoard.png diagram.

Am I right in thinking that the I2C master MCU is connected through the TCA9517 to the MPU6050's AUX_SCL and AUX_SDA lines? Why the AUX lines and not the normal SCL and SDA?

Sorry, that's my nomenclature for the PCB at large - this is one of five off-board I2C lines. The "AUX" tag was because I hadn't settled on a specific sensor for this line at the time of manufacture. The other lines, for instance, are "RTC_SCL," "OLED_SCL," and so forth. I am using the main SDA and SCL lines on the MPU6050. The XCA, XDL, AD0, and INT pins are left floating on my GY-521. I've attached the whole schematic below, I was trying to keep things uncluttered. The MPU is on the line reserved for an auxiliary sensor.

I2C Board Rev 1.1.pdf (177 KB)

No pullup resistors on 5V SDA and SCL by the look of it.

MarkT:
No pullup resistors on 5V SDA and SCL by the look of it.

Pullups on the 5V side are 3.3k on the PCB in parallel with the 10k pullups present on the Mega 2560 for an equivalent pullup of 2.48k.

The I2C line functions perfectly fine on this port (the AUX sensor) with any of the other sensors plugged into it. It's just the MPU6050 that is unable to communicate because of the false logic level shown above in SDA1.jpg and SDA2.jpg above. I just can't figure out what is causing these false levels.

Bhewgill:
the GY-521 is being supplied with 3.3V (the onboard LDO regulator will produce 3.3V from as low as ~2.1V input), and the TCA9517 utilizes both voltages. I2C level on the Arduino side is 5V and logic level on the sensor side is 3.3V.

Feeding a LDO linear regulator with 2.1V and getting a 3.3V output seems a tad unlikely. Since these modules are produced en masse by some faceless Chinese factory, I can't find any really convincing specification for them; I would be suspicious that they would work reliably with anything much less than 5V.

Just throwing stuff at you in case something sticks.

By the way, what's the difference between the J2 and the J17 connections WRT the MPU?

arduarn:
Feeding a LDO linear regulator with 2.1V and getting a 3.3V output seems a tad unlikely. Since these modules are produced en masse by some faceless Chinese factory, I can't find any really convincing specification for them; I would be suspicious that they would work reliably with anything much less than 5V.

Just throwing stuff at you in case something sticks.

By the way, what's the difference between the J2 and the J17 connections WRT the MPU?

That's a great point - I swapped the connection from R20 to R21 to supply 5V to the MPU rather than 3.3V. Powered on, I measure 5.14V at the VCC pin of the MPU, but still see the same behavior on the serial monitor.
J2 and J16 are both RJ45 jacks, but J2 is on the B side of a TCA9517, so is being used for slave devices. J16 is connected to pins 20 and 21 of the Arduino (SDA and SCL) and is on the A side of all the TCA9517's. J17 was an option to mount the MPU directly to the PCB rather than have the sensor live off-board. That location works to read sensor values, but it turns out the MPU needs to be located off-board, which prompted the move to the J2 location.

Here's an image of the top side of the board to give a bit of an idea of the topology. The white CAT6 cable leads to the MPU, and the red CAT6 on the lower side of the image is connected to the Arduino. The TCA9517 chips are on the other side of the board, but each of the upper RJ45 jacks have their own buffer chip.

I have an old BNO055 that I'm going to breadboard up and then have a go through some CAT6, and I'll report back.

Thanks for all the suggestions so far guys, I appreciate it.

I set up my old BNO055 in the same method I've been using for all my I2C sensors, and it's working a treat. I'll just move forward with the BNO and shelve the MPU for the time being. Thanks for the help everyone. If anybody has insight as to the false I2C levels shown in earlier posts I'd still love to hear any ideas as to what's happening, but for the time being I've got my solution.

Hi guys,
I am a beginner, sorry. I want to work with this mpu and the sensor response the adress 0x68 tested with i2c scanner. When i do the programm imu from az delivery ebook i get the error : connection fail. What is the mistake?
I thank you for your help
Fridold