It's 🐍CircuitPython Monday🐍 at Adafruit! Use the code ADATY to get 20% off CircuitPython and 15% off items storewide!
0

I2c extender falling short
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

I2c extender falling short

by SkyRyder on Sun Oct 24, 2021 12:29 pm

Hi all, I have the I2C Extender / Active Terminator - STEMMA QT / Qwiic 4756 attached to a Metro Express Airlift... with I2C wires that are about 24" total... working great.

But then adding 20 feet of CAT6 twisted pair to the setup seems to fail.

The twisted line for data and clock are connected to ground on both ends of the run... which I think is how to reduce noise as much as possible.

The extender is supposed to be good for about 100 feet... so 20 feet shouldn't be an issue.

Why might this be failing?

Thank you for your kind help

SkyRyder
 
Posts: 45
Joined: Fri Mar 06, 2020 6:05 pm

Re: I2c extender falling short

by mikeysklar on Tue Oct 26, 2021 5:17 pm

Did you double up the eight conductors on the ethernet? Each pin Vcc/GND/SDA/SDL getting two pins?

Have you tried lowering the i2c bus speed just to confirm that communication was going through at a lower rate?

mikeysklar
 
Posts: 6184
Joined: Mon Aug 01, 2016 8:10 pm

Re: I2c extender falling short

by adafruit2 on Wed Oct 27, 2021 1:22 pm

do *not* twist data or clock with ground. that increases capacitiance and its not differential! use a scope to look at your traces at the end of the line

adafruit2
Site Admin
 
Posts: 20343
Joined: Fri Mar 11, 2005 7:36 pm

Re: I2c extender falling short

by SkyRyder on Wed Oct 27, 2021 6:54 pm

