Pixy Visual Tracking. HELP!

So, I am wondering exactly how to use Pixy. (Pixy, the visual recognition camera with Arduino.) There are plenty of tutorials out there... but not what I need! All the tutorials show how to use the Pan/Tilt example. All I want is this:

When the pixy detects something near the left of the view, it does the detectleft() function. When the pixy detects something to the right, it does the detectright() function, How the heck do I code this?!?!?!?! Could you give me some example code? (If you give me some code, please cover it with a bunch of notes so I know what piece of code does! :slight_smile: )

The only wiring is the Pixy connected to the Arduino with it's special cable, and a LED on Pin 4. In the detectleft() function, the LED flashes 1 time, and in the detectright() function, the LED flashes 2 times.

PLEASE PLEASE PLEASE! Give me some code for this, it is REALLY appreciated! :slight_smile: :slight_smile: :slight_smile:

When the pixy detects something near the left of the view, it does the detectleft() function.

What detectleft() function are you talking about? Some context would be useful.

So would links to the hardware and libraries you are using, and your damned code.

When the pixy detects something near the left of the view, it does the detectleft() function.

The Pixy returns the coordinates of the centroid of the object, doesn't it?
So, if x is less than some threshold, call "detectLeft".

You may want to make sure that you haven't detected more than one object by retrieving the whole list, maybe even produce the average centroid of all the objects detected, and make your decision based on that.

Edit: I just looked at the pan/tilt example - it virtually does all you want.

But see I don't grasp the pan tilt.... Can someone please please please give me some sample code for what I described... I have never done anything quite on this level so this is new to me.... can you please provide some starter code?

Just pick the pan tilt code apart - it tests to see there's at least one object there.
Use that object's x coordinate and see if that value is less than some threshold that says it is on the left hand side of the image
Forget the servo class that's in there - just bin it..

I'm sorry, I'm posting from a tablet, and I don't have the code in front of me, but your code will be shorter than the pan tilt code.
A lot shorter.

Here is the normal Pan Tilt Example, if you would like to see it.

//
// begin license header
//
// This file is part of Pixy CMUcam5 or "Pixy" for short
//
// All Pixy source code is provided under the terms of the
// GNU General Public License v2 (http://www.gnu.org/licenses/gpl-2.0.html).
// Those wishing to use Pixy source code, software and/or
// technologies under different licensing terms should contact us at
// cmucam@cs.cmu.edu. Such licensing terms are available for
// all portions of the Pixy codebase presented here.
//
// end license header
//
// This sketch is a simple tracking demo that uses the pan/tilt unit.  For
// more information, go here:
//
// http://cmucam.org/projects/cmucam5/wiki/Run_the_Pantilt_Demo
//

#include <SPI.h>  
#include <Pixy.h>

Pixy pixy;

#define X_CENTER        ((PIXY_MAX_X-PIXY_MIN_X)/2)       
#define Y_CENTER        ((PIXY_MAX_Y-PIXY_MIN_Y)/2)

class ServoLoop
{
public:
 ServoLoop(int32_t pgain, int32_t dgain);

 void update(int32_t error);
  
 int32_t m_pos;
 int32_t m_prevError;
 int32_t m_pgain;
 int32_t m_dgain;
};


ServoLoop panLoop(300, 500);
ServoLoop tiltLoop(500, 700);

ServoLoop::ServoLoop(int32_t pgain, int32_t dgain)
{
 m_pos = PIXY_RCS_CENTER_POS;
 m_pgain = pgain;
 m_dgain = dgain;
 m_prevError = 0x80000000L;
}

void ServoLoop::update(int32_t error)
{
 long int vel;
 char buf[32];
 if (m_prevError!=0x80000000)
 { 
   vel = (error*m_pgain + (error - m_prevError)*m_dgain)>>10;
   //sprintf(buf, "%ld\n", vel);
   //Serial.print(buf);
   m_pos += vel;
   if (m_pos>PIXY_RCS_MAX_POS) 
     m_pos = PIXY_RCS_MAX_POS; 
   else if (m_pos<PIXY_RCS_MIN_POS) 
     m_pos = PIXY_RCS_MIN_POS;
 }
 m_prevError = error;
}



void setup()
{
 Serial.begin(9600);
 Serial.print("Starting...\n");
 
 pixy.init();
}

void loop()
{ 
 static int i = 0;
 int j;
 uint16_t blocks;
 char buf[32]; 
 int32_t panError, tiltError;
 
 blocks = pixy.getBlocks();
 
 if (blocks)
 {
   panError = X_CENTER-pixy.blocks[0].x;
   tiltError = pixy.blocks[0].y-Y_CENTER;
   
   panLoop.update(panError);
   tiltLoop.update(tiltError);
   
   pixy.setServos(panLoop.m_pos, tiltLoop.m_pos);
   
   i++;
   
   // do this (print) every 50 frames because printing every
   // frame would bog down the Arduino
   if (i%50==0) 
   {
     sprintf(buf, "Detected %d:\n", blocks);
     Serial.print(buf);
     for (j=0; j<blocks; j++)
     {
       sprintf(buf, "  block %d: ", j);
       Serial.print(buf); 
       pixy.blocks[j].print();
     }
   }
 }  
}

Please read this:-
How to use this forum
Because your post is breaking the rules about posting code.

