<< return to Pixycam.com

Read multi objects

My 13yrs old son and myself are making a cube solving robot. We have written the algorithm to solve the cube and built the lego robot to turn the faces and it can solve a cube if by hand we input the colors on each face. we want to use pixy to read all the colors on each face. We are programing in Small basic and using the lego brick to run the program.

We have able to communicate with pixy in 2 different ways. We can install the lego firmware on pixy then using the function sensor.communicateI2C we can write 0x51 through to 0x57 at address 1. this will read the largest object of each color but often there can be more than 1 object of the same colour and we can’t read the second object of same colour.

The other way we can communicate to pixy is install standard firmware and use the sensor.communicateI2C function and it returns 16 byte that will have info just about the first object only.

How can I read multi object of same color?

A little more detail:

The only fuction that I have is : Sensor.CommunicateI2C (port, address, writebytes, readbytes, writedata)
see https://sites.google.com/site/ev3basic/ev3-basic-programming/ev3-basic-manual

if using lego firmware my code will look like this if the pixy is plugged into port 1 and I want to read largest object in signature 1. Readback is an array that will retrurn 6 bytes.

writedata[0] = 81
readback = Sensor.CommunicateI2C(1,1,1,6,writedata)

If using standard firmware and interface set to I2C the code will look like this. It doesn’t seem to matter what I set writedata too it will still send back the same result.

writedata[0] = 1
readback = Sensor.CommunicateI2C(1,84,2,16,writedata)

This is what I would like to be able to do:

  1. Pause pixy from any updates to objects
  2. read the number of current objects
  3. read each of the objects
  4. unpause pixy so the it can again go back to updating objects.

Hello Shane,
Sorry, I’m having trouble understanding what you’re asking.

It sounds like you’ve seen this document(?)

http://cmucam.org/documents/36

The LEGO firmware only provides the largest object, but you might be able to use the standard non-lego firmware. Have you tried this? You should be able to see the sync word if you’re getting correct data.

http://cmucam.org/projects/cmucam5/wiki/Porting_Guide

Edward

I have installed the standard lego firmware and set interface to I2C.
I can communicate with pixy using this following function.

Sensor.CommunicateI2C (port, address, writebytes, readbytes, writedata)
Port is the port that pixy is plugged into, I usually use port 1
Address is the I2C bus address with standard pixy firmware this is Hex 54 or decimal 84
Writebytes is how many bytes to send to pixy, I usually send just 1 byte
Readbytes is how many you want to receive back, for an object in standard firmware this 16 bytes
Writedata is an array of bytes the size of writebtye that contains the data to send to pixy. It doesn’t seem to matter what data I send I alwasy just get the data back about first object.

The following code will write 1 byte with value = 1 to pixy in port 1 at bus address dec 84 and the array readback will recieve 16 bytes.

writedata0 = 1
readback = Sensor.CommunicateI2C(1,84,1,16,writedata)

This will give me 16bytes of data as per http://cmucam.org/projects/cmucam5/wiki/Porting_Guide

Object block format

Bytes 16-bit word Description

0, 1 y sync: 0xaa55=normal object, 0xaa56=color code object
2, 3 y checksum (sum of all 16-bit words 2-6, that is, bytes 4-13)
4, 5 y signature number
6, 7 y x center of object
8, 9 y y center of object
10, 11 y width of object
12, 13 y height of object

But this is just the data of first object. How do I get data for rest of objects? Do I need to change what data that I am sending to pixy in order to get second object?

I have done a test where I read the stream on bytes from pixy. I do see the double sync 16 bit word (0xaa55)in decimal if comes endian 85,170,85,170 then I get 2 bytes for checksum then the 5 x 16 bit words for the object data of first object. If I hold several objects in front of the pixy most of the time it will just give me the 1st object then the double sync and first object again. about 1 in every 10 reads it will give only 1 sync then the data for second object. At no stage ever do I get the data for the 3rd object.