Well, they are twisted pairs (which are supposedly a good thing with respect to noise...

But as they are physically twisted, should I twist data and clock with a conductor that is not connected at either end?

Also, I don't know how to lower the I2C data rate...

what is the normal rate, and the command to set a lower one?

Thank you!

SkyRyder
 
Posts: 45
Joined: Fri Mar 06, 2020 6:05 pm

Re: I2c extender falling short

by mikeysklar on Wed Oct 27, 2021 6:55 pm

@SkyRyder,

What example code are you running? Is it Arduino or Python? Can you paste it in CODE tags here?

mikeysklar
 
Posts: 6184
Joined: Mon Aug 01, 2016 8:10 pm

Re: I2c extender falling short

by SkyRyder on Wed Oct 27, 2021 7:58 pm

mikeysklar wrote:@SkyRyder,

What example code are you running? Is it Arduino or Python? Can you paste it in CODE tags here?


Thank you for your help...

Code: Select all | TOGGLE FULL SIZE
//  TFT display resolution 320x240 (rotation 1)
//version 2.3 adds arrays to help with defining and handling different regions.
//  Adds a message display area.  Updates Temperature display.

//version 2.2 gets rid of writing to the serial port... instead
//  sending messages to the display.  We also add a button to
//  drive the relay
//  What's this < > thing? With < >, the compiler searches INCLUDE directories for the file.
//  With quotes, the compiler searches the INCLUDE directories and the *current directory*.

#include "Adafruit_MCP9601.h"       //for thermocouple

#include "SPI.h"                    //for display
#include "Adafruit_GFX.h"           //for display
#include "Adafruit_ILI9341.h"       //for display
#include <Adafruit_FT6206.h>        //for display

#include <Wire.h>                   //for relay
#define COMMAND_RELAY_OFF 0x00      //for relay
#define COMMAND_RELAY_ON 0x01       //for relay
#define COMMAND_CHANGE_ADDRESS 0x03 //for relay

//The actual default address is SUPPOSED to be 0x18, but 0x19 is what works!
volatile byte qwiicRelayAddress = 0x18;           // Set Address for relay

// The FT6206 uses hardware I2C (SCL/SDA)
Adafruit_FT6206 ts = Adafruit_FT6206();           //for touch screen

boolean ValveCondition = false;                   // don't know what this is
boolean FingerUp = true;                          // touch latch for TS

// For the Adafruit shield, these are the default.
#define TFT_DC 9                                  // for display but what?
#define TFT_CS 10                                 // for display but what?


#define TEMP1_ADDRESS (0x67)                      //for thermocouple
Adafruit_MCP9601 mcp;                             //for thermocouple

// Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);

int PumpButton[] = {220, 1, 100, 50};             //an array that holds the region used for the pump button
int WaterTempDisplay[] = {0, 50, 100, 50};        //an array that holds the region used to display temp
int MsgDisplay[] = {0, 214, 319, 25};             //an array that holds the region used to display messages
int TempDisplay[] = {92, 100, 75, 50};            //an array that holds the region used to display the temperature
int ClrScreen[] = {290, 210, 30, 30};             //an array of a hidden button intended to clear the screen

void setup()
{
  // this needs to be here so that we can stop code from executing (by not opening a serial monitor
  // in case there is some lock up situation.
  Serial.begin(9600);
  while (!Serial) {
    delay(10);
  }

  // we will now start with the display so we can send messages to it
  // instead of the serial port
  tft.begin();                              // start display process?
  delay(10);                                // delay needed to prevent display inversion?

  testFillScreen();                         // makes some flashy screens
  delay(500);
  tft.setRotation(1);                       // initialize the desired screen rotation
  tft.fillScreen(ILI9341_BLACK);
  yield();
  tft.setTextColor(ILI9341_GREEN, ILI9341_BLACK);
  tft.setTextSize(1);

  tft.println("Display Enabled");           // Send to display

  // ts.begin(40);                          // start touch screen
  // tft.println("Touchscreen Enabled");    // Send to display

  // This may not be needed since the TC module is also using Wire
  Wire.begin();                             // join the I2C Bus (relay)
  //Wire.setClock(10000);                     // set I2C to only 10% of standard
  Wire.beginTransmission(qwiicRelayAddress); // transmit to device
  delay(100);
  //check here for an ACK from the slave
  tft.println("begin wire transmission test");
  if (Wire.endTransmission() != 0 ) {
    tft.println("Check Connections. Slave not found.");
  }
  else {
    tft.println("Qwiic Relay found at 0x19!");
  }

  relayOff();                               //set relay to non-ambiguous state

  // required or subsequent mcp call fails
  delay (10);                               // only 1ms required

  /* Initialise the driver with XXX_ADDRESS and the default I2C bus. */
  if (! mcp.begin(TEMP1_ADDRESS)) {
    tft.println("Thermocouple not found. Check wiring!");
    //while (1);
  }

  mcp.setADCresolution(MCP9600_ADCRESOLUTION_18);   //set TC resolution to 18 bits
  mcp.setThermocoupleType(MCP9600_TYPE_K);          //set TC type to K
  mcp.setFilterCoefficient(3);                      //not sure what this does
  mcp.enable(true);                                 //not sure what this does

  tft.println("Thermocouple Enabled");              // Send to display

  delay(2000);                                      //let messages linger before we continue

  tft.fillScreen(ILI9341_BLACK);                    //clear screen after setup
  ValveBtn(0, PumpButton);                          //initialize button and valve states to closed

  DispMsg("Display Message test.");
}


//why is void in the arguments?  because it doesn't return a value
void loop(void) {

  tft.setCursor(0, 0);
  //text color to green and background to black
  tft.setTextColor(ILI9341_GREEN, ILI9341_BLACK);
  tft.setTextSize(2);
  tft.println("Tiny Recirculator");
  tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);

  DispTemp(mcp.readThermocouple());


  // See if there's any touch data for us
  // we need a latch so that a finger has to come UP first
  if (ts.touched()) {
    delay(15);                                //psudo-debounce

    if (CheckTouch(ClrScreen) == true) {      //check hidden button touch
      tft.fillScreen(ILI9341_BLACK);
    }

    if (CheckTouch(PumpButton) == true) {     //check for a touch in the PumpButton region
    if (FingerUp == true) {                   //only continue if finger was not down prior
        FingerUp = false;                     //flag the finger on the button
        if (ValveCondition == true) {         //if the valve condtion is open, close it
          ValveBtn(0, PumpButton);            //close valve
        }
        else {                                // ValveCondition == false
          ValveBtn(1, PumpButton);            //open valve
        }
      }
    }
  }
  else {                          //finger was not touching... let's remember this
    FingerUp = true;
  }
}


/* Begin function definitions....   */