Does anyone understand this problem? Please help!!! (And I fixed the thing and am following rules now. I forgot, oops!)

If you want to understand that code, there is no other course of action than to study every single line of it until you understand what that line does.

Put some print statements in various places, to get a feel for the numbers involved.

Learning is what Arduino is for!

Like I said, dump all the ServoLoop class code - you don't need it.

Now turn your attention to loop ().

You need to retrieve the number of blocks found (just like in the example), and if it is greater than zero, (just like in the example) you need to retrieve the x coordinate (technically the abscissa) of the centroid of the object (just like in the "pan_error" calculation).

Now see if the value of the abscissa places it in either the left or right of the screen (you have to write that bit).

Ignoring braces and anything else you may want to do in it, "loop ()" is no more than five lines of code, three of which are "if"s, if I've understood your requirements correctly; it's even simpler than blink without delay.

You also need to write two functions "detectLeft" and "detectRight". I have no idea how big they're going to be.

Ok. So I made some code. I got the basic idea from the internet, but revised it for my needs. Would this work?

//Pixy arduino robot
//Arduino IDE 1.6.4

#include <SPI.h>  
#include <Pixy.h>

Pixy pixy;

int signature = 0;
int x = 0;                      //positon x axis
int y = 0;                      //position y axis
unsigned int width = 0;         //object's width
unsigned int height = 0;        //object's height
unsigned int area = 0;
unsigned int newarea = 0;
int Xmin = 70;                  //min x position
int Xmax = 200;                 //max x position
int maxArea = 0;
int minArea = 0;

static int i = 0;

void setup()
{ 

  Serial.begin(9600);
  Stop();
  pixy.init();
}

void loop()
{ 
  while(millis()<5000)
  {
    scan();
    area = width * height; //calculate the object area 
    maxArea = area + 1000;
    minArea = area - 1000;
  }

    scan(); 

  if(signature == 2)//looking for signature 2
  {
    newarea = width * height; //calculate the object area
    
      if (x < Xmin)//turn left if x position < max x position
      {     
       moveleft();
      }
      else if (x > Xmax) //turn right if x position > max x position
      {
       moveright();
      }
      else if(newarea < minArea)//go forward if object too small
      {
       moveforward(); 
      }
      else if(newarea > maxArea)//go backward if object too big
      {
       moveback(); 
      }
      
      //else stop
      else
      {
        moveStop(); 
      } 
   }
   else
   {
    moveStop();
     }
}

void moveback()
  {
//Move the robot back
  }

void moveforward()
  {
//Move the robot forward
  }

void moveright()
  {
//Move the robot right
  }

void moveleft()
  {
//Move the robot Left
  }

void Stop()//stop
  {
//Stop the robot
  }
void scan()
  {
  uint16_t blocks;
  blocks = pixy.getBlocks();  //receive data from pixy 
  signature = pixy.blocks[i].signature;    //get object's signature
  x = pixy.blocks[i].x;                    //get x position
  y = pixy.blocks[i].y;                    //get y position
  width = pixy.blocks[i].width;            //get width
  height = pixy.blocks[i].height;          //get height
  }

What happens when you try it out?

Ok, I revised the code (Again) This one should work:

#include <SPI.h>  
#include <Pixy.h>

Pixy pixy;

int signature = 0;
int x = 0;                      //positon x axis
int y = 0;                      //position y axis
unsigned int width = 0;         //object's width
unsigned int height = 0;        //object's height
unsigned int area = 0;
unsigned int newarea = 0;
int Xmin = 70;                  //min x position
int Xmax = 200;                 //max x position
int maxArea = 0;
int minArea = 0;
static int i = 0;

void setup()
{ 
  Serial.begin(9600);
  Stop();
  pixy.init();
}

void loop()
{ 
  while(millis()<5000)
  {
    scan();
    area = width * height; //calculate the object area 
    maxArea = area + 1000;
    minArea = area - 1000;
  }

    scan(); 

  if(signature == 2)//looking for signature 2
  {
    newarea = width * height; //calculate the object area
    
      if (x < Xmin)//turn left if x position < max x position
      {     
       left();
      }
      else if (x > Xmax) //turn right if x position > max x position
      {
       right();
      }
      else if(newarea < minArea)//go forward if object too small
      {
       forward(); 
      }
      else if(newarea > maxArea)//go backward if object too big
      {
       backward(); 
      }
      
      //else stop
      else
      {
        Stop(); 
      } 
   }
   else
   {
    Stop();
     }
}

void backward()
  {
//reverse
  }

void forward()
  {
//Move forward
  }

void right()
  {
//Turn Right
  }

void left()
  {
//Turn Left
  }

void Stop()
  {
//Stop alltogether
  }
void scan()
  {
  uint16_t blocks;
  blocks = pixy.getBlocks();  //receive data from pixy 
  signature = pixy.blocks[i].signature;    //get object's signature
  x = pixy.blocks[i].x;                    //get x position
  y = pixy.blocks[i].y;                    //get y position
  width = pixy.blocks[i].width;            //get width
  height = pixy.blocks[i].height;          //get height
  }

Again, what happens when you run it?

I don't get the point of function "scan" - all it does is copy the properties of "blocks [0]" to a bunch of global variables.
Also, you assume that your object of interest (signature == 2) will always be "blocks [0]".
That may not be the case - you may have to search "blocks" to find it.