Pixy for Propeller?

I have the new pixy (CMUcam5) but I have no idea how to use it for the propeller (or the stamp for that matter).

Is anybody working on this?
«1

Comments

  • 43 Comments sorted by Date Added Votes
  • KyeKye Posts: 2,200
    edited May 2014 Vote Up0Vote Down
    Hi,

    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.
    Nyamekye,
  • Jim the HermitJim the Hermit Posts: 79
    edited May 2014 Vote Up0Vote Down
    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.
  • Duane DegnDuane Degn Posts: 10,002
    edited May 2014 Vote Up0Vote Down
    Kye wrote: »
    Hi,

    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.
  • Duane DegnDuane Degn Posts: 10,002
    edited May 2014 Vote Up0Vote Down
    I managed to get some data from the Pixy but just barely.

    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).

    attachment.php?attachmentid=108475&stc=1

    Here are some other changes I made.

    In the "General" tab is used these settings.

    attachment.php?attachmentid=108474&stc=1

    Since I was just receiving zeros, I decided to change the settings and changed the saturation from 15.0 to 5.0.

    attachment.php?attachmentid=108476&stc=1

    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.
  • Duane DegnDuane Degn Posts: 10,002
    edited May 2014 Vote Up0Vote Down
    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.
  • KyeKye Posts: 2,200
    edited May 2014 Vote Up0Vote Down
    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.
    Nyamekye,
  • Duane DegnDuane Degn Posts: 10,002
    edited May 2014 Vote Up0Vote Down
    Kye wrote: »
    I didn't build the pixy. Different team. I designed the CMUcam4.

    Yes, but you did say:
    Kye wrote: »
    Everything you need to know is there on the wiki.

    Which I don't completely agree with. Plus you're here and I don't want to gripe to people I don't know. :smile:
    Kye wrote: »
    Play with it a bit and you should be able to get going.

    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.
  • Jim the HermitJim the Hermit Posts: 79
    edited May 2014 Vote Up0Vote Down
    Just so you know, I'm watching this thread with interest
  • KyeKye Posts: 2,200
    edited May 2014 Vote Up0Vote Down
    @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.
    Nyamekye,
  • twm47099twm47099 Posts: 670
    edited May 2014 Vote Up0Vote Down
    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 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
  • Duane DegnDuane Degn Posts: 10,002
    edited May 2014 Vote Up0Vote Down
    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.
  • twm47099twm47099 Posts: 670
    edited May 2014 Vote Up0Vote Down
    Duane Degn wrote: »
    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
  • Duane DegnDuane Degn Posts: 10,002
    edited May 2014 Vote Up0Vote Down
    twm47099 wrote: »
    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.
  • twm47099twm47099 Posts: 670
    edited August 2015 Vote Up0Vote Down
    Latest results.

    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
  • twm47099twm47099 Posts: 670
    edited June 2014 Vote Up0Vote Down
    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.
  • twm47099twm47099 Posts: 670
    edited August 2015 Vote Up0Vote Down
    Today's result.

    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);
           }
     }
    
    
  • vanmunchvanmunch Posts: 567
    edited June 2014 Vote Up0Vote Down
    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.

    Thanks for sharing your experiences using it! :)

    Dave
    My wife is very, very understanding

    Prospero: Robot Farmer
    http://www.youtube.com/watch?v=ACtihXjq2B0
    www.DorhoutRD.com
  • twm47099twm47099 Posts: 670
    edited June 2014 Vote Up0Vote Down
    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

    [TABLE]
    [TR]
    [TD="class: xl22"]Mem Model[/TD]
    [TD="class: xl22"]Optmization[/TD]
    [TD="class: xl22, width: 64"]Baud[/TD]
    [TD="class: xl22, width: 64"]B/F max[/TD]
    [TD="class: xl22, width: 63"]B/F min[/TD]
    [TD="class: xl22, width: 71"]B/F typical[/TD]
    [TD="class: xl22, width: 64"]Num Err[/TD]
    [/TR]
    [TR]
    [TD="class: xl22"][/TD]
    [TD="class: xl22"][/TD]
    [TD="class: xl22"][/TD]
    [TD="class: xl22"][/TD]
    [TD="class: xl22"][/TD]
    [TD="class: xl22"][/TD]
    [TD="class: xl22"][/TD]
    [/TR]
    [TR]
    [TD="class: xl22"]CMM[/TD]
    [TD="class: xl22"]Size[/TD]
    [TD="class: xl22"]14400[/TD]
    [TD="class: xl22"]3[/TD]
    [TD="class: xl22"]1[/TD]
    [TD="class: xl22"]2[/TD]
    [TD="class: xl22"]0[/TD]
    [/TR]
    [TR]
    [TD="class: xl22"]CMM[/TD]
    [TD="class: xl22"]Size[/TD]
    [TD="class: xl22"]16800[/TD]
    [TD="class: xl22"]4[/TD]
    [TD="class: xl22"]2[/TD]
    [TD="class: xl22"]2[/TD]
    [TD="class: xl22"]1[/TD]
    [/TR]
    [TR]
    [TD="class: xl22"]CMM[/TD]
    [TD="class: xl22"]Speed[/TD]
    [TD="class: xl22"]16800[/TD]
    [TD="class: xl22"]3[/TD]
    [TD="class: xl22"]2[/TD]
    [TD="class: xl22"]2[/TD]
    [TD="class: xl22"]1[/TD]
    [/TR]
    [TR]
    [TD="class: xl22"]LMM[/TD]
    [TD="class: xl22"]Size[/TD]
    [TD="class: xl22"]16800[/TD]
    [TD="class: xl22"]3[/TD]
    [TD="class: xl22"]2[/TD]
    [TD="class: xl22"]2[/TD]
    [TD="class: xl22"]0[/TD]
    [/TR]
    [TR]
    [TD="class: xl22"]LMM[/TD]
    [TD="class: xl22"]Speed[/TD]
    [TD="class: xl22"]19200[/TD]
    [TD="class: xl22"]3[/TD]
    [TD="class: xl22"]2[/TD]
    [TD="class: xl22"]2[/TD]
    [TD="class: xl22"]0[/TD]
    [/TR]
    [TR]
    [TD="class: xl22"]LMM[/TD]
    [TD="class: xl22"]Speed[/TD]
    [TD="class: xl22"]38400[/TD]
    [TD="class: xl22"]6[/TD]
    [TD="class: xl22"]1[/TD]
    [TD="class: xl22"]4[/TD]
    [TD="class: xl22"]0[/TD]
    [/TR]
    [/TABLE]
  • twm47099twm47099 Posts: 670
    edited August 2015 Vote Up0Vote Down
    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];
      
    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
    }
    
  • twm47099twm47099 Posts: 670
    edited August 2015 Vote Up0Vote Down
    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;
       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
        }
    }
    
    
  • twm47099twm47099 Posts: 670
    edited August 2015 Vote Up0Vote Down
    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 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); 
    }
    
    
  • prof_brainoprof_braino Posts: 4,312
    edited June 2014 Vote Up0Vote Down
    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
    /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.
  • vanmunchvanmunch Posts: 567
    edited June 2014 Vote Up0Vote Down
    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
    /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 &#8216;bin&#8217;: File exists
    cp: cannot stat &#8216;src/host/pixymon/PixyMon&#8217;: 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 :)
    My wife is very, very understanding

    Prospero: Robot Farmer
    http://www.youtube.com/watch?v=ACtihXjq2B0
    www.DorhoutRD.com
  • twm47099twm47099 Posts: 670
    edited July 2014 Vote Up0Vote Down
    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

    http://forums.parallax.com/showthread.php/155208-Open-Propeller-Project-5-BlocklyProp?p=1276733#post1276733
  • twm47099twm47099 Posts: 670
    edited August 2015 Vote Up0Vote Down
    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 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
    
    
  • twm47099twm47099 Posts: 670
    edited August 2015 Vote Up0Vote Down
    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 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
    
    
  • twm47099twm47099 Posts: 670
    edited August 2014 Vote Up0Vote Down
    I wrote a program that combines bluetooth control and pixy control of the ActivityBot and posted it in the Learn forum.
    Tom

    http://forums.parallax.com/showthread.php/156970-Bluetooth-App-to-control-ActivityBot
  • imbinaryimbinary Posts: 1
    edited August 2014 Vote Up0Vote Down
    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

    [TABLE="class: outer_border"]
    [TR]
    [TD]pixyCMU5[/TD]
    [TD]Propeller activity[/TD]
    [/TR]
    [TR]
    [TD]PIN 1[/TD]
    [TD]PIN 14[/TD]
    [/TR]
    [TR]
    [TD]PIN 2[/TD]
    [TD]5v[/TD]
    [/TR]
    [TR]
    [TD]PIN 3[/TD]
    [TD]PIN 15[/TD]
    [/TR]
    [TR]
    [TD]PIN 4[/TD]
    [TD]PIN 13[/TD]
    [/TR]
    [TR]
    [TD]PIN 6[/TD]
    [TD]GND[/TD]
    [/TR]
    [/TABLE]


    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
  • Duane DegnDuane Degn Posts: 10,002
    edited August 2014 Vote Up0Vote Down
    imbinary wrote: »
    IOne gotcha I encountered was not having enough light when testing, and not detecting anything so assumed the code was broken :frown:.

    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.
  • twm47099twm47099 Posts: 670
    edited August 2014 Vote Up0Vote Down
    imbinary wrote: »
    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.

    Thanks again,
    Tom
Sign In or Register to comment.