unsigned long testFillScreen() {
  unsigned long start = micros();
  tft.fillScreen(ILI9341_BLACK);
  yield();
  tft.fillScreen(ILI9341_RED);
  yield();
  tft.fillScreen(ILI9341_GREEN);
  yield();
  tft.fillScreen(ILI9341_BLUE);
  yield();
  tft.fillScreen(ILI9341_BLACK);
  yield();
  return micros() - start;          // this calculates how long it took to fill screen
}

//The following is a whack text display... needs much work
unsigned long testText() {
  tft.fillScreen(ILI9341_BLACK);
  unsigned long start = micros();
  tft.setCursor(0, 0);
  tft.setTextColor(ILI9341_GREEN);
  tft.setTextSize(2);
  tft.println("Tiny Recirculator");
  tft.setTextSize(1);
  tft.println("Ver 1.0");
  return micros() - start;
}

void relayOn() {
  Wire.beginTransmission(qwiicRelayAddress);
  Wire.write(COMMAND_RELAY_ON);
  if (Wire.endTransmission() != 0) {
    DispMsg("Check Connections. No slave attached");
  }
}


// RelayOff() turns off the relay at the qwiicRelayAddress
// Checks to see if a slave is connected and prints a
// message to the Monitor if no slave found.
void relayOff() {
  Wire.beginTransmission(qwiicRelayAddress);
  Wire.write(COMMAND_RELAY_OFF);
  if (Wire.endTransmission() != 0) {
    DispMsg("Check Connections. No slave attached");
  }
}


void DispTemp(float theTemp) {
  tft.setTextColor(ILI9341_GREEN, ILI9341_BLACK);
  tft.setCursor(TempDisplay[0], TempDisplay[1]);
  tft.setTextSize(1);
  tft.println("Temp (F):");
  tft.setCursor(TempDisplay[0], TempDisplay[1] + 12);
  tft.setTextSize(5);
  tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
  tft.print(theTemp * 1.8 + 32);                          //convert c to f before displaying
}



void DispMsg( String theMsg) {
  tft.setTextSize(2);
  tft.setTextColor(ILI9341_GREEN, ILI9341_BLACK);
  tft.setCursor(MsgDisplay[0] + 2 , MsgDisplay[1] + 10);
  tft.print(theMsg);
  tft.print("                                                      ");
}

void ValveBtn(int ValveState, int TheRegion[])       // 0="CLOSE" 1="OPEN" 2="TOGGLE", region array
{
  //tft.drawRect(OFFBUTTON_X, OFFBUTTON_Y, OFFBUTTON_W, OFFBUTTON_H, ILI9341_GREEN);

  //add some code here to set for valve state 2: toggle to force valve state to 0 or 1
  tft.drawRect(TheRegion[0], TheRegion[1], TheRegion[2], TheRegion[3], ILI9341_BLUE);
  tft.setTextSize(2);
  switch (ValveState) {
    case 0:
      tft.setTextColor(ILI9341_BLUE, ILI9341_BLACK);
      tft.setCursor(TheRegion[0] + 14 , TheRegion[1] + 18);
      tft.println("CLOSED");
      relayOff();                               //turn off relay
      ValveCondition = false;                   //false is closed
      break;

    case 1:                                     //open the valve
      tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
      tft.setCursor(TheRegion[0] + 14 , TheRegion[1] + 18);
      tft.println(" OPEN ");
      relayOn();                                  //turn on relay
      ValveCondition = true;
      break;
  }
}

boolean CheckTouch(int TheRegion[])
{
  TS_Point p = ts.getPoint();                   // Retrieve a point
  delay(15);                                    //psudo-debounce

  if (FingerUp == true) {                       // only do something if finger is touching but wasn't

    // rotate coordinate system
    // flip it around to match the screen.
    p.x = map(p.x, 0, 240, 240, 0);
    p.y = map(p.y, 0, 320, 320, 0);
    int y = tft.height() - p.x;
    int x = p.y;

    //check to see if we are touching the button
    if ((x > TheRegion[0]) && (x < (TheRegion[0] + TheRegion[2]))) {
      if ((y > TheRegion[1]) && (y <= (TheRegion[1] + TheRegion[3]))) {
        return true;                              // terminate function & return true if region was touched
      }
    }
  }
  return false;                                   // terminate function & return false if region was not touched
}

SkyRyder
 
Posts: 45
Joined: Fri Mar 06, 2020 6:05 pm

Re: I2c extender falling short

by SkyRyder on Wed Oct 27, 2021 8:27 pm