I think the problem maybe that pixy is updating to fast at 50 fps and the lego block can’t read it that fast. By the time the lego block goes to get the data for next object pixy has already updated the frame and gone back to first object.

Is there a way to lock the frame until after I have read all objects?

Hello Shane,
I believe you are correct. If you read the object data at a low rate, Pixy will create new objects from the next frame and deliver those instead, under the assumption that newer data is better.

The LEGO block reads at around 10kbps, or 1Kbyte/s, or 200 bytes/frame, or 20 blocks/frame. 20 blocks is pretty decent. Are you printing out the raw data? This can slow things down. What if you just read as fast as you can into memory until the see the double-sync?

Edward

ok here is a small test program. The pixy is plugged into port 1 on brick and plugged into PC via USB. I run pixymon to ensure that I have good lock on 3 objects(each object different colors) in front of pixy cam then exit pixymon so that pixy can communicate to brick then run below program.

writebyte[0] = 1
readback = Sensor.CommunicateI2C(1,84,1,32,writebyte)
TextWindow.Write(readback)

It reads 32 bytes (functions max allowed bytes in one read) from port 1 at I2C address dec 84 into an array called readback then writes the array to a text window.

see output below

0=85;1=170;2=85;3=170;4=101;5=1;6=1;7=0;8=137;9=0;10=100;11=0;12=59;13=0;14=60;15=0;16=85;17=170;18=85;19=170;20=99;21=1;22=1;23=0;24=137;25=0;26=99;27=0;28=57;29=0;30=61;31=0;

As you can see the first 4 bytes are the double sysnc in decimal 85,170,85,170, next 2 bytes is check sum, next 2 bytes (6,7) are the signature = 1 then followed by X center, y center and width then hieght. Then next 4 bytes are double sync (bytes 16, 17, 18, 19).

Now the brick bus maybe able to read at your quoted speed but is this the brick it’s self? I do understand the lego virtual machine is quite cumbersome and restrictive, also I am issuing this command via a Small Basic function and not sure what the compiler does to it by the time it is compiled into lego virtual machine then complied from there to Linux then complied again in to machine code. I assume compiling from Small basic to lego to linux to machine code has created many bottle necks.

When running pixy mon there is a stop play button to pause pixy from updating the objects, is there a way to issue a command to do the same over I2C. If I could pause pixy then read objects then un pause pixy this would solve my problem.

Hello Shane,
Are you printing or doing anything else while grabbing data that could slow things down? Another question is how fast is small basic? Is there a way to benchmark the code you are running with some kind of clock (external or otherwise)? This way you could at least determine that it’s the code that’s running slow (or something else).

Unfortunately,there is no way to issue a stop or pause through the serial interfaces (i2c, spi, uart).

Edward

No I am not doing anything else while reading the I2C port. Not sure how fast Small basic is but I think both Small basic and lego virtual machine are both slow. Either way the outcome is: trying to read multi objects with Small basic over the EV3 brick isn’t happening. I have now got a Pi and the hello_pixy demo running on the Pi will read as many object as I can hold in front of it.

Hi Shane,

I just had a quick look at EV3 basic with PixyCam (I had the lego version using the I2C interface and normal firmware) and I can confirm that Pixy is able to detect multiple objects. The trick is to store all the read information into an array first and then filter out those entries considered to be “similar”.

Here’s my code -

For i = 0 To 99
writedata[0] = 1
output[i] = Sensor.CommunicateI2C(1, 84, 1, 16, writedata)
EndFor

For i = 0 To 99
TextWindow.Write(“sig: " + output[i][6] + " x: " + output[i][8] + " y: " + output[i][10] + " width: " + output[i][12] + " height: " + output[i][14])
TextWindow.WriteLine(”")
EndFor

I am doing recognition on s1 on 3 objects and pixy is able to send 3 distinct coordinates across.

Hope this helps.

/CC

p.s. The data seems to play up after a few runs (as in the “sig” bit got replaced with the frame marker).