<< return to Pixycam.com

gerBlocks function

Hi everyone, I am doing a car which is controlled with arduino is going well but one Thing:

I want to stop the car if it doesnt receive any Information (pixy.getBlocks would be 0), but I also get 0 when the camera recognizes a block. If I do Serial.print(pixy.getBlocks()) and a block is in front of the camera I get this:

100000010000001000000…

If I have 2 blocks:

20000002000000…

etc.

How can I program Arduino in order to stop the Motors when I dont have anything in front of the camera?

Thanks in advance

Take a look in PixyMon-- make sure you’re getting good detection of your object. Perhaps you’re getting intermittent detection and that’s what you’re seeing (your signature needs to be tweaked for better detection).

thanks!

Hi Rich, thanks for the answer. I am pretty sure about what Pixy sees: A fixed block with no changes. Like the wiki said, getBlocks gives the number of blocks that Pixy sees right? No matter the color or the size. Then my function does not run properly, cause the values change always (and repeat the same sequence each 7 function calls). Any h elp?

Thanks again!

Oh, sorry, this is straightforward— getBlocks() will return 0 if there is no new data. So if there’s just one object, you’ll get the object through getBlocks and then getBlocks will return 0 because there is no new data… until the next frame comes in. You can verify that the getBlock() calls that return 1 or 2 come in 50 times/sec.

This way you can periodically check (poll) by calling getBlocks(). If getBlocks waited for data (blocked), it would be a pain to write programs like the pan/tilt demo (or any other program…) :slight_smile:

All right Rich, now all makes sense. Thank you very much. So here the question: it means that if I want to call the function just when Pixy is seeing something, I would need to change some functions in the library libpixyusb or trying to find a way to synchronise the microcontroller in order to call the function exactly when the camera recognizes a block?

Thanks again

So currently getBlocks() will return 0 if there are no objects AND if there is no new data. (and there’s no way to tell the difference.) That’s pretty lame, so we need to fix. A better way would be if getBlocks always returns the blocks from the most recent frame. So say you called getBlocks 3 times in 1 millisecond (much less than a frame period), you’d always get the same data unless a frame came in during that 1 millisecond.

I’m not sure if you’re hinting at a the same problem though… at any rate, you’ve shed light on a real problem – thanks!

Rich LeGrand wrote:

So currently getBlocks() will return 0 if there are no objects AND if there is no new data. (and there’s no way to tell the difference.) That’s pretty lame, so we need to fix. A better way would be if getBlocks always returns the blocks from the most recent frame. So say you called getBlocks 3 times in 1 millisecond (much less than a frame period), you’d always get the same data unless a frame came in during that 1 millisecond.

I’m not sure if you’re hinting at a the same problem though… at any rate, you’ve shed light on a real problem – thanks!

Hey Rich,
I’m running up against this exact issue. I see it was only identified a month ago. Any progress on a fix?
I’m currently trying to read the same camera twice during the same loop (I alter the lighting conditions between reads so that I’m getting two different sets of objects).
Because I can’t currently distinguish between “no objects detected” and “new data not ready”, my only current option is waiting enough time that I’m certain the ‘0’ I read back means that no objects are detected, which is not ideal.
I’ve been looking through TPixy.h to try and find a way to return a different value for the “data not ready” condition, but I’m coming up empty.
Thanks for any help or suggestion.

Hi Sam,
This was fixed a while back in libpixyusb, but for the Arduino library, we need to change the protocol, which is more involved. As a workaround— when getBlocks returns 0 you can delay for 20ms (call delay(20)) then call getBlocks again. If you still get a 0 then there are no blocks detected.

thanks!

Hey Rich,
First, thanks for your reply.
I figured as much RE: changing the protocol - looking through the Arduino code, it didn’t appear there was anything I could do on my side to fix this.
Just as a confirmation:
Since the pixy communicates serially with the micro via polling, if I’ve waited some indeterminate amount of time (but definitely greater than 20 ms) since my last getBlocks() call, I can be certain that a return value of ‘0’ means the pixy sees no blocks? Pseudocode example of what I’m talking about:

@

void main(void){

while(1){

//do stuff that takes more than 20 ms

checkFrontCam();

}

}

void checkFrontCam(void){

blocks = getBlocks();

if(blocks){

//processing assuming that “blocks == 0” means there were no blocks in view
}

delay(20);

blocks = getBlocks();

if(blocks){

//different processing assuming again that “blocks == 0” means no blocks were in view
}
}
@

So, if I’m correct, both of the commented assumptions in the “checkFrontCam” function are valid?
I know I should be able to determine this from testing, but I’ve gotten some weird results that are the result of either a) one of my assumptions is incorrect or b) I’ve got something screwed up elsewhere in my code.

Thanks again,
Sam

Hi Sam,
Here’s what I was thinking — this code lets you go at 50 frames/sec

while(1) {  // your loop

blocks = getBlocks();

if (blocks)
{
 // process blocks!
}
else // we may have no blocks, so do some more checking....
{
  delay(20);  // wait for a frame period
  blocks = getBlocks();  
  if (blocks)
  {
     // process blocks!
  }
  else
  {
     // no blocks detected (guaranteed)
  }
}
}

or, you can always do this, which is simpler, but you’ll probably not get 50 frames/sec:

while(1) {  // your loop

delay(20); // or you can do something here that takes at least 20 ms

blocks = getBlocks();

if (blocks)
{
  // process blocks!
}
else
{
  // no blocks detected (guaranteed)
}
}

The main thing to keep in mind is that if you poll faster than 50 times/sec, you will end up with getBlocks being 0 (which is the ambiguous case – does 0 mean no new blocks detected, or does it mean no blocks detected at all in the latest frame), so the first piece of code will work. But if you poll at 50 times/sec or less, you’ll always get the latest blocks (if they exist) and the ambiguous case goes away. If you’re not so worried about 50 frames/sec, I’d used the 2nd piece of code. It’s simpler. :slight_smile:

Thanks Rich.
I believe you answered my question, and I believe I’ve got test code that confirms it. I guess another way to ask it (just in case anybody else finds this thread and is left with a vague feeling of ambiguity) would be to speak in frames per second. If I poll at some arbitrary rate that is less than 50 fps (say 48 fps, just to have a number), can I be certain of no ambiguous 0’s? My reading of your answer and personal experience (at this point) says “yes”.
Thanks,
Sam

Hello Sam,
Yes, you are correct. Polling at less than 50 times per second = no ambiguous 0’s.

Edward

Gentlemen,

Clarification please:

It is stated: " Pixy sends block information to Arduino at 1 Mbits/second which means Pixy can send more than 6000 detected objects
per second or 135 detected objects per frame (Pixy processes at 50 frames per second.) "

How is it possible to obtain the 6000+ object blocks for one signature in one second? Am I miss reading the above quote?

I am interested in obtaining only the x,y width, height and signature of one object in “block format”. The case is of a BB being fired and capturing one seconds of its flight by recording 6000+ blocks.

Thank you for your time.

Is there a tutorial with example on programming the Arduino to obtain pixy’s data?

My understanding is that, if the BB only represents one block (ie, in any given frame from the camera, you have one block which represents the centroid and bounding box surrounding the BB), then the maximum number of position data-points you’re going to get on the BB is 50 per second.
The 6000 number comes from the idea of tracking multiple objects (with or without multiple colors):
Imagine you have 135 colored balls bouncing in front of a black background. The pixy is (theoretically) capable of tracking all of those balls, at a framerate of 50 frames per second, giving you (135*50 =) 6750 separate blocks received during one second. However, for tracking an individual object, you’re still limited to 50 frames (and hence 50 data points) per second.

Alexander Luis wrote:

Is there a tutorial with example on programming the Arduino to obtain pixy’s data?

I’ve found the examples included with the Arduino library get the point across pretty well. You only have a few functions. The basics are:
-Include the Pixy library of your choice (Pixy.h for standard SPI communication, PixyI2C.h for I2C communication, etc…).
-Define a Pixy object with .
-Call .init() in the setup function.
-Call .getBlocks() in the loop. You can use getBlocks(int number of blocks) to specify a maximum number of blocks if you like. The getBlocks() function returns the number of blocks that were gotten.
-You can access the data about the retrieved blocks using .blocks[N].(x,y,width,height,signature), where ‘N’ is the number of the block you’d like to get info about (with N ranging from 0 to one less than the number returned by “getBlocks()”), and with the blocks sorted by signature (1-7) and then by size (largest to smallest), such that .blocks[0]… - will give you data about the largest block of the lowest number signature you have defined.
-You can also just print out the data for any block to the serial terminal using .blocks[N].print();

Hope that helps.

Gentlemen, thank you again for your time.
It was stated that " The 6000 number comes from the idea of tracking multiple objects (with or without multiple colors):"
What does “tracking multiple objects” mean then (how does the pixy know one object from another)? If the pixy is capable of tracking all those balls (very fast), can it "track just one object 135 times per frame?

Also, if I can take advantage of your valuable time:
The OV5642 sensor is 5 Megapixel (2592 x 1944) and QVGA at (320 X 240): 120 FPS. Can I substitute this sensor and increase my frame rate(120 blocks/sec)?

Thank you again for your time.

The pixy detects objects on a pixel by pixel basis. Blobs of adjacent pixels that fall within a predefined range (your chosen color signature) are considered objects. So, two yellow balls (assuming your chosen color is that hue of yellow) that are within the camera’s field if vision, and that don’t overlap each other within that field of vision, will be detected as two separate objects. Fifty times per second, the camera captures a frame, analyzes all the pixels, and generates a list of objects based on the number of separate blobs of tracked colors it sees. This is why you can’t get 6000 data points for a single bb. It will only appear as a single blob of color (and I’m not entirely certain that it will - you’ll need to paint your bbs, most likely) in each of the fifty frames the camera takes per second.
As to replacing the camera module, while I’m not certain, my guess would be that the answer is “not without some major changes to the pixy’s firmware”.

I’m also new to Pixy CAM.
But whenever I try to execute by entering “Y” the getBlocks() function, the 1st print display the pixy information(object existed) but when I remove the object, and execute by entering “Y” again it still display pixy information and the 3rd execute it only display the error message.
String input;
if (Serial.available() > 0)
{
input = Serial.readStringUntil(’\n’);
if (input == “Y”)
{
blocks = pixy.getBlocks();//retrieve blocks
if (blocks)
{
if (pixy.blocks[0].signature == 1)
{
pixy.blocks[0].print();

    }

  }
  else
  {
    delay(20);
    blocks = pixy.getBlocks();//retrieve blocks
    if (blocks)
    {
      if (pixy.blocks[0].signature == 1)
      {
        pixy.blocks[0].print();
        
      }

    }
    else
    {
      Serial.print("Error no blocks detected");
    }
  }
}

I not quiet sure what is the problem about it. Need help immediately thank you.

This is the display i got. But is not what I wanted. Not sure what is the problem.

DO i have to alter TPixy.h?