mikeysklar wrote:Did you double up the eight conductors on the ethernet? Each pin Vcc/GND/SDA/SDL getting two pins?

Have you tried lowering the i2c bus speed just to confirm that communication was going through at a lower rate?


I set the clock speed to 10,000 and I did not see a difference... I'm not sure that is a valid speed though.

SkyRyder
 
Posts: 45
Joined: Fri Mar 06, 2020 6:05 pm

Re: I2c extender falling short

by SkyRyder on Wed Oct 27, 2021 8:54 pm

Here is a photo of the clock read at only 24 inches from the metro express airlift.
(See more photos)
Attachments
0804A1F4-3887-4D2E-B8FC-F27C278C446F.jpeg
0804A1F4-3887-4D2E-B8FC-F27C278C446F.jpeg (89.65 KiB) Viewed 90 times

SkyRyder
 
Posts: 45
Joined: Fri Mar 06, 2020 6:05 pm

Re: I2c extender falling short

by SkyRyder on Wed Oct 27, 2021 8:58 pm

Here is the clock when connected to 20’ of cat 6 wire… measured at about 22’ total length
Attachments
CB71539E-D059-4DFE-9AED-AF420F37FF24.jpeg
CB71539E-D059-4DFE-9AED-AF420F37FF24.jpeg (89.76 KiB) Viewed 89 times

SkyRyder
 
Posts: 45
Joined: Fri Mar 06, 2020 6:05 pm

Re: I2c extender falling short

by mikeysklar on Thu Oct 28, 2021 12:14 pm

Thank you for the scope pics and trying the lower i2c speed.

Can you show how you have connected the cat-5 cable? Maybe it is an increased capacitence issue as @adafruit2 suggested or something else that will be obvious from photos.

mikeysklar
 
Posts: 6184
Joined: Mon Aug 01, 2016 8:10 pm

Re: I2c extender falling short

by SkyRyder on Fri Oct 29, 2021 2:36 am

On one side I've got a terminal block and I plug in a standard ethernet connector. That connector is wired directly to the solder terminals on the I2C extender (which is connected to the metro board 20 inches away).

20 feet later, the cable goes to another network connector to a terminal block that connects to i2C modules just a few inches away.

I've tried with clock and data twisted together, clock+ gnd and data+gnd twisted together, and then just separate data and clock lines, twisted with disconnected wires.

All look the exact same on the o-scope.

is it possible it's a power issue over that distance?

SkyRyder
 
Posts: 45
Joined: Fri Mar 06, 2020 6:05 pm

Re: I2c extender falling short

by mikeysklar on Fri Oct 29, 2021 10:29 am

I'll need to see a diagram or photo of how you are using the twisted pairs. I understand what you are saying about trying different combinations of CLK and GND twisted together or with their ground, but there are 8-pins on an RJ-45 so I'd like to see how you are using all of them and ganging or not of the connections.

I've used RJ-45 in a lot of projects and found it to be an excellent conductor when using two pin pairs that are pre-twisted for the same signal.

I don't think it will be a power issue over this distance, but the way to test would be to start cutting the length of the cable into halves to see where the failure occurs after we verify the pinouts.

mikeysklar
 
Posts: 6184
Joined: Mon Aug 01, 2016 8:10 pm

Re: I2c extender falling short

by adafruit_support_bill on Fri Oct 29, 2021 11:11 am

Judging from the shape of the waveform, it doesn't look like a problem with capacitance. The rise time is nice and crisp with just a bit of overshoot. But it doesn't look even remotely like your clock signal either.

Your scope is showing a clock frequency of about 4.2 KHz with the short cabling. With the long cable your scope is saying just 170 Hz (!?!)

If you look at the schematic, the signal on the board is connected straight through from one side to the other. The LTC4311 is just an active pullup. What you see on the other end of your cable should at least be the same frequency as what goes in. If not, you must have something connected wrong.

https://learn.adafruit.com/adafruit-ltc ... /downloads

adafruit_support_bill
 
Posts: 82399
Joined: Sat Feb 07, 2009 10:11 am

Re: I2c extender falling short

by adafruit2 on Fri Oct 29, 2021 1:56 pm

yah are you sure you have it wired right? those are squariest square waves. thats not the issue

adafruit2
Site Admin
 
Posts: 20343
Joined: Fri Mar 11, 2005 7:36 pm

Please be positive and constructive with your questions and comments.