Arduino I2C RoboRIO Communication

Hey! I’m trying to transmit a few bytes from an Arduino to the RoboRIO through I2C.

Here is my read() method
private I2C i2c;
private final int MAX_SIZE = 8;

public VisionSubsystem() {
    i2c = new I2C(Port.kOnboard, 0);
}

@Override
protected void initDefaultCommand() {
    setDefaultCommand(new DefaultVisionCommand());
}

/**
 * Returns the target data received from the arduino
 * @return PixyPacket with length of 2 (ALWAYS) - **CAN RETURN NULL**
 * PixyPacket[0] gives you the first vision target
 * PixyPacket[1] gives you the second vision target
 */
public PixyPacket[] read() {
    byte[] data = new byte[MAX_SIZE]; 
    i2c.readOnly(data, 8); //read arduino
    PixyPacket[] packets = new PixyPacket[2]; //if the data received is not null, and is the size of 8 
    int x1 = data[0];
    int y1 = data[1];
    int width1 = data[2];
    int height1 = data[3];
    packets[0] = new PixyPacket(x1, y1, width1, height1);

    int x2 = data[4];
    int y2 = data[5];
    int width2 = data[6];
    int height2 = data[7];
    packets[1] = new PixyPacket(x2, y2, width2, height2);
    return packets;
}

And my arduino code - intended to write to RoboRIO

#include <Wire.h>
#include <Pixy.h>
#include <Servo.h>

#define MIN_WIDTH 0; //TBD
#define MAX_WIDTH 0; //TBD
#define MIN_HEIGHT 0; //TBD
#define MAX_HEIGHT 0; //TBD

Pixy pixy;
Servo servo;
byte data[8];

void setup() {
Serial.begin(9600);
Wire.begin(0);
pixy.init();
delay(500);
}

void loop() {
Wire.begin(0);
int blocks = pixy.getBlocks();
data[0] = pixy.blocks[0].x;
data[1] = pixy.blocks[0].y;
data[2] = pixy.blocks[0].width;
data[3] = pixy.blocks[0].height;
data[4] = pixy.blocks[1].x;
data[5] = pixy.blocks[1].y;
data[6] = pixy.blocks[1].width;
data[7] = pixy.blocks[1].height;
pixy.blocks[0].print();
pixy.blocks[1].print();
Wire.write(data, 8);
delay(100); //prevent lag in the arduino
}

Any help is much appreciated!

The i2c.readOnly() method returns a boolean (true for dropped communication, false for no dropped communication). I would suggest filtering all your bad values out in this way.

Also can you describe your problem a bit better? Are you unable to receive information on the roborio?

1 Like

Hi, thanks for reaching out!
Sorry, I’m a little new to this. I hope I can get this thing working for my team.

Right now, I’m trying to receive some byte[] data from my arduino uno which is connected to a Pixy cam. I only want two blocks of information which holds the x, y, width and height. So data[0] would be x, data[1] would be y, data[2] would be width, and data[3] would hold height; and so forth for the next block until data[7].

I’m also a little confused on what the ‘registerAddress’ would be. I’ve replaced the readOnly() method in my code to read() and has the following parameters:
read (int registerAddress, int count, byte[] buffer)

Same goes for the I2C object I have in java. On the top, the constructor for I2C is (Port port, int deviceAddress) also don’t know what to put for the deviceAddress.

As for the arduino code, I’m pretty sure Wire.write(byte[] buffer, int size) is the way to go, but I also see a beginTransmission(address) and endTransmission(address) in the documentation, which I’m not too sure goes in as arguments as well. If I were to use Wire.begin() without any arguments, it would join the bus as a ‘master’ which I don’t entirely understand. It has an optional parameter for an address, which I believe would have to go also in the beginTransmission(address) and endTransmission(address) argument?

If you or anybody else out there can help me, it would be greatly appreciated!

I don’t think the arduino has a register address. You want to keep using readOnly(). However, on the arduino side of things, checkout the function onRequest(). When the rio calls readOnly(), the arduino runs the function specified in the parameter of onRequest().

We wrote some I2C Arduino to RoboRio communication this year. Our code is in C++ but it should be similar to java. A register address is basically used to differentiate devices using the same I2C wires. This allows communication between multiple devices all connected to the same wires. In your application, you are using the Arduino as a slave device and the Roborio as a master. Here is a good example to look at on how to set up the Arduino: http://dsscircuits.com/articles/arduino-i2c-slave-guide .

Looking at your code, I see you’re using Wire.write() and you said you’re trying to use BeginTransmission and End Transmission. These are functions generally used on master devices. Instead, you should setup a new function called requestEvent() and use Wire.send() as the page describes.

Look at your data types as well. We haven’t used pixyCam’s before but the data you are receiving from it is integers. Any communication you send over I2C wires is in bytes. An integer is equal to 4 bytes so if you want to send 8 integers over I2C you will need to send 32 bytes. This is going to be a little difficult because you will need to convert your integer on the arduino side to 4 bytes and then parse those 4 bytes on the Roborio side back to an integer. We found it easier to convert it a byte into an array of chars because each char is equivalent to a byte making it easier to parse the byte back into a char on the Roborio side and then to a number. I would highly recommend attempting to only send a simple “hello” message at the beginning to ensure that your basic I2C communications are working. You should connect the ground, SDA, and SCL lines, no need to connect the power lines.

I hope you can get this working!

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.