I2C Link Cable

If we did everything by the book there would be no reason to write new books

5 Likes

Have you got any code you can share around this?

Sure!

//I2c arduboy

#include <Wire.h>
#include <Arduboy2.h>

Arduboy2 arduboy;

int x = 0;
int i2caddr = 0;
int i2cother = 0;
bool isdata = 0;

void setup() {

  arduboy.boot();
  arduboy.clear();
  arduboy.setTextSize(2);
  while ( arduboy.anyPressed(A_BUTTON | B_BUTTON) ) {}
  arduboy.println("Set Player");
  arduboy.println("A or B");
  arduboy.display();

  while ( i2caddr == 0 ) {
    arduboy.pollButtons();
    if ( arduboy.justPressed(A_BUTTON) ) {
      i2caddr = 7;
      i2cother = 9;
    }
    if ( arduboy.justPressed(B_BUTTON) ) {
      i2caddr = 9;
      i2cother = 7;
    }
  }

  Wire.begin(i2caddr);
  Wire.onReceive(receiveEvent);
  
}

void receiveEvent(int bytes) {
  x = Wire.read();   
  isdata = 1;
}

void loop() {
  
  arduboy.clear();

  if (i2caddr == 7) {
    arduboy.println("Player A");
  }
  if (i2caddr == 9) {
    arduboy.println("Player B");
  }

  arduboy.pollButtons();

  if ( arduboy.pressed(RIGHT_BUTTON) ) {
    Wire.beginTransmission(i2cother);
    Wire.write(1);
    Wire.endTransmission();
  }
  if ( arduboy.pressed(LEFT_BUTTON) ) {
    Wire.beginTransmission(i2cother);
    Wire.write(2);
    Wire.endTransmission();
  }
  if ( arduboy.pressed(UP_BUTTON) ) {
    Wire.beginTransmission(i2cother);
    Wire.write(3);
    Wire.endTransmission();
  }
  if ( arduboy.pressed(DOWN_BUTTON) ) {
    Wire.beginTransmission(i2cother);
    Wire.write(4);
    Wire.endTransmission();
  }
  if ( arduboy.pressed(A_BUTTON) ) {
    Wire.beginTransmission(i2cother);
    Wire.write(5);
    Wire.endTransmission();
  }
  if ( arduboy.pressed(B_BUTTON) ) {
    Wire.beginTransmission(i2cother);
    Wire.write(6);
    Wire.endTransmission();
  }

  if (isdata) {
    if (x == 1) {
      arduboy.println("RIGHT!");
    }
    if (x == 2) {
      arduboy.println("LEFT!");
    }
    if (x == 3) {
      arduboy.println("UP!");
    }
    if (x == 4) {
      arduboy.println("DOWN!");
    }
    if (x == 5) {
      arduboy.println("A!");
    }
    if (x == 6) {
      arduboy.println("B!");
    }
    
    isdata = 0;
    
  }

  arduboy.display();
}

Update: you also have to remove the power saving feature from the library as it disables i2c.

Is this code in the setup implying that you need to know which device is A is which is B?

Do you think its possible to have the two devices periodically sending a byte on either 9 or 7 and waiting to hear something back on the other (7 or 9) as a rudimentary way of negotiating who is who? As soon as they get a signal from the other devce, they look in their current settings and start playing?

I’ve got no idea how hard or what the story is on trying to auto handshake i2c, it’s probably possible. You could send high pulse over the line first and whoever sends the signal first gets to be the master then you init off of that. It’s just the wire library for arduino nothing special going on here, you can replicate the hardware with any two arduinos to test it out.

Or with the mini :slight_smile:

You can get access to one by making a tutorial for the SH1106

LOL … not sure I know how.

Also, would probably need TWO.

Right. The callback is asynchronous I assume?

yeah i2c is just 2 wires, a clock and signal, works like a walkie talkie each device has to take turns i forget exactly how it works but yeah

1 Like

Made me actually LOL… :rofl:

regarding the pull ups. from section 20.5.1 of the datasheet:

Note that the internal pull-ups in the AVR pads can be enabled by setting the PORT
bits corresponding to the SCL and SDA pins, as explained in the I/O Port section. The internal pull-ups can in some systems eliminate the need for external ones.

Note that because those pullups are relatively high, the distance and speed of i2C link will be limited.

Note 2 when using the Arduino Wire library the internal pullups are activated :slight_smile:

2 Likes

I suspected that may be the case, when I saw in the link that @bateske posted, that the two Uno’s were working back to back without pullups. However, as quoted, such weak pullups would likely not allow very long cables.

You could, though, make a custom cable with pullups built into the cable itself.

@bateske since you need to make some design changes to the mini. Would it be possible to add some solder pads /jumpers to optionally connect i2c to those usb-c pads?

Also how long of an usb-c cable did you test with the build in pullups?

1 Like

1 meter cable

Probably won’t make the usb-c change to the mini, since you’ve already got the i2c pins

I bet you it would work for like 20 feet

Yes, and they are on the top, which is more convenient. Also, by linking via Qwiic you would still be able to power from USB at the same time.

Maximum cable length will be somewhat dependent on the I²C clock speed. The fact that USB cable is shielded might also be a factor.

Works over 25 feet of two different hdmi cables using the shield ground as a conductor.

Considering unrolling a spool of wire for science

Got two more of those HDMI cables? and two more crocodile clips? then you can double the length :slight_smile:

i2c over a bowl of salty water???

works

(tested somewhere around 2mega ohm of resistance)

Ok now i need a second person I think we can do this with meatbag signal transmission.

1 Like

Doing rough math doesn’t this mean I could send the signal over like a mile of ethernet cable?

At some point, the capacitance of the cable starts to affect things. That’s why it’s also dependent on clock speed and pullup strength.

Well anyways, there are pullup resistors on the mini, there are not pull up resistors on the fx-c which may or may not have i2c pins broken out to the sba1 and 2 pins, so the link cable should work on the fx-c

I haven’t tested it so once I get the prototypes in for those I’m going to redo the store page with the new features.