Yes, I know all about that site with all those words and groups of letters and such. What I need is someone smarter than me to write spin code to use the pixy so that I can use the pixy too.
All I can find is how to read a packet from the Pixy. I don't see any way of setting the Pixy's modes.
I see Pixymon Configuration Parameters but I don's see how to use these parameters from a microcontroller? Do I have to use the PC to interface with the Pixy prior to using a Propeller over a serial line? I'm guessing yes.
I was hoping to find a list of commands the Propeller could issue to configure the Pixy on its own.
I initially only saw zero data returned, as in eight bits of 0. Apparently the Pixy streams zeros when it doesn't have anything to say.
I used the program PixyMon to set the output to UART and to change the baud to 115,200 (from 19,200).
Here are some other changes I made.
In the "General" tab is used these settings.
Since I was just receiving zeros, I decided to change the settings and changed the saturation from 15.0 to 5.0.
I trained the Pixy with two signatures (#1 and #2) I used Post It notes as the targets. It usually takes me a couple of attempts to capture the target since I'm not sure which combination of actions will result in a captured target. At some point the program will let you drag the mouse over a captured image to select the target.
With these changes, I was able to capture a few blips of data.
The value "syncError" is a count of how many characters were received which didn't lead to valid packet.
I was only able to capture a few valid packets before the evening light dimmed to the point where it no long assisted the indoor light enough for a valid capture.
I'll give this a try again when I have some better lighting.
The attached program will display the packet data but each packet will be displayed over top of the previous packet (deleting the previous packet's data).
You have to make the changes shown above with PixyMon and train a few signature before the Pixy will output anything the Propeller can read.
I'm learning I made some bad assumptions earlier. I thought the brightness setting was how bright the object needed to be to be detected. It's really how bright you want the Pixy to make the image. The Pixy was able to find more signature items with the brightness turned up.
The maximum brightness is 232. I found a setting of 80 worked pretty well.
The saturation value is important in how picky the Pixy should be about the color. It seems like somewhere between 5 and 10 worked pretty well with some colors. I'm presently using a setting of 7 for the saturation.
I reduced the number of objects to 2 and I'm only going to teach a single signature for my next experiment with the Pixy.
I'm gong to modify the code to output data about two objects at a time.
I didn't build the pixy. Different team. I designed the CMUcam4. The pixy is more powerful than the CMUcam4. It also has a better color tracking algorithm. Play with it a bit and you should be able to get going.
@Duane - I suppose your right, you'll have the post on the forum to get more information about how to use the system. However, I think all the technical details about how to use the camera are on the wiki.... I believe. Knowing the technical details about how to use the camera doesn't actually help you USE the camera however. Some knowledge of what to do with the camera is needed.
I just got a Pixy and the servo mount kit. I haven't tried the kit yet but I have got the Pixy working.
I wanted to try hooking it up to a Quickstart board and run it using pfth, but the serial methods are going to take some time for me to understand. I have an Activity Bot and realized that the Activity Board has a 4 channel ADC, The Pixy can send voltage proportional to X or Y position, and the C Learning tutorials have a couple of ADC examples. So I decided to try using the AB.
One big limitation of the Pixy is that it only has one ADC interface so can only send either x data or y data. Since I want to use this with the robot, I chose the X data (interface mode 3).
I didn't have a lot of time for this so my setup was not ideal. I was working on a card table (shake shake shake). Pixy was leaning up against a box. And I was holding a light blue pen cap as the object of interest. Also the lighting was florescent.
I used the Simple IDE C program "Measure Volts" (below) from the Simple Circuits section of the C Learning tutorial. That program uses ADC channels 2 and 3 to read voltage. Pixy sends the voltage proportional to the X position ranging from 0 volts full Left to 3.3 v full Right. I connected Pixy Pin #3 (v out) to ACT Brd ADC 3, Pixy Pin 6 (GND) to AB GND. I also attached Pixy Pin #1 to ADC 2.
Pixy pin 1 is high (3.3v) when the color is detected and 0 when not. I found testing that helped clean up the data when the object was near the extreme Left or Right of the Pixy field of view. I modified the printing near the end of the code to only print the ADC3 voltage if ADC2 voltage was >1.
/* Measure Volts.c
Version 0.94 for use with SimpleIDE 9.40 and its Simple Libraries
Make voltmeter style measurements with the Propeller Activity Board.
http://learn.parallax.com/propeller-c-simple-circuits/measure-volts
*/#include"simpletools.h"// Include simpletools#include"adcDCpropab.h"// Include adcDCpropabint main() // Main function
{
adc_init(21, 20, 19, 18); // CS=21, SCL=20, DO=19, DI=18float v2, v3; // Voltage variableswhile(1) // Loop repeats indefinitely
{
v2 = adc_volts(2); // Check A/D 2
v3 = adc_volts(3); // Check A/D 3
putChar(HOME); // Cursor -> top-left "home"
print("A/D2 = %f V%c\n", v2, CLREOL); // Display voltsif(v2 > 1 ) print("A/D3 = %f V%c\n", v3, CLREOL); // Display volts Added condition on Pixy Pin 1
pause(300); // Increased Wait to 3/10 s
}
}
Because of the shakiness of my setup the voltage values printed out did have some jitter. When I did everything I could to minimize the shakes, the data was quite good with the variations in the 3rd or 4th decimal place.
Next I've got to work up the commands to use those readings to rotate the Activity Bot to track the object.
I don't suppose I could talk you into posting some output from the Program?
Since you're using C, I wonder if you could just port the Arduino code into Propeller C?
Even without porting the full code, You might be able to make better use of the Pixy with the UART using C.
Either way (UART or ADC), I hope you keep us updated on your progress.
Duane,
The output from the code above was just the voltage values (approx 0 to approx 3.3). Using simple IDE I ran the code using the run with terminal.
I've quickly looked at the Arduino code. But quite frankly, I'm a C novice and figuring out the Arduino code is going to take some time and learning on my part. Once of the concerns I have using the UART is that the Pixy just continuously sends values. I'd be more comfortable if I could send it a command to start sending the values for a specific signature. But I'll keep working on it. One reason why I'd like to use pfth for this is that it is easier for me to see the format of the data (I have the Pixy info from he wiki) and modify things in real time.
My first step will be to use the Spin code you posted, and I will probably have some questions for you. I still have to play with the configuration settings that you described. I found that with the lighting I had, it was necessary to raise brightness to 120 to get consistent readings.
I think that the Arduino code has commands to set the Pixy configuration, like Pixymon does, so there are some good reasons to try to figure it out.
One of my problems is that I tend to jump ahead before fully working out the basics. So I'm already starting to work on methods to rotate the Activity bot to drive to a stationary object (should be pretty easy), and then to rotate to follow a moving object (steady motion and then random motion). I realize that there are folks here for whom that would be almost trivial, but its more new ground for me.
I think that the Arduino code has commands to set the Pixy configuration, like Pixymon does, so there are some good reasons to try to figure it out.
I haven't seen these codes myself. As far as I can tell, there are a lot of configuration parameters that have to be set with the Pixymon program. IMO, this aspect of the Pixy is very bothersome.
I tried to figure out the UART. I tried Duane's Spin code from post 5 and got very inconsistent results. Some times I would get some values, other times all zeros.
Tonight I tried using Forth (pfth version) to see if I could decipher what the Pixy UART was putting out. I have a routine that I used to debug a bluetooth serial connection. I have a forth word (bt>str) that simply does an FDS_Read (fds_rx) and stores the byte received in a string array and repeats. Once the array is filled the word ends. Then I use a forth word (.bt) that prints out the byte values. That way I can see the how the sending device formats the block. Because of the size of the Pixy block (14 bytes) I increased the array size to 129 bytes, so I could catch at least a few blocks.
First thing I found out was that I received a couple of initial bytes and then just zeros if I had Pixymon running. So I closed that program.
Once I did that I initially tried using my normal baud rate of 115200.
I looked for the Pixy sync word aa55 (or 55 aa, LSB first). If you search through the above, you will see only one instance of that, and it appears to be an incomplete block. I guessed that 115200 baud might be too fast and characters were being lost. So I tried the Pixy default of 19200 baud.
I put in some line feeds to set off the complete blocks. There are a number of complete 14 byte blocks starting with 55 aa. (I have to try a slower baud to see if the results get better). However, at the begining and end of the buffer there are values that don't make any sense or are partial blocks. The Pixy wiki states that if Pixy is transmitting a block and the next cycle of data starts, it will just discard the data from the previous block. That makes decoding more complex. Again, I wish that they had written the firmware so that the user could start and stop transmission blocks remotely rather than just having Pixy bang away.
Next I took a couple of blocks and translated them into decimal to see if they made any sense.
It appears that the results are reasonable. Now that am getting some consistent results I'll have to try with a more controlled set up (instead of me just waving a flower in front of the lens). Then the next thing is to try to use the serial objects in either spin or C to try to collect the data and make use of it.
I have also done a little more with the ADC method in C, translating the x-location (from voltage) into a command to rotate the Activity Bot. I have to do some work on the robot (replace Ping with Pixy) and see how it works.
Today's results:
I tried a more controlled test. I mounted 3 pieces of different size non-glossy colored paper rectangles on a white board, and trained Pixy for each color. Then kept everything in a fixed location.
The pixy wiki states that Pixy will transmit a new frame of data every 20 ms and can send data on 135 objects per frame (approx 1 per 0.15 ms). I calculated that at 19200 baud, Pixy would send 3 objects worth (14 byte blocks - 2 sync bytes 55, aa and 12 data bytes) of data in each frame. Each Frame starts with 4 hex bytes: 55, aa, 55, aa and then the data from the first block, followed by 55, aa starting the second block, etc. Pixy sends the data in decreasing order of size of each block.
At 19200 baud, I got some data that looked good, but less than 50% of the blocks were ok. The rest seemed to be blocks with data out of order, wrong number of data bytes, etc. It seemed as though Pixy was sending data faster than pfth could handle it (simply put it into an element in a character array and test for the maximum number of bytes in the array.) I have used pfth with Full Duplex Serial at 115200 baud from a bluetooth device, but the BT device sends the data packets at a relatively slow speed (e.g. speed of typing).
Since decreasing the baud rate of the Pixy serial connection from 115200 to 19200 enabled getting some correct data blocks, I lowered the baud rate one more step to 9600. Using that I got reliable data almost all of the time. But because of the reduced baud rate Pixy was only able to send 1 block of data per frame. And since the Pixy priority is to send the data block for the largest item first, that is the only data that can be received.
From what Dave Hein has written, pfth is not the fastest language around. I will have to try in both Spin and C to see if they are fast enough to use with FDS. I will also have to learn how to use the Pixy SPI and I2C interface to see how they work.
I tried using C with Simple IDE. It was a very simple program (see below): open the serial port, read a byte, print it on the terminal.
I was able to read 5 blocks of data per frame accurately at 19200 baud with the Pixymon program not running. The next thing to do is to sync data collection and interpretation with the Pixy sync bytes. I'll also try some tests with higher baud with Pixymon off.
Tom
/* C code used with Pixy - CMUCAM5 Test to see how many blocks of data can be received per frame.
Just performed Rx and printed value.
Result - With Pixymon running, the serial port had to run at 9600 baud and only one block was received per frame
- With Pixymon program closed, the serial port ran at 19200 baud and 5 blocks were received per frame.
The checksum confirmed that the data was received correctly
*/#include"simpletools.h"// Include simple tools#include"fdserial.h"
fdserial *blut;
char c1;
intmain(){
// fdserial * fdserial_open(int rxpin, int txpin, int mode, int baudrate)
blut = fdserial_open(9, 8, 0, 19200);
while(1) // do forever
{
c1 = fdserial_rxChar(blut); // read byte from Pixy
print("%d\n", c1);
}
}
I'm very interested in following everyone's work with using the Pixy. I just bought one through Amazon, but haven't done anything besides using the PixyMon program and teaching it a couple of objects. It would be great to use the propeller to control it and read the data.
Today, I ran some tests with C. I used the program in post 17, tried different Bauds (in the program when I open fdserial and set on Pixy through Pixymon) and memory models to see how many blocks per frame could be received reliably. I ran the above program with terminal. After collecting data for 30 seconds, I clicked "disable" on the terminal. Then I scrolled back through the terminal screen until I found the first instance of 85, 170, 85, 170 (the decimal sync bytes for a new frame.) Then I selected all the values from that point to the end and copy/pasted them into excel.
In the following column in excel, next to the first byte for each word (LSB) -- for example in cell D5, I entered the following =(256*D6)+D5, so I could have all the word values sent and check the checksum for accuracy.
I got the following results. Note that in some cases, after sending a complete block of data, there would be a series of zeros without a starting sync word. Based on the pixy documentation, this indicates no signatures detected. I was doing this test in a medium well lit room, and I could see when using Pixymon that sometimes the signatures would flicker.
I tried 57600 baud, but there were many errors.
My conclusions from the results below are that if I have to use CMM to fit a program, I would restrict the baud to 14400 if I wanted no errors. If I had good error detection in my software, I'd use 16800. If I could use LMM, I'd choose 19200 or 38400.
Tom
Mem Model
Optmization
Baud
B/F max
B/F min
B/F typical
Num Err
Today I put together a C program that reads data from Pixy, then throws away data before the first sync word, then combines the Pixy bytes into Pixy words values. The program should be run using "run with terminal". It prints out a lot of intermediate steps, and the last part of the printout is a single column of the pixy words that can be copy and pasted into Excel or other program. My next step is to try to get the reading data from Pixy part into a separate cog.
Note that I did try to find the first sync word and then start reading values from Pixy, but there was enough of a delay that the first 2 or 3 words after the sync were lost. So that's why I read everything and then truncate.
Tom
Here's the code:
/* C code used with Pixy - CMUCAM5 Tom Montemarano June 2014, MIT License.
1. Collects data from Pixy (LSB, MSB)
2. Discards values before first sync word.
3. Calculates and saves pixy words
Run with terminal. This version shows all intermediate steps.
The last part of the printout is the words in one column that can be cut and pasted into excel.
The order is:
43605 (sync), checksum (sum of next 5 words), signature # (1 - 7), x-position, y-position, width, height.
2 sync words in succession mean start of new frame.
Set Pixy to 19200 baud
Now that I got it working I need to:
1. write code that can select a specific signature, and position
2. clean up and tighten up.
3. Put getting Pixy data in separate cog.
4. Loop to control Activitybot
*/#include"simpletools.h"// Include simple tools#include"fdserial.h"#define mvs 130
fdserial *pixy;
int mvals = mvs;
char c1[mvs];
int c2[mvs];
char synclsb = 85;
char syncmsb = 170;
int i;
int j;
int k;
int flg;
int pv[mvs/2];
intmain(){
// fdserial * fdserial_open(int rxpin, int txpin, int mode, int baudrate)
pixy = fdserial_open(9, 8, 0, 19200); // This baud seems optimum - it collects 2 or 3 blocks per frame w/o errorsfor(i=1; i<mvals; i++) c1[i] = fdserial_rxChar(pixy) ; // read byte from Pixy with no delays
print("values read\n");
k=1;
j=1;
flg = 0;
for(i=1; i<mvals; i++)
{
if(flg == 0)
{
if(c1[i] ==synclsb) // Find first sync word's LSB
{
print("synclsb\n");
if(c1[i+1] ==syncmsb) // Is next byte the first sync word's MSB
{
print("syncmsb\n");
flg=1;
}
}
}
if(flg==1)
{
print("flg=1\n");
c2[k] = c1[i]; // put bytes starting with first sync word into integer
print("k = %d, c2 = %d\n", k, c2[k] );
k++;
}
}
print("k = %d\n", k );
for(i=1; i<k; i=i+2)
{
pv[j] = c2[i]+ (c2[i+1]<<8); // take LSB and MSB and make word
print("j = %d, pv = %d\n", j, pv[j] );
j++;
}
for(i=1; i<j; i++) print("%d\n", pv[i]); // Printout words in column
}
Today, I cleaned up the C program and moved the serial function that collects the data from the Pixy to a separate cog. When I use this to control the Activity Bot, I will run the entire program as a function in a separate cog including the getpixy function, so that the analyzed data will be ready when the robot control program calls for it.
The demo just prints out the pixywords in the terminal. It uses a while(1) loop and prints "end of data" between pixy data collections.
Tom
Here's the code:
/* C code used with Pixy - CMUCAM5 Tom Montemarano June 2014, MIT License.
1. Collects data from Pixy (LSB, MSB)
2. Discards values before first sync word.
3. Calculates and saves pixy words
Run with terminal. Uncomment print statements to print intermediate steps.
The last part of the printout is the words in one column that can be cut and pasted into excel.
The order is:
43605 (sync), checksum (sum of next 5 words), signature # (1 - 7), x-position of centroid, y-position, width, height.
2 sync words in succession mean start of new frame.
Set Pixy to 19200 baud
Now that I got it working I need to:
1. write code that can select a specific signature, and position
2. clean up and tighten up. (done?)
3. Put getting Pixy data in separate cog. (done)
4. Loop to control Activitybot
*/#include"simpletools.h"// Include simple tools#include"fdserial.h"#define mvs 110 // To get one full frame (2 - 3 blocks) set mvs to 110
fdserial *pixy;
voidgetpixy(); // forward declare functionint *cog;
volatileint mvals = mvs;
volatilechar c1[mvs]; // raw byte values from pixyvolatileint flag; // use as a lockchar synclsb = 85; // LSB of sync wordchar syncmsb = 170; // MSB of sync wordint pv[mvs/2]; // Pixy wordsintmain(){
int i;
int j;
int k;
int flg; // flg = 1 when first sync word located
flag = 0;
cog = cog_run(&getpixy, 128);
while(1) // do forever
{
while(flag==0) { } // stall main while getpixy collects data
flag=1; // stall getpixy
k = 1;
j = 1;
flg = 0;
i = 0;
while(flg == 0)
{ i++;
if(c1[i] == synclsb) // Find first sync word LSB
{ // print("synclsb\n"); if(c1[i+1] == syncmsb) // Find first sync word MSB
{ // print("syncmsb\n");
flg=1; // Got first sync word, set flg=1
}
}
}
for(k=i; k<mvals-2; k=k+2)
{ pv[j]=c1[k+1]; // make MSB integer for shift
pv[j]=(pv[j] <<8) | c1[k]; // take LSB and MSB and make Pixy word// print("j = %d, pv = %d\n", j, pv[j] );
j++;
}
for(i=1; i<j; i++) print("%d\n", pv[i]); // Printout words in column
print("end of data \n");
flag=0; // unstall get pixy
} // end of infinite while loop
} // end mainvoidgetpixy(){
int i;
// fdserial * fdserial_open(int rxpin, int txpin, int mode, int baudrate)
pixy = fdserial_open(9, 8, 0, 19200); // This baud seems optimum - collects 2 or 3 blocks per frame w/o errorswhile(1)
{
while( flag==1){ } // Wait until main finishes and sets flag = 0for(i=1; i<mvals; i++) c1[i] = fdserial_rxChar(pixy) ; // read bytes from Pixy with no delays
flag = 1; // stall serial and start main processing
}
}
The program below collects Pixy data, checks the checksum, indexs it by signature number, and prints out the selected data and average (either x, y, width, or height) for the selected signature. Additional info can be printed to the terminal by uncommenting the print statements.
/* C code used with Pixy - CMUCAM5 Tom Montemarano June 2014, MIT License.
This program prints out the average value of x for a chosen signature
1. Collects data from Pixy (LSB, MSB)
2. Discards values before first sync word.
3. Calculates and saves pixy words
4. Checks ckecksum
5. Indexs blocks by signature number
6. Gets x-position for selected signature and averages it.
Run with terminal.
This version only prints out the data and average value of x, y, width, or height
for the selected signature to show how quickly it runs.
There are 4 parameters that can be changed (kk, zz, dd, pxi) to change:
kk = the color signature of interest,
zz = the number of data sets,
dd = the delay between data sets, and
pxi = the parameter to be printed (x, y, w, or h).
Uncomment other print words to get see intermediate steps including:
The words in one column that can be cut and pasted into excel.
The number of blocks collected.
The number of blocks of each signature value
The indices of PV[] that contain the signature number
The order of Pixy words in each block is:
43605 (sync), checksum (sum of next 5 words), signature # (1 - 7), x-position of centroid, y-position, width, height.
2 sync words in succession mean start of new frame.
Set Pixy to 19200 baud
Now that I got it working I need to:
1. write code that can select a specific signature, and position - done
2. clean up and tighten up. -
3. Put getting Pixy data in separate cog - done (not in this program)
4. Loop to control Activitybot
*/#include"simpletools.h"// Include simple tools#include"fdserial.h"#define mvs 210 // To get one full frame (2 - 3 blocks) set mvs to 110voidindexpixy(void);
fdserial *pixy;
int mvals = mvs;
char c1[mvs]; // raw byte values from pixychar synclsb = 85; // LSB of sync wordchar syncmsb = 170; // MSB of sync wordint i;
int j; // number of pixy wordsint k;
// These 4 values are for the demoint kk = 1; // signature of interest to be printed out -- set to a color signature taught to Pixy (1 - 7)int zz = 5; // Number of averages to printint dd = 100; // Delay in ms between data sets - use smaller to show program speed, larger to demo motionint pxi = 1; // This points to the specific value in the block - 1=x, 2=y, 3=width, 4=heightint m;
int bk;
int fr;
int flg; // flg = 1 when first sync word locatedint pv[mvs/2]; // Pixy wordsint sig[8][12]; // signature number, number of blocksintmain(){
// fdserial * fdserial_open(int rxpin, int txpin, int mode, int baudrate)
pixy = fdserial_open(9, 8, 0,19200); // This baud seems optimum - it collects 2 or 3 blocks per frame w/o errors// With more objects, the baud can be increasedint z;
for(z=1; z<zz+1; z++)
{
for(i=1; i<mvals; i++) c1[i] = fdserial_rxChar(pixy) ; // read byte from Pixy with no delays// print("values read\n");
k = 1;
j = 1;
flg = 0;
i = 0;
while(flg == 0)
{ i++;
if(c1[i] == synclsb) // Find first sync word LSB
{ // print("synclsb\n"); if(c1[i+1] == syncmsb) // Find first sync word MSB
{ // print("syncmsb\n");
flg=1; // Got first sync word, set flg=1
}
}
}
for(k=i; k<mvals-2; k=k+2)
{ pv[j]=c1[k+1]; // make MSB integer for shift
pv[j]=(pv[j] <<8) | c1[k]; // take LSB and MSB and make Pixy word// print("j = %d, pv = %d\n", j, pv[j] );
j++;
}
// for(i=1; i<j; i++) print("%d\n", pv[i]); // Printout words in one column// print("j = %d\n", j);
indexpixy();
pause(dd);
}
} // end mainvoidindexpixy(void)// { // 43605 = decimal sync wordfor(i=1; i<8; i++) sig[i][0] = 0;
fr = bk = 0;
i=1;
while (i < j )
{
if(pv[i] == 43605) // sync word
{
m = i;
bk++;
if(pv[i+1] == 43605)
{
m++;
i++;
fr++;
}
int chksum = pv[m+1];
int sg = pv[m+2];
int xx = pv[m+3];
int yy = pv[m+4];
int ww = pv[m+5];
int hh = pv[m+6];
if(chksum == (sg+xx+yy+ww+hh) ) // chksum is good
{
sig[sg][0]++;
chksum = sig[sg][0]; // chksum just used here as a temp variable
sig[sg][chksum]=i+2;
}
else bk--; // if chksum not good
} // End of if sync word
i++;
} // End of while loop// This part of program demos how to pick up a specific parameter for a specific signature.// Uncomment the lines below to print out summary data// print("Number of Frames = %d, Number of Blocks = %d\n", fr, bk);// print("Number of blocks of: \n");// for(i=1; i<8; i++) print("Signature %d, = %d\n", i, sig[i][0]);// for(i=1; i<sig[kk][0]+1; i++) print("sig %d locations = %d\n", kk, sig[kk][i]); // Location of the signature word in pv[]int xx = 0;
for(i=1; i<sig[kk][0]+1; i++)
{
xx = xx + pv[sig[kk][i]+pxi];
switch(pxi)
{
case1: print("Signature %d, x = %d\n", kk, pv[sig[kk][i]+pxi]); break;
case2: print("Signature %d, y = %d\n", kk, pv[sig[kk][i]+pxi]); break;
case3: print("Signature %d, width = %d\n", kk, pv[sig[kk][i]+pxi]); break;
case4: print("Signature %d, height = %d\n", kk, pv[sig[kk][i]+pxi]); break;
}
}
int aavg = xx/sig[kk][0];
print("Signature %d, average = %d\n\n", kk, aavg);
}
This thread caught me off guard. I know to exercise caution when I read posts from erco, but as soon as I saw the gif with the balls bouncing found I had ordered one. Because I NEED another project on my bench.....
So my pixy arrived today. The install instructions for linux failed me at
This thread caught me off guard. I know to exercise caution when I read posts from erco, but as soon as I saw the gif with the balls bouncing found I had ordered one. Because I NEED another project on my bench.....
So my pixy arrived today. The install instructions for linux failed me at
I've done a little more with my PIXY. I have tried to write programs for it using BlockProp (C-version) and have had some success using the ADC method (interface mode 3) and the UART (mode 2). Today I wrote a program to have PIXY track a laser dot and control a standard servo (Ping bracket servo) attached to my ActivityBOT. I used the ADC method because it is much more simple than collecting and selecting specific data from the UART method. There was some difficulty with the ADC function that BlockyProp chose, so I copied the generated C-code to SimpleIDE and changed the function to one I was more used to. It worked. I have that C program with build info posted in the link below.
Next is to control ActivityBot motion to track the laser dot, but that's gong to take some time to figure out how I want to mount the PIXY and include whiskers or Ping to keep the Bot from running into things.
Tom
Been a while, but I've finally had a chance to make some progress (and find some more Pixy limitations).
The c program below has the ActivityBot track and more towards an object with a defined color signature. My intent was to have it work with a laser pointer, shining it in the direction I want the bot to go. But at any distance greater than about 1 foot the dot is too small for Pixy to track.
However, it will go towards an object with the defined color signature. If there are two objects, it might have a nervous breakdown since I am using the adc method which only sends the voltage corresponding to the x-position of the largest visualization of the defined color (Pixy interface mode 3)
I mounted the Pixy rigidly to the front of the activitybot. I ran Pixy pin 1 to abot adc0, pin 2 to +5v, pin3 to adc1, pin 6 to gnd.
I trained Pixy using Pixymon before I connected the pins above.
Load the program using 'load EEPROM and run' with the abot switch set to position 1. Once loaded set switch to position 2 and it will start moving.
/* pixy-activitybot-1.c
Tom Montemarano 2014
Drives activtybot towards defined color signature
Color needs to be unique and large enough to see at a distance. Laser pointer dot is too small.
ActivityBot speed is kept slow.
Future -- if signatue is out of fied of view, add rotation of abot to expand field of view and search for signature
*/#include"simpletools.h"// Include simpletools#include"abdrive.h"#include"adcDCpropab.h"// Include adcDCpropabintmain()// Main function{
adc_init(21, 20, 19, 18); // CS=21, SCL=20, DO=19, DI=18float adc0;
float adc1; // Voltage variables while(1) // Loop repeats indefinitely
{
adc0= adc_volts(0);
// print("%f\n",adc0);if(adc0 <2) drive_speed(0,0); // stop if color signature is outside camera field of view, approx +/- 37.5 deg,// start again if color signature comes into FOV else
{
adc1 = adc_volts(1);
// print("%f\n", adc1);if(adc1<1.3) // color signature is to left of center
{
drive_speed(-10,10);
pause(100);
}
elseif(adc1>1.9) // color signature is to right of center
{
drive_speed(10,-10);
pause(100);
}
elseif((adc1 <=1.9) && (adc1 >= 1.3)) // Color signature is center, need to play with limits
{
drive_speed(10,10);
pause(100);
}
} // end of main if-else
pause(200);
} // end of while
} // end of main
Today's progress -- Added a function to search for a colored object if outside the Pixy field of view, cleaned up some code, and tuned the search speeds. Thought I had a problem after I trained pixy on a bright green object and went into the family room to show my son. The bot searched and went everywhere except towards the green object. After stopping and trying a few times, I decided to let the bot run until it hit something. It went towards my patio door and then i realized that it was seeing the green trees that surround my house. So the windows and doors were all larger 'objects' than the small green toy.
So I retrained pixy on red and it worked and my son was impressed.
The code is below, and the instructions are in the previous post.
Tom
/* pixy-activitybot-2a.c
Tom Montemarano 2014
Drives activtybot towards defined color signature
Uses Pixy interface mode 3 -- voltage corresponding to x-position of largest object
Pixypin 1 -- abot adc0, Ppin2 -- +5v, Ppin3 -- adc1, Ppin6 -- gnd
Color needs to be unique and large enough to see at a distance. Laser pointer dot is too small.
ActivityBot speed is kept slow.
Includes -- if signature is out of fied of view, add rotation of abot to expand field of view
and search for signature
Future -- add Ping to stop if distance to object <5 inches
-- try averaging of x signal to minimize oscillation
*/#include"simpletools.h"// Include simpletools#include"abdrive.h"#include"adcDCpropab.h"// Include adcDCpropab#define rspd 3 // speed to rotate L or R when searching for color#define fspd 30 // forward speedfloat adc0;
float adc1; // Voltage variablesint dir = -1; // -1 = left, +1 = rightintfindsig()// ** modified to use +/- dir i.e. local sspd * dir{
int sspd = 10; // search speed
sspd = sspd * dir;
drive_speed(sspd,-sspd);
pause(2000); // turn ~60 deg one way
adc0= adc_volts(0);
// print(" findsig %f\n",adc0); // *** for debugif(adc0 <2) // Pixy pin 1 low -- no objct detected
{
drive_speed(-sspd,sspd); // search right
pause(4000); // turn ~120 deg the other
adc0= adc_volts(0);
if(adc0 <2)
{
drive_speed(sspd,-sspd);
pause(2000); // turn back to center
drive_ramp(0,0); // stop
}
}
} // end find sig intmain()// Main function{
pause(2000); // need to add a beep or something to fill dead air
adc_init(21, 20, 19, 18); // CS=21, SCL=20, DO=19, DI=18
drive_setRampStep(1); // 4 ticks per 50th of sec is defaultwhile(1) // Loop repeats indefinitely
{
adc0= adc_volts(0);
// print("%f\n",adc0); // *** for debugif(adc0 <2) // Pixy pin 1 = low -- no objct detected
{
drive_ramp(0,0); // Stop - color signature out of pixy FOV, approx +/- 37.5 deg.
findsig(); // rotate activitybot to find color
}
else
{
adc1 = adc_volts(1);
// print("%f\n", adc1); // *** for debugif(adc1<1.3) // color sig to left of center
{
dir = -1;
drive_speed(-rspd,rspd);
pause(100);
}
elseif(adc1>1.9) // color sig to right of center
{
dir = 1;
drive_speed(rspd,-rspd);
pause(100);
}
elseif((adc1 <=1.9) && (adc1 >= 1.3)) // Color sig at center, play with limits
{
drive_ramp(fspd,fspd);
pause(100);
}
} // end of main if-else
pause(200);
} // end of while
} // end of main
I'm working on a simple robot project with the activity board and pixyCMU5. I modified the arduino code to work with this board via SPI.
The initial release is here https://github.com/imbinary/parallax-pixy . I run the code in a cog and access the data from the blocks struct. One gotcha I encountered was not having enough light when testing, and not detecting anything so assumed the code was broken :frown:.
Connect the Pixy like so
pixyCMU5
Propeller activity
PIN 1
PIN 14
PIN 2
5v
PIN 3
PIN 15
PIN 4
PIN 13
PIN 6
GND
or modify pixy.c to suit your needs.
I run pixy in a cog and access the data as shown in the code below.
I'm working on a simple robot project with the activity board and pixyCMU5. I modified the arduino code to work with this board via SPI.
Hopefully this helps someone else get started.
imbinary
Thanks for the code. As you can see from the code above, my knowledge of C and interfacing is pretty elementary. I've been wanting to try using the Pixy SPI interface, but had no idea how to start. I'm going to try to work through the code to understand what you have done, and hopefully I'll learn.
Comments
They have all the info up on the wiki: http://www.cmucam.org/projects/cmucam5/wiki/Pixy_Serial_Protocol
You should be able to use one of my serial drivers that has a large FIFO buffer to easy process the data: http://obex.parallax.com/object/246
http://www.cmucam.org/projects/cmucam5/wiki
Everything you need to know is there on the wiki.
All I can find is how to read a packet from the Pixy. I don't see any way of setting the Pixy's modes.
I see Pixymon Configuration Parameters but I don's see how to use these parameters from a microcontroller? Do I have to use the PC to interface with the Pixy prior to using a Propeller over a serial line? I'm guessing yes.
I was hoping to find a list of commands the Propeller could issue to configure the Pixy on its own.
I'm learning the Pixy likes a lot of light and very bright (saturated) colors.
I wrote a program for the Propeller to monitor the tx line of the Pixy and display the data to a terminal window.
These three methods are the guts of the program.
PUB MainLoop repeat result := Pst.RxCount if result ReadPstInput result := Pixy.RxCount if result \ReadPixyFirstCharacter if abortErrorPtr NewLine Pst.Str(string("abortErrorPtr = ")) Pst.Str(abortErrorPtr) abortErrorPtr := 0 PUB ReadPixyFirstCharacter | syncIndex syncIndex := 0 result := Pixy.CharIn NewLine Pst.Str(string("Received Data From Pixy")) NewLine repeat 4 result := RxTime(DEFAULT_TIMEOUT) if result == -1 TimeOutError(syncIndex) abort else ReceiveSyncCharacter(result, syncIndex++) syncError := 0 rxChecksum := GetWord calculatedChecksum := 0 repeat result from 0 to 4 signature[result] := GetWord calculatedChecksum &= $FFFF if rxChecksum == calculatedChecksum DisplayData else DisplayData ChecksumError(rxChecksum, calculatedChecksum) abort PUB DisplayData Pst.Home NewLine Pst.Str(string("Object Data")) NewLine Pst.Str(string("signature = ")) Pst.Dec(signature) NewLine Pst.Str(string("locationX = ")) Pst.Dec(locationX) NewLine Pst.Str(string("locationY = ")) Pst.Dec(locationY) NewLine Pst.Str(string("width = ")) Pst.Dec(width) NewLine Pst.Str(string("height = ")) Pst.Dec(height) NewLine Pst.Str(string("syncError = ")) Pst.Dec(syncError)
I initially only saw zero data returned, as in eight bits of 0. Apparently the Pixy streams zeros when it doesn't have anything to say.
I used the program PixyMon to set the output to UART and to change the baud to 115,200 (from 19,200).
Here are some other changes I made.
In the "General" tab is used these settings.
Since I was just receiving zeros, I decided to change the settings and changed the saturation from 15.0 to 5.0.
I trained the Pixy with two signatures (#1 and #2) I used Post It notes as the targets. It usually takes me a couple of attempts to capture the target since I'm not sure which combination of actions will result in a captured target. At some point the program will let you drag the mouse over a captured image to select the target.
With these changes, I was able to capture a few blips of data.
Object Data signature = 2 locationX = 136 locationY = 96 width = 64 height = 23 syncError = 14004
The value "syncError" is a count of how many characters were received which didn't lead to valid packet.
I was only able to capture a few valid packets before the evening light dimmed to the point where it no long assisted the indoor light enough for a valid capture.
I'll give this a try again when I have some better lighting.
The attached program will display the packet data but each packet will be displayed over top of the previous packet (deleting the previous packet's data).
You have to make the changes shown above with PixyMon and train a few signature before the Pixy will output anything the Propeller can read.
The maximum brightness is 232. I found a setting of 80 worked pretty well.
The saturation value is important in how picky the Pixy should be about the color. It seems like somewhere between 5 and 10 worked pretty well with some colors. I'm presently using a setting of 7 for the saturation.
I reduced the number of objects to 2 and I'm only going to teach a single signature for my next experiment with the Pixy.
I'm gong to modify the code to output data about two objects at a time.
Yes, but you did say:
Which I don't completely agree with. Plus you're here and I don't want to gripe to people I don't know.
Yes, I think you're right.
I may start asking questions on the Pixy forum if I can't find the answers in the Wiki or past Pixy forum threads.
I wanted to try hooking it up to a Quickstart board and run it using pfth, but the serial methods are going to take some time for me to understand. I have an Activity Bot and realized that the Activity Board has a 4 channel ADC, The Pixy can send voltage proportional to X or Y position, and the C Learning tutorials have a couple of ADC examples. So I decided to try using the AB.
One big limitation of the Pixy is that it only has one ADC interface so can only send either x data or y data. Since I want to use this with the robot, I chose the X data (interface mode 3).
I didn't have a lot of time for this so my setup was not ideal. I was working on a card table (shake shake shake). Pixy was leaning up against a box. And I was holding a light blue pen cap as the object of interest. Also the lighting was florescent.
I used the Simple IDE C program "Measure Volts" (below) from the Simple Circuits section of the C Learning tutorial. That program uses ADC channels 2 and 3 to read voltage. Pixy sends the voltage proportional to the X position ranging from 0 volts full Left to 3.3 v full Right. I connected Pixy Pin #3 (v out) to ACT Brd ADC 3, Pixy Pin 6 (GND) to AB GND. I also attached Pixy Pin #1 to ADC 2.
Pixy pin 1 is high (3.3v) when the color is detected and 0 when not. I found testing that helped clean up the data when the object was near the extreme Left or Right of the Pixy field of view. I modified the printing near the end of the code to only print the ADC3 voltage if ADC2 voltage was >1.
/* Measure Volts.c Version 0.94 for use with SimpleIDE 9.40 and its Simple Libraries Make voltmeter style measurements with the Propeller Activity Board. http://learn.parallax.com/propeller-c-simple-circuits/measure-volts */ #include "simpletools.h" // Include simpletools #include "adcDCpropab.h" // Include adcDCpropab int main() // Main function { adc_init(21, 20, 19, 18); // CS=21, SCL=20, DO=19, DI=18 float v2, v3; // Voltage variables while(1) // Loop repeats indefinitely { v2 = adc_volts(2); // Check A/D 2 v3 = adc_volts(3); // Check A/D 3 putChar(HOME); // Cursor -> top-left "home" print("A/D2 = %f V%c\n", v2, CLREOL); // Display volts if(v2 > 1 ) print("A/D3 = %f V%c\n", v3, CLREOL); // Display volts Added condition on Pixy Pin 1 pause(300); // Increased Wait to 3/10 s } }
Because of the shakiness of my setup the voltage values printed out did have some jitter. When I did everything I could to minimize the shakes, the data was quite good with the variations in the 3rd or 4th decimal place.
Next I've got to work up the commands to use those readings to rotate the Activity Bot to track the object.
Tom
Thanks for posting what you've done.
I don't suppose I could talk you into posting some output from the Program?
Since you're using C, I wonder if you could just port the Arduino code into Propeller C?
Even without porting the full code, You might be able to make better use of the Pixy with the UART using C.
Either way (UART or ADC), I hope you keep us updated on your progress.
Duane,
The output from the code above was just the voltage values (approx 0 to approx 3.3). Using simple IDE I ran the code using the run with terminal.
I've quickly looked at the Arduino code. But quite frankly, I'm a C novice and figuring out the Arduino code is going to take some time and learning on my part. Once of the concerns I have using the UART is that the Pixy just continuously sends values. I'd be more comfortable if I could send it a command to start sending the values for a specific signature. But I'll keep working on it. One reason why I'd like to use pfth for this is that it is easier for me to see the format of the data (I have the Pixy info from he wiki) and modify things in real time.
My first step will be to use the Spin code you posted, and I will probably have some questions for you. I still have to play with the configuration settings that you described. I found that with the lighting I had, it was necessary to raise brightness to 120 to get consistent readings.
I think that the Arduino code has commands to set the Pixy configuration, like Pixymon does, so there are some good reasons to try to figure it out.
One of my problems is that I tend to jump ahead before fully working out the basics. So I'm already starting to work on methods to rotate the Activity bot to drive to a stationary object (should be pretty easy), and then to rotate to follow a moving object (steady motion and then random motion). I realize that there are folks here for whom that would be almost trivial, but its more new ground for me.
I'll keep updating.
Tom
I haven't seen these codes myself. As far as I can tell, there are a lot of configuration parameters that have to be set with the Pixymon program. IMO, this aspect of the Pixy is very bothersome.
I tried to figure out the UART. I tried Duane's Spin code from post 5 and got very inconsistent results. Some times I would get some values, other times all zeros.
Tonight I tried using Forth (pfth version) to see if I could decipher what the Pixy UART was putting out. I have a routine that I used to debug a bluetooth serial connection. I have a forth word (bt>str) that simply does an FDS_Read (fds_rx) and stores the byte received in a string array and repeats. Once the array is filled the word ends. Then I use a forth word (.bt) that prints out the byte values. That way I can see the how the sending device formats the block. Because of the size of the Pixy block (14 bytes) I increased the array size to 129 bytes, so I could catch at least a few blocks.
First thing I found out was that I received a couple of initial bytes and then just zeros if I had Pixymon running. So I closed that program.
Once I did that I initially tried using my normal baud rate of 115200.
These are the results I got:
$00000080 $00000010 $00000010 $00000040 $00000000 $00000000 $000000da $00000000 $0000000a $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $0000003c $000000aa $00000001 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $0000003a $00000000 $000000a5 $00000001 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000055 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000055 $00000001 $0000002c $00000000 $00000009 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $000000aa $000000aa $00000000 $0000002c $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000055 $000000aa $00000001 $00000001 $0000005e $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000
I looked for the Pixy sync word aa55 (or 55 aa, LSB first). If you search through the above, you will see only one instance of that, and it appears to be an incomplete block. I guessed that 115200 baud might be too fast and characters were being lost. So I tried the Pixy default of 19200 baud.
The results from that were:
$00000080 $00000054 $000000a5 $00000056 $000000a5 $000000f6 $00000005 $00000005 $00000002 $000000a2 $00000000 $0000001b $00000000 $0000003e $00000000 $00000031 $000000aa $00000084 $00000001 $00000001 $00000000 $0000003b $00000001 $0000003d $00000000 $00000009 $00000000 $00000002 $00000000 $00000055 $000000aa $000000a8 $00000001 $00000001 $00000000 $00000039 $00000001 $00000056 $00000000 $0000000d $00000000 $0000000b $00000000 $00000055 $000000aa $0000009f $00000001 $00000001 $00000000 $00000039 $00000001 $00000054 $00000000 $0000000d $00000000 $00000004 $00000000 $00000055 $000000aa $00000083 $00000001 $00000001 $00000000 $000000f5 $00000000 $0000001a $00000000 $0000003d $00000000 $00000032 $00000000 $00000055 $000000aa $000000a2 $00000001 $00000001 $00000000 $000000f5 $00000000 $0000001a $00000000 $0000003d $00000000 $00000031 $00000000 $00000055 $000000aa $000000a6 $00000001 $00000001 $00000000 $0000003a $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000000 $00000055 $000000aa $00000055 $000000aa $00000080 $00000001 $00000001 $00000001 $00000058 $00000000 $0000000c $00000000 $0000000a $00000000 $00000055 $000000aa $000000b1 $00000001 $00000001 $00000000 $0000003e $00000001 $00000067 $00000000 $0000003c $00000000 $00000032
I put in some line feeds to set off the complete blocks. There are a number of complete 14 byte blocks starting with 55 aa. (I have to try a slower baud to see if the results get better). However, at the begining and end of the buffer there are values that don't make any sense or are partial blocks. The Pixy wiki states that if Pixy is transmitting a block and the next cycle of data starts, it will just discard the data from the previous block. That makes decoding more complex. Again, I wish that they had written the firmware so that the user could start and stop transmission blocks remotely rather than just having Pixy bang away.
Next I took a couple of blocks and translated them into decimal to see if they made any sense.
Here's one:
[TABLE] [TR] [TD="class: xl22"][SIZE=2]Word [/SIZE][/TD] [TD="class: xl23"][SIZE=2]Description[/SIZE][/TD] [TD="class: xl23"][SIZE=2]Byte[/SIZE][/TD] [TD="class: xl23"][SIZE=2]Value[/SIZE][/TD] [TD="class: xl23, width: 69"][SIZE=2]Word[/SIZE][/TD] [TD="class: xl38, width: 86"][SIZE=2]Decimal[/SIZE][/TD] [TD="class: xl42, width: 64"][SIZE=2]Pixy Range[/SIZE][/TD] [/TR] [TR] [TD="class: xl24, width: 64"][SIZE=2]0[/SIZE][/TD] [TD="class: xl26, width: 130"][SIZE=2]Sync aa55[/SIZE][/TD] [TD="class: xl35, width: 64"][SIZE=2]Lo[/SIZE][/TD] [TD="class: xl25, width: 95"][SIZE=2]$00000055[/SIZE][/TD] [TD="class: xl25, width: 69"][SIZE=2]aa55[/SIZE][/TD] [TD="class: xl39, width: 86"][SIZE=2]43,605[/SIZE][/TD] [TD="class: xl45"][SIZE=2] [/SIZE][/TD] [/TR] [TR] [TD="class: xl30, width: 64"][SIZE=2] [/SIZE][/TD] [TD="class: xl32, width: 130"][SIZE=2] [/SIZE][/TD] [TD="class: xl36, width: 64"][SIZE=2]Hi[/SIZE][/TD] [TD="class: xl31, width: 95"][SIZE=2]$000000aa[/SIZE][/TD] [TD="class: xl31, width: 69"][SIZE=2] [/SIZE][/TD] [TD="class: xl40, width: 86"][SIZE=2] [/SIZE][/TD] [TD="class: xl46"][SIZE=2] [/SIZE][/TD] [/TR] [TR] [TD="class: xl27, width: 64"][SIZE=2]1[/SIZE][/TD] [TD="class: xl29, width: 130"][SIZE=2]checksum sum 2-6[/SIZE][/TD] [TD="class: xl37, width: 64"][SIZE=2]Lo[/SIZE][/TD] [TD="class: xl28, width: 95"][SIZE=2]$0000009f[/SIZE][/TD] [TD="class: xl28, width: 69"][SIZE=2]019f[/SIZE][/TD] [TD="class: xl41, width: 86"][SIZE=2]415[/SIZE][/TD] [TD="class: xl45"][SIZE=2] [/SIZE][/TD] [/TR] [TR] [TD="class: xl30, width: 64"][SIZE=2] [/SIZE][/TD] [TD="class: xl32, width: 130"][SIZE=2] [/SIZE][/TD] [TD="class: xl36, width: 64"][SIZE=2]Hi[/SIZE][/TD] [TD="class: xl31, width: 95"][SIZE=2]$00000001[/SIZE][/TD] [TD="class: xl31, width: 69"][SIZE=2] [/SIZE][/TD] [TD="class: xl40, width: 86"][SIZE=2] [/SIZE][/TD] [TD="class: xl46"][SIZE=2] [/SIZE][/TD] [/TR] [TR] [TD="class: xl27, width: 64"][SIZE=2]2[/SIZE][/TD] [TD="class: xl29, width: 130"][SIZE=2]Signature[/SIZE][/TD] [TD="class: xl37, width: 64"][SIZE=2]Lo[/SIZE][/TD] [TD="class: xl28, width: 95"][SIZE=2]$00000001[/SIZE][/TD] [TD="class: xl28, width: 69"][SIZE=2]0001[/SIZE][/TD] [TD="class: xl41, width: 86"][SIZE=2]1[/SIZE][/TD] [TD="class: xl45"][SIZE=2]1 - 7[/SIZE][/TD] [/TR] [TR] [TD="class: xl30, width: 64"][SIZE=2] [/SIZE][/TD] [TD="class: xl32, width: 130"][SIZE=2] [/SIZE][/TD] [TD="class: xl36, width: 64"][SIZE=2]Hi[/SIZE][/TD] [TD="class: xl31, width: 95"][SIZE=2]$00000000[/SIZE][/TD] [TD="class: xl31, width: 69"][SIZE=2] [/SIZE][/TD] [TD="class: xl40, width: 86"][SIZE=2] [/SIZE][/TD] [TD="class: xl46"][SIZE=2] [/SIZE][/TD] [/TR] [TR] [TD="class: xl27, width: 64"][SIZE=2]3[/SIZE][/TD] [TD="class: xl29, width: 130"][SIZE=2]x-center[/SIZE][/TD] [TD="class: xl37, width: 64"][SIZE=2]Lo[/SIZE][/TD] [TD="class: xl28, width: 95"][SIZE=2]$00000039[/SIZE][/TD] [TD="class: xl28, width: 69"][SIZE=2]0139[/SIZE][/TD] [TD="class: xl41, width: 86"][SIZE=2]313[/SIZE][/TD] [TD="class: xl45"][SIZE=2]0 - 319[/SIZE][/TD] [/TR] [TR] [TD="class: xl30, width: 64"][SIZE=2] [/SIZE][/TD] [TD="class: xl32, width: 130"][SIZE=2] [/SIZE][/TD] [TD="class: xl36, width: 64"][SIZE=2]Hi[/SIZE][/TD] [TD="class: xl31, width: 95"][SIZE=2]$00000001[/SIZE][/TD] [TD="class: xl31, width: 69"][SIZE=2] [/SIZE][/TD] [TD="class: xl40, width: 86"][SIZE=2] [/SIZE][/TD] [TD="class: xl46"][SIZE=2] [/SIZE][/TD] [/TR] [TR] [TD="class: xl27, width: 64"][SIZE=2]4[/SIZE][/TD] [TD="class: xl29, width: 130"][SIZE=2]y-center[/SIZE][/TD] [TD="class: xl37, width: 64"][SIZE=2]Lo[/SIZE][/TD] [TD="class: xl28, width: 95"][SIZE=2]$00000054[/SIZE][/TD] [TD="class: xl28, width: 69"][SIZE=2]0054[/SIZE][/TD] [TD="class: xl41, width: 86"][SIZE=2]84[/SIZE][/TD] [TD="class: xl45"][SIZE=2]0 - 199[/SIZE][/TD] [/TR] [TR] [TD="class: xl30, width: 64"][SIZE=2] [/SIZE][/TD] [TD="class: xl32, width: 130"][SIZE=2] [/SIZE][/TD] [TD="class: xl36, width: 64"][SIZE=2]Hi[/SIZE][/TD] [TD="class: xl31, width: 95"][SIZE=2]$00000000[/SIZE][/TD] [TD="class: xl31, width: 69"][SIZE=2] [/SIZE][/TD] [TD="class: xl40, width: 86"][SIZE=2] [/SIZE][/TD] [TD="class: xl46"][SIZE=2] [/SIZE][/TD] [/TR] [TR] [TD="class: xl27, width: 64"][SIZE=2]5[/SIZE][/TD] [TD="class: xl29, width: 130"][SIZE=2]width[/SIZE][/TD] [TD="class: xl37, width: 64"][SIZE=2]Lo[/SIZE][/TD] [TD="class: xl28, width: 95"][SIZE=2]$0000000d[/SIZE][/TD] [TD="class: xl28, width: 69"][SIZE=2]000d[/SIZE][/TD] [TD="class: xl41, width: 86"][SIZE=2]13[/SIZE][/TD] [TD="class: xl45"][SIZE=2]1 - 320[/SIZE][/TD] [/TR] [TR] [TD="class: xl30, width: 64"][SIZE=2] [/SIZE][/TD] [TD="class: xl32, width: 130"][SIZE=2] [/SIZE][/TD] [TD="class: xl36, width: 64"][SIZE=2]Hi[/SIZE][/TD] [TD="class: xl31, width: 95"][SIZE=2]$00000000[/SIZE][/TD] [TD="class: xl31, width: 69"][SIZE=2] [/SIZE][/TD] [TD="class: xl40, width: 86"][SIZE=2] [/SIZE][/TD] [TD="class: xl46"][SIZE=2] [/SIZE][/TD] [/TR] [TR] [TD="class: xl27, width: 64"][SIZE=2]6[/SIZE][/TD] [TD="class: xl29, width: 130"][SIZE=2]height[/SIZE][/TD] [TD="class: xl37, width: 64"][SIZE=2]Lo[/SIZE][/TD] [TD="class: xl28, width: 95"][SIZE=2]$00000004[/SIZE][/TD] [TD="class: xl28, width: 69"][SIZE=2]0004[/SIZE][/TD] [TD="class: xl41, width: 86"][SIZE=2]4[/SIZE][/TD] [TD="class: xl45"][SIZE=2]1 - 200[/SIZE][/TD] [/TR] [TR] [TD="class: xl30, width: 64"][SIZE=2] [/SIZE][/TD] [TD="class: xl32, width: 130"][SIZE=2] [/SIZE][/TD] [TD="class: xl36, width: 64"][SIZE=2]Hi[/SIZE][/TD] [TD="class: xl31, width: 95"][SIZE=2]$00000000[/SIZE][/TD] [TD="class: xl31, width: 69"][SIZE=2] [/SIZE][/TD] [TD="class: xl40, width: 86"][SIZE=2] [/SIZE][/TD] [TD="class: xl46"][SIZE=2] [/SIZE][/TD] [/TR] [TR] [TD="class: xl33, width: 64"][SIZE=2] [/SIZE][/TD] [TD="class: xl34, width: 130"][SIZE=2]Sum 2 6[/SIZE][/TD] [TD="class: xl43, width: 64"][SIZE=2] [/SIZE][/TD] [TD="class: xl34, width: 95"][SIZE=2] [/SIZE][/TD] [TD="class: xl34, width: 69"][SIZE=2] [/SIZE][/TD] [TD="class: xl44, width: 86"][SIZE=2]415[/SIZE][/TD] [TD="class: xl47"][SIZE=2] [/SIZE][/TD] [/TR] [/TABLE] [SIZE=2] [/SIZE]
It appears that the results are reasonable. Now that am getting some consistent results I'll have to try with a more controlled set up (instead of me just waving a flower in front of the lens). Then the next thing is to try to use the serial objects in either spin or C to try to collect the data and make use of it.
I have also done a little more with the ADC method in C, translating the x-location (from voltage) into a command to rotate the Activity Bot. I have to do some work on the robot (replace Ping with Pixy) and see how it works.
Tom
I tried a more controlled test. I mounted 3 pieces of different size non-glossy colored paper rectangles on a white board, and trained Pixy for each color. Then kept everything in a fixed location.
The pixy wiki states that Pixy will transmit a new frame of data every 20 ms and can send data on 135 objects per frame (approx 1 per 0.15 ms). I calculated that at 19200 baud, Pixy would send 3 objects worth (14 byte blocks - 2 sync bytes 55, aa and 12 data bytes) of data in each frame. Each Frame starts with 4 hex bytes: 55, aa, 55, aa and then the data from the first block, followed by 55, aa starting the second block, etc. Pixy sends the data in decreasing order of size of each block.
At 19200 baud, I got some data that looked good, but less than 50% of the blocks were ok. The rest seemed to be blocks with data out of order, wrong number of data bytes, etc. It seemed as though Pixy was sending data faster than pfth could handle it (simply put it into an element in a character array and test for the maximum number of bytes in the array.) I have used pfth with Full Duplex Serial at 115200 baud from a bluetooth device, but the BT device sends the data packets at a relatively slow speed (e.g. speed of typing).
Since decreasing the baud rate of the Pixy serial connection from 115200 to 19200 enabled getting some correct data blocks, I lowered the baud rate one more step to 9600. Using that I got reliable data almost all of the time. But because of the reduced baud rate Pixy was only able to send 1 block of data per frame. And since the Pixy priority is to send the data block for the largest item first, that is the only data that can be received.
From what Dave Hein has written, pfth is not the fastest language around. I will have to try in both Spin and C to see if they are fast enough to use with FDS. I will also have to learn how to use the Pixy SPI and I2C interface to see how they work.
I tried using C with Simple IDE. It was a very simple program (see below): open the serial port, read a byte, print it on the terminal.
I was able to read 5 blocks of data per frame accurately at 19200 baud with the Pixymon program not running. The next thing to do is to sync data collection and interpretation with the Pixy sync bytes. I'll also try some tests with higher baud with Pixymon off.
Tom
/* C code used with Pixy - CMUCAM5 Test to see how many blocks of data can be received per frame. Just performed Rx and printed value. Result - With Pixymon running, the serial port had to run at 9600 baud and only one block was received per frame - With Pixymon program closed, the serial port ran at 19200 baud and 5 blocks were received per frame. The checksum confirmed that the data was received correctly */ #include "simpletools.h" // Include simple tools #include "fdserial.h" fdserial *blut; char c1; int main() { // fdserial * fdserial_open(int rxpin, int txpin, int mode, int baudrate) blut = fdserial_open(9, 8, 0, 19200); while(1) // do forever { c1 = fdserial_rxChar(blut); // read byte from Pixy print("%d\n", c1); } }
Thanks for sharing your experiences using it!
Dave
In the following column in excel, next to the first byte for each word (LSB) -- for example in cell D5, I entered the following =(256*D6)+D5, so I could have all the word values sent and check the checksum for accuracy.
I got the following results. Note that in some cases, after sending a complete block of data, there would be a series of zeros without a starting sync word. Based on the pixy documentation, this indicates no signatures detected. I was doing this test in a medium well lit room, and I could see when using Pixymon that sometimes the signatures would flicker.
I tried 57600 baud, but there were many errors.
My conclusions from the results below are that if I have to use CMM to fit a program, I would restrict the baud to 14400 if I wanted no errors. If I had good error detection in my software, I'd use 16800. If I could use LMM, I'd choose 19200 or 38400.
Tom
Mem Model
Optmization
Baud
B/F max
B/F min
B/F typical
Num Err
CMM
Size
14400
3
1
2
0
CMM
Size
16800
4
2
2
1
CMM
Speed
16800
3
2
2
1
LMM
Size
16800
3
2
2
0
LMM
Speed
19200
3
2
2
0
LMM
Speed
38400
6
1
4
0
Note that I did try to find the first sync word and then start reading values from Pixy, but there was enough of a delay that the first 2 or 3 words after the sync were lost. So that's why I read everything and then truncate.
Tom
Here's the code:
/* C code used with Pixy - CMUCAM5 Tom Montemarano June 2014, MIT License. 1. Collects data from Pixy (LSB, MSB) 2. Discards values before first sync word. 3. Calculates and saves pixy words Run with terminal. This version shows all intermediate steps. The last part of the printout is the words in one column that can be cut and pasted into excel. The order is: 43605 (sync), checksum (sum of next 5 words), signature # (1 - 7), x-position, y-position, width, height. 2 sync words in succession mean start of new frame. Set Pixy to 19200 baud Now that I got it working I need to: 1. write code that can select a specific signature, and position 2. clean up and tighten up. 3. Put getting Pixy data in separate cog. 4. Loop to control Activitybot */ #include "simpletools.h" // Include simple tools #include "fdserial.h" #define mvs 130 fdserial *pixy; int mvals = mvs; char c1[mvs]; int c2[mvs]; char synclsb = 85; char syncmsb = 170; int i; int j; int k; int flg; int pv[mvs/2]; int main() { // fdserial * fdserial_open(int rxpin, int txpin, int mode, int baudrate) pixy = fdserial_open(9, 8, 0, 19200); // This baud seems optimum - it collects 2 or 3 blocks per frame w/o errors for(i=1; i<mvals; i++) c1[i] = fdserial_rxChar(pixy) ; // read byte from Pixy with no delays print("values read\n"); k=1; j=1; flg = 0; for(i=1; i<mvals; i++) { if(flg == 0) { if(c1[i] ==synclsb) // Find first sync word's LSB { print("synclsb\n"); if(c1[i+1] ==syncmsb) // Is next byte the first sync word's MSB { print("syncmsb\n"); flg=1; } } } if(flg==1) { print("flg=1\n"); c2[k] = c1[i]; // put bytes starting with first sync word into integer print("k = %d, c2 = %d\n", k, c2[k] ); k++; } } print("k = %d\n", k ); for(i=1; i<k; i=i+2) { pv[j] = c2[i]+ (c2[i+1]<<8); // take LSB and MSB and make word print("j = %d, pv = %d\n", j, pv[j] ); j++; } for(i=1; i<j; i++) print("%d\n", pv[i]); // Printout words in column }
The demo just prints out the pixywords in the terminal. It uses a while(1) loop and prints "end of data" between pixy data collections.
Tom
Here's the code:
/* C code used with Pixy - CMUCAM5 Tom Montemarano June 2014, MIT License. 1. Collects data from Pixy (LSB, MSB) 2. Discards values before first sync word. 3. Calculates and saves pixy words Run with terminal. Uncomment print statements to print intermediate steps. The last part of the printout is the words in one column that can be cut and pasted into excel. The order is: 43605 (sync), checksum (sum of next 5 words), signature # (1 - 7), x-position of centroid, y-position, width, height. 2 sync words in succession mean start of new frame. Set Pixy to 19200 baud Now that I got it working I need to: 1. write code that can select a specific signature, and position 2. clean up and tighten up. (done?) 3. Put getting Pixy data in separate cog. (done) 4. Loop to control Activitybot */ #include "simpletools.h" // Include simple tools #include "fdserial.h" #define mvs 110 // To get one full frame (2 - 3 blocks) set mvs to 110 fdserial *pixy; void getpixy(); // forward declare function int *cog; volatile int mvals = mvs; volatile char c1[mvs]; // raw byte values from pixy volatile int flag; // use as a lock char synclsb = 85; // LSB of sync word char syncmsb = 170; // MSB of sync word int pv[mvs/2]; // Pixy words int main() { int i; int j; int k; int flg; // flg = 1 when first sync word located flag = 0; cog = cog_run(&getpixy, 128); while(1) // do forever { while(flag==0) { } // stall main while getpixy collects data flag=1; // stall getpixy k = 1; j = 1; flg = 0; i = 0; while(flg == 0) { i++; if(c1[i] == synclsb) // Find first sync word LSB { // print("synclsb\n"); if(c1[i+1] == syncmsb) // Find first sync word MSB { // print("syncmsb\n"); flg=1; // Got first sync word, set flg=1 } } } for(k=i; k<mvals-2; k=k+2) { pv[j]=c1[k+1]; // make MSB integer for shift pv[j]=(pv[j] <<8) | c1[k]; // take LSB and MSB and make Pixy word // print("j = %d, pv = %d\n", j, pv[j] ); j++; } for(i=1; i<j; i++) print("%d\n", pv[i]); // Printout words in column print("end of data \n"); flag=0; // unstall get pixy } // end of infinite while loop } // end main void getpixy() { int i; // fdserial * fdserial_open(int rxpin, int txpin, int mode, int baudrate) pixy = fdserial_open(9, 8, 0, 19200); // This baud seems optimum - collects 2 or 3 blocks per frame w/o errors while(1) { while( flag==1){ } // Wait until main finishes and sets flag = 0 for(i=1; i<mvals; i++) c1[i] = fdserial_rxChar(pixy) ; // read bytes from Pixy with no delays flag = 1; // stall serial and start main processing } }
/* C code used with Pixy - CMUCAM5 Tom Montemarano June 2014, MIT License. This program prints out the average value of x for a chosen signature 1. Collects data from Pixy (LSB, MSB) 2. Discards values before first sync word. 3. Calculates and saves pixy words 4. Checks ckecksum 5. Indexs blocks by signature number 6. Gets x-position for selected signature and averages it. Run with terminal. This version only prints out the data and average value of x, y, width, or height for the selected signature to show how quickly it runs. There are 4 parameters that can be changed (kk, zz, dd, pxi) to change: kk = the color signature of interest, zz = the number of data sets, dd = the delay between data sets, and pxi = the parameter to be printed (x, y, w, or h). Uncomment other print words to get see intermediate steps including: The words in one column that can be cut and pasted into excel. The number of blocks collected. The number of blocks of each signature value The indices of PV[] that contain the signature number The order of Pixy words in each block is: 43605 (sync), checksum (sum of next 5 words), signature # (1 - 7), x-position of centroid, y-position, width, height. 2 sync words in succession mean start of new frame. Set Pixy to 19200 baud Now that I got it working I need to: 1. write code that can select a specific signature, and position - done 2. clean up and tighten up. - 3. Put getting Pixy data in separate cog - done (not in this program) 4. Loop to control Activitybot */ #include "simpletools.h" // Include simple tools #include "fdserial.h" #define mvs 210 // To get one full frame (2 - 3 blocks) set mvs to 110 void indexpixy(void); fdserial *pixy; int mvals = mvs; char c1[mvs]; // raw byte values from pixy char synclsb = 85; // LSB of sync word char syncmsb = 170; // MSB of sync word int i; int j; // number of pixy words int k; // These 4 values are for the demo int kk = 1; // signature of interest to be printed out -- set to a color signature taught to Pixy (1 - 7) int zz = 5; // Number of averages to print int dd = 100; // Delay in ms between data sets - use smaller to show program speed, larger to demo motion int pxi = 1; // This points to the specific value in the block - 1=x, 2=y, 3=width, 4=height int m; int bk; int fr; int flg; // flg = 1 when first sync word located int pv[mvs/2]; // Pixy words int sig[8][12]; // signature number, number of blocks int main() { // fdserial * fdserial_open(int rxpin, int txpin, int mode, int baudrate) pixy = fdserial_open(9, 8, 0,19200); // This baud seems optimum - it collects 2 or 3 blocks per frame w/o errors // With more objects, the baud can be increased int z; for(z=1; z<zz+1; z++) { for(i=1; i<mvals; i++) c1[i] = fdserial_rxChar(pixy) ; // read byte from Pixy with no delays // print("values read\n"); k = 1; j = 1; flg = 0; i = 0; while(flg == 0) { i++; if(c1[i] == synclsb) // Find first sync word LSB { // print("synclsb\n"); if(c1[i+1] == syncmsb) // Find first sync word MSB { // print("syncmsb\n"); flg=1; // Got first sync word, set flg=1 } } } for(k=i; k<mvals-2; k=k+2) { pv[j]=c1[k+1]; // make MSB integer for shift pv[j]=(pv[j] <<8) | c1[k]; // take LSB and MSB and make Pixy word // print("j = %d, pv = %d\n", j, pv[j] ); j++; } // for(i=1; i<j; i++) print("%d\n", pv[i]); // Printout words in one column // print("j = %d\n", j); indexpixy(); pause(dd); } } // end main void indexpixy(void) // { // 43605 = decimal sync word for(i=1; i<8; i++) sig[i][0] = 0; fr = bk = 0; i=1; while (i < j ) { if(pv[i] == 43605) // sync word { m = i; bk++; if(pv[i+1] == 43605) { m++; i++; fr++; } int chksum = pv[m+1]; int sg = pv[m+2]; int xx = pv[m+3]; int yy = pv[m+4]; int ww = pv[m+5]; int hh = pv[m+6]; if(chksum == (sg+xx+yy+ww+hh) ) // chksum is good { sig[sg][0]++; chksum = sig[sg][0]; // chksum just used here as a temp variable sig[sg][chksum]=i+2; } else bk--; // if chksum not good } // End of if sync word i++; } // End of while loop // This part of program demos how to pick up a specific parameter for a specific signature. // Uncomment the lines below to print out summary data // print("Number of Frames = %d, Number of Blocks = %d\n", fr, bk); // print("Number of blocks of: \n"); // for(i=1; i<8; i++) print("Signature %d, = %d\n", i, sig[i][0]); // for(i=1; i<sig[kk][0]+1; i++) print("sig %d locations = %d\n", kk, sig[kk][i]); // Location of the signature word in pv[] int xx = 0; for(i=1; i<sig[kk][0]+1; i++) { xx = xx + pv[sig[kk][i]+pxi]; switch(pxi) { case 1: print("Signature %d, x = %d\n", kk, pv[sig[kk][i]+pxi]); break; case 2: print("Signature %d, y = %d\n", kk, pv[sig[kk][i]+pxi]); break; case 3: print("Signature %d, width = %d\n", kk, pv[sig[kk][i]+pxi]); break; case 4: print("Signature %d, height = %d\n", kk, pv[sig[kk][i]+pxi]); break; } } int aavg = xx/sig[kk][0]; print("Signature %d, average = %d\n\n", kk, aavg); }
So my pixy arrived today. The install instructions for linux failed me at
/pixymon $ ./buildpixymon.sh Building for linux ./buildpixymon.sh: line 15: qmake-qt4: command not found make: Entering directory `/home/braino/Downloads/pixymon/src/host/pixymon' make: *** No targets specified and no makefile found. Stop. make: Leaving directory `/home/braino/Downloads/pixymon/src/host/pixymon' mkdir: cannot create directory bin: File exists cp: cannot stat src/host/pixymon/PixyMon: No such file or directory strip: 'bin/PixyMon': No such file
Once I get that resolved, I will start on adding pixy to LittleRobot.
Good Good
Next is to control ActivityBot motion to track the laser dot, but that's gong to take some time to figure out how I want to mount the PIXY and include whiskers or Ping to keep the Bot from running into things.
Tom
http://forums.parallax.com/showthread.php/155208-Open-Propeller-Project-5-BlocklyProp?p=1276733#post1276733
The c program below has the ActivityBot track and more towards an object with a defined color signature. My intent was to have it work with a laser pointer, shining it in the direction I want the bot to go. But at any distance greater than about 1 foot the dot is too small for Pixy to track.
However, it will go towards an object with the defined color signature. If there are two objects, it might have a nervous breakdown since I am using the adc method which only sends the voltage corresponding to the x-position of the largest visualization of the defined color (Pixy interface mode 3)
I mounted the Pixy rigidly to the front of the activitybot. I ran Pixy pin 1 to abot adc0, pin 2 to +5v, pin3 to adc1, pin 6 to gnd.
I trained Pixy using Pixymon before I connected the pins above.
Load the program using 'load EEPROM and run' with the abot switch set to position 1. Once loaded set switch to position 2 and it will start moving.
/* pixy-activitybot-1.c Tom Montemarano 2014 Drives activtybot towards defined color signature Color needs to be unique and large enough to see at a distance. Laser pointer dot is too small. ActivityBot speed is kept slow. Future -- if signatue is out of fied of view, add rotation of abot to expand field of view and search for signature */ #include "simpletools.h" // Include simpletools #include "abdrive.h" #include "adcDCpropab.h" // Include adcDCpropab int main() // Main function { adc_init(21, 20, 19, 18); // CS=21, SCL=20, DO=19, DI=18 float adc0; float adc1; // Voltage variables while(1) // Loop repeats indefinitely { adc0= adc_volts(0); // print("%f\n",adc0); if(adc0 <2) drive_speed(0,0); // stop if color signature is outside camera field of view, approx +/- 37.5 deg, // start again if color signature comes into FOV else { adc1 = adc_volts(1); // print("%f\n", adc1); if(adc1<1.3) // color signature is to left of center { drive_speed(-10,10); pause(100); } else if(adc1>1.9) // color signature is to right of center { drive_speed(10,-10); pause(100); } else if((adc1 <=1.9) && (adc1 >= 1.3)) // Color signature is center, need to play with limits { drive_speed(10,10); pause(100); } } // end of main if-else pause(200); } // end of while } // end of main
So I retrained pixy on red and it worked and my son was impressed.
The code is below, and the instructions are in the previous post.
Tom
/* pixy-activitybot-2a.c Tom Montemarano 2014 Drives activtybot towards defined color signature Uses Pixy interface mode 3 -- voltage corresponding to x-position of largest object Pixypin 1 -- abot adc0, Ppin2 -- +5v, Ppin3 -- adc1, Ppin6 -- gnd Color needs to be unique and large enough to see at a distance. Laser pointer dot is too small. ActivityBot speed is kept slow. Includes -- if signature is out of fied of view, add rotation of abot to expand field of view and search for signature Future -- add Ping to stop if distance to object <5 inches -- try averaging of x signal to minimize oscillation */ #include "simpletools.h" // Include simpletools #include "abdrive.h" #include "adcDCpropab.h" // Include adcDCpropab #define rspd 3 // speed to rotate L or R when searching for color #define fspd 30 // forward speed float adc0; float adc1; // Voltage variables int dir = -1; // -1 = left, +1 = right int findsig() // ** modified to use +/- dir i.e. local sspd * dir { int sspd = 10; // search speed sspd = sspd * dir; drive_speed(sspd,-sspd); pause(2000); // turn ~60 deg one way adc0= adc_volts(0); // print(" findsig %f\n",adc0); // *** for debug if(adc0 <2) // Pixy pin 1 low -- no objct detected { drive_speed(-sspd,sspd); // search right pause(4000); // turn ~120 deg the other adc0= adc_volts(0); if(adc0 <2) { drive_speed(sspd,-sspd); pause(2000); // turn back to center drive_ramp(0,0); // stop } } } // end find sig int main() // Main function { pause(2000); // need to add a beep or something to fill dead air adc_init(21, 20, 19, 18); // CS=21, SCL=20, DO=19, DI=18 drive_setRampStep(1); // 4 ticks per 50th of sec is default while(1) // Loop repeats indefinitely { adc0= adc_volts(0); // print("%f\n",adc0); // *** for debug if(adc0 <2) // Pixy pin 1 = low -- no objct detected { drive_ramp(0,0); // Stop - color signature out of pixy FOV, approx +/- 37.5 deg. findsig(); // rotate activitybot to find color } else { adc1 = adc_volts(1); // print("%f\n", adc1); // *** for debug if(adc1<1.3) // color sig to left of center { dir = -1; drive_speed(-rspd,rspd); pause(100); } else if(adc1>1.9) // color sig to right of center { dir = 1; drive_speed(rspd,-rspd); pause(100); } else if((adc1 <=1.9) && (adc1 >= 1.3)) // Color sig at center, play with limits { drive_ramp(fspd,fspd); pause(100); } } // end of main if-else pause(200); } // end of while } // end of main
Tom
http://forums.parallax.com/showthread.php/156970-Bluetooth-App-to-control-ActivityBot
The initial release is here https://github.com/imbinary/parallax-pixy . I run the code in a cog and access the data from the blocks struct. One gotcha I encountered was not having enough light when testing, and not detecting anything so assumed the code was broken :frown:.
Connect the Pixy like so
pixyCMU5
Propeller activity
PIN 1
PIN 14
PIN 2
5v
PIN 3
PIN 15
PIN 4
PIN 13
PIN 6
GND
or modify pixy.c to suit your needs.
I run pixy in a cog and access the data as shown in the code below.
pixy_cog = cog_run(&pixyStart, 60); while(1) { pause(500); if(blockCount){ //dprint(xbee,"pixy: %d\n",blocks[0].x); dprint(xbee,"pixy: count %d x(%d) y(%d)\n",blockCount,blocks[0].x,blocks[0].y); } }
Hopefully this helps someone else get started.
imbinary
I've had the same (lack of) light problem with the Pixy.
Thanks for posting your code and welcome to the forums.
I hope you share more details about your project with us sometime.
Thanks for the code. As you can see from the code above, my knowledge of C and interfacing is pretty elementary. I've been wanting to try using the Pixy SPI interface, but had no idea how to start. I'm going to try to work through the code to understand what you have done, and hopefully I'll learn.
Thanks again,
Tom