I2C port Pixy 2 data from Arduino not working

Not sure if anyone here has experience with Pixycam, but our code that used to work suddenly isn’t working? We’re thinking that there is an error with the i2c ports and that it just doesn’t work anymore? Since it had worked before.

Arduino Code:

#include <Pixy2.h>
#include <SPI.h>
#include <Wire.h>

//built in class from arduino, strongly suggest looking at it on their website
//it is not a complicated class

//this is provided by the pixy creators, you will have to go to the arduino sketch editor, 
//click sketch, include library, and import the pixy .zip files

//SETUP THE DEVICES

//plug sda on RoboRIO into A4
//plug scl on RoboRIO into A5
//connect the two grounds


String piOutput = "none";//string to be sent to the robot
               
String input = "blank";  //string received from the robot
const String PIXY = "pi";
Pixy2 pixy;

const int trigPin = 9;
const int echoPin = 10;

long duration;
int distance;

void setup(){
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  Serial.begin(9600);
  Wire.begin(4);                // join i2c bus with address #4 as a slave device
  Wire.onReceive(receiveEvent); // Registers a function to be called when a slave device receives a transmission from a master
  Wire.onRequest(requestEvent); // Register a function to be called when a master requests data from this slave device
  pixy.init();
}

void loop(){
  // Clears the trigPin
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  // Sets the trigPin on HIGH state for 10 micro seconds
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  // Reads the echoPin, returns the sound wave travel time in microseconds
  duration = pulseIn(echoPin, HIGH);
  // Calculating the distance
  distance = duration*0.034/2;
  // Prints the distance on the Serial Monitor
  Serial.print("Distance: ");
  Serial.println(distance);
  
  uint16_t blocks;
  blocks = pixy.ccc.getBlocks();//use this line to get every available object the pixy sees
  //^^^not sure what exactly this is for, honestly
  int biggest = -1;
  double area = 0, temp;
  for(int i=0;i<blocks;i++){
    //if(pixy.blocks[i].signature == 3) //if checking for an object and have more than one "type" or color to choose from
                         //use this line and choose the signature or "color" you want
      temp = pixy.ccc.blocks[i].m_width * pixy.ccc.blocks[i].m_height;
      if(temp > area){
        area = temp;
        biggest = i;
      }
  
      //that loops finds the biggest object since sometimes the object you are looking for becomes 
      //broken up into multiple, smaller, objects
  }
  if(!blocks){
    piOutput = String("none"); //if no blocks tell roborio there are none 
    //piOutput += "|";
    //piOutput += String(distance);
  }else{
    piOutput = String(pixy.ccc.blocks[biggest].m_x / 319.0);  //turns into a percent of the screen 
    piOutput += "|";                //inserts a "pipe" so robrio can split the numbers later
    piOutput += String(pixy.ccc.blocks[biggest].m_y / 199.0); //319 and 199 were, we found, the dimensions of the screen 
    piOutput += "|";          
    piOutput += String(area / 64000); 
    //piOutput += "|";
    //piOutput += String(distance);
  }
  Serial.println(piOutput);

  delay(1000); //gives time for everything to process
}

void requestEvent(){//called when RoboRIO request a message from this device
  Wire.write(piOutput.c_str()); //writes data to the RoboRIO, converts it to string

}

void receiveEvent(int bytes){//called when RoboRIO "gives" this device a message
}

Java Code:

package frc.robot;

import edu.wpi.first.wpilibj.I2C;
import edu.wpi.first.wpilibj.I2C.Port;

public class M_I2C {
	private static I2C Wire = new I2C(Port.kOnboard, 4);//uses the i2c port on the RoboRIO
														//uses address 4, must match arduino
	private static final int MAX_BYTES = 32;
	
	public void write(String input){//writes to the arduino 
			char[] CharArray = input.toCharArray();//creates a char array from the input string
			byte[] WriteData = new byte[CharArray.length];//creates a byte array from the char array
			for (int i = 0; i < CharArray.length; i++) {//writes each byte to the arduino
				WriteData[i] = (byte) CharArray[i];//adds the char elements to the byte array 
			}
			Wire.transaction(WriteData, WriteData.length, null, 0);//sends each byte to arduino
			
	}
	
	public PixyData getPixy(){//reads the data from arduino and saves it
		String info[] = read().split("\\|");//everytime a "|" is used it splits the data,
											//and adds it as a new element in the array
		PixyData pkt = new PixyData();  //creates a new packet to hold the data 
		if(info[0].equals("none") || info[0].equals("")){//checks to make sure there is data 
			pkt.x = -1;//the x val will never be -1 so we can text later in code to make sure 
					   //there is data
			pkt.y = -1;
			pkt.area = -1;
		}else if(info.length == 3){//if there is an x, y, and area value the length equals 3
			pkt.x = Double.parseDouble(info[0]);//set x
			pkt.y = Double.parseDouble(info[1]);//set y
			pkt.area = Double.parseDouble(info[2]);//set area
		}
		return pkt;
	}
	
	private String read(){//function to read the data from arduino
		byte[] data = new byte[MAX_BYTES];//create a byte array to hold the incoming data
		Wire.read(4, MAX_BYTES, data);//use address 4 on i2c and store it in data
		String output = new String(data);//create a string from the byte array
		int pt = output.indexOf((char)255);
		return (String) output.subSequence(0, pt < 0 ? 0 : pt);
	}

}

I just want to know if this is a hardware or software issue, most likely

Are the logic levels the same between the roborio and the I2C device?

Are you using old code from the first pixy cam? If so, the protocol is probably different. Also, the pixy2 doesn’t require an arduino to get its data to the roborio. You can directly write to and receive packets from the pixy2 via I2C with a custom cable.

Did you solve this issue?

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