Is anybody successfully using RoboRIO I2C?

We have a pixy2 working over I2C, but had to get 5V from the VRM (since the I2C port only has 3.3V available).

Do you have any idea what what I2C clock speed that device operates at? With an Arduino connected to the I2C, we found that we had to set the clock speed on the Arduino to match that of the RoboRio.

Wire.setClock(400000); // set clock speed to fast to match RoboRio I2C clock speed

Yes. The arduino was powered through the voltage regulator module.

We’ll have a closer look at this too. I can’t think of why the onboard I2C would use/expect a different clock speed than the one coming through the MXP breakout, but clearly something is different between them.

Looking at the pixy2 docs, it looks like they have internal pullups, so that’s a point for that theory. Looking at the line follower schematic, I don’t see internal pullups. It’s still unclear why it works through the MXP port though, as I don’t see any pullups there either.

We will definitely give it a try with external pullups, probably later this week. We’ll post our findings.

Clearly others are seeing similar problems, so if something works for us maybe it will help them too.

Thanks to all for the input!

We use the roborio i2c directly to an arduino for led controls.

roborio code:

final I2C arduino = new I2C(Port.kOnboard, 4);
final String data = "ENABLED:000";
boolean success = arduino.transaction(data.getBytes(), data.getBytes().length, new byte[0], 0);

arduino code:

String state = "";
String additionalInfo = "";
boolean stateChanged = true;

void setup() {
  Wire.begin(4);
  Wire.onReceive(receiveEvent);
}

void receiveEvent(int howMany) {
  String input = "";

  while (Wire.available() > 0) {
    char n = (char) Wire.read();
    if (((int) n) > ((int)(' '))) {
      input += n;
    }
  }

  int index = input.indexOf(':');
  if (input.substring(0, index) != state) {
    stateChanged = true;
  }

  state = input.substring(0, index);
  additionalInfo = input.substring(index + 1);
}

We use both I2C ports (Normal Onboard and Onboard MXP) with one Rev Robotics Color Sensor on each. They seem to work well.

Are you using external pullup resistors on either port?

I haven’t looked at it in awhile, but I seem to remember that the roboRIOI I2C port is at 400 kHz, 3.3v but 5v tolerant (substitute 5v from DIO power pin, MXP 5v or PI 5v).
Make sure you use the voltage required by your device.
The RoboRio I2C library uses 7 bit addressing (1 - 128) and 112 is the default address of the RoboRio. An Arduino, for example, uses 8 bit addressing. The clock and data I2C lines on the roboRIO have 2.2kOhm pullup resistors to 3.3v, so make sure that’s compatible with the I2C device.

The MXP I2c shares DIO 14/15 pins and those have a pullup, too.
MXP_DIO-I2C_Circuits

We’re using external pullup resistors on the MXP port. We’re not using any on the normal onboard port. Both I2C devices work as expected. After reading the NI roboRIO User Manual (refer to diagram that @Mark_McLeod posted) , I’m not even sure if the pullup resistors were needed.

There is one difference between the MXP and “Onboard” I2C ports, per a discussion I had with Joe Hershberger of National Instruments. The I2C circuitry is implemented differently for each. At an implementation level, the MXP I2C port is implemented by the ARM core included in the Xilinx chip in the RoboRIO; the Onboard I2C is implemented in the RoboRIO FPGA code. So it’s definitely possible the behaviors are not identical. One way to get to the bottom of this is to use Logic Analyzer and connect the same device to both ports, and observe the differences. There are some very low cost logic analyzers (e.g., from companies like Salaeae) that can capture the I2C traffic and decode the I2C protocol. I think this is a very powerful learning experience about protocols for students with sufficient interest.

1 Like

navX-MXP does not include pullup resistors on the MXP I2C signals; this decision was made because (as mentioned earlier in this thread) pullups are included on the RoboRIO side; per the RoboRIO User’s manual both SDA and SCL have 2.2K pullups to 3.3V within the RoboRIO.

One difference is… that they’re completely different implementations :slightly_smiling_face:

At a 1000 foot level, this explains a lot. This is above my pay grade, but our EE mentor can certainly run with this. Thank you again, and we’ll post back anything we learn. It will be a learning experience for more than just the students.

Yes, we are using a logic level converter. It seems to be doing what it’s supposed to, as it works fine on the MXP port and at least for a while on the onboard.

If you’re actually diving into I2C protocol, it’s actually an interesting and relatively complex protocol. The most simple modes of operation are straightforward, but there are features like the Repeated Start Condition that make it more complicated. Certain devices keep it simple and stay on the well-beaten path, but other devices use some of these features. So this adds up to some devices working fine on different implementations, but some devices behaving differently. Based on that, I’m recommending your team review the protocol used by the device in question, to understand what I2C features it is requiring. Then with the logic analyzer you can review the different transaction types under the microscope and find the trouble area.

If you look at the device at the link in the first post, it sure looks simple. It’s not particularly well documented, though there is Arduino sample code available, and it looks pretty simple too. While what you suggest sounds like an interesting learning exercise, it’s probably not going to happen near term. The immediate problem is that we have a nice working lateral position sensor on our hatch end and we’d like to add one to our ball handler too. If there’s not an easy fix other things will probably take priority between now and Detroit.

Longer term, I do hope we can figure out how to run this device, as it’s a much more compact and precise tape-following setup than many we’ve seen.

I would also hope the NI and WPI folks will pay attention and give us a few more hints as to what their “I2C” hardware and software do and don’t actually support.

I dug around awhile looking at the sensor you referenced. The board referenced has an onboad STM8 microcontroller that implements the I2C protocol; no documentation on the firmware implementation that would implement the protocol is provided, the vendor should provide that in my opinion.

The only clue I can see in the “test code” on the product site I can see is:

// slave may send less than requested

Just a thought, but you might consider what that comment actually means with respect to the protocol, and whether your translation to the RoboRIO platform covers that case. It’s possible for instance the RoboRIO requires all bytes to be sent using the I2C API call used to communicate with it and doesn’ handle this strange case of slave sending less data than requested (I’m not an I2C protocol expert, but that seems strange).

  • scott

The other thing to consider is timing. Since this board handles the I2C protocol via a microcontroller, it won’t be able to respond as quickly to the initial request for data as an I2C protocol implemented in circuitry (e.g., an FPGA or ASIC). That’s probably why the repeated start request is not used in that sample code. It might be that the timing with the onboard I2C implementation is just different enough than that of the MXP I2C interface that with the roboRIO code you’re using to access it, the microcontroller (responding via interrupts, likely) can’t respond quickly enough to the request. That’s a wild guess, but perhaps this line of thinking could lead to an answer.

We successfully used I2c to talk to a lidar range finder in 2017.
Our source code is here:
https://github.com/Team537/RobotCode2017/blob/master/Competition2017/src/org/team537/robot/subsystems/Lidar.java

We relied on former posting on Chief Delphi that said they needed a pullup resistor between SCL and 5 volts.

We also ran the fetching code in a separate thread so the startup and fetching of values would not impact the main robot loop.

1 Like

What was the make and model of your lidar?