One Robot Per Feeder & One Part Per Feeder

Program Example 1.1

Example Type:
Using the PF_Robot Callback for motion

Configuration

  • Number of Robots: 1
  • Number of Feeders: 1
  • Number of Parts Types on the Feeder: 1
  • Number of Placement Positions: 1
    Camera Orientation: Fixed Downward Camera over Feeder#1

Description
Parts are removed from the feeder and placed into a box. When all the parts have been removed, the Control callback will request more parts. When the operator or hopper replenishes the feeder with more parts, the cycle continues. If the PF_Stop command is executed, the current cycle ends and then the application will terminate. (PF_Stop command is not used in the following sample code.)

Sample Code
Main.prg

Function main
    If Motor = Off Then
        Motor On
    EndIf
    Power Low
    Jump Park
    PF_Start 1
Fend

PartFeeding.prg

Function PF_Robot(PartID As Integer) As Integer
    Do While PF_QueLen(PartID) > 0
        P0 = PF_QueGet(PartID)
        Jump P0
        On Gripper; Wait 0.2
        Jump Place
        Off Gripper; Wait 0.2
        PF_QueRemove PartID
        If PF_IsStopRequested(PartID) = True Then
            Exit Do
        EndIf
    Loop
    PF_Robot = PF_CALLBACK_SUCCESS
 Fend

Program Example 1.2

Example Type:
Multiple robot system - 1 robot per feeder & 1 part per feeder

Configuration

  • Number of Robots: 2
    Robot 1 is connected to the Control Unit. Robot 2 is connected to the Drive Unit.
  • Number of Feeders: 2
  • Number of Parts Types on each Feeder: 1
  • Number of Placement Positions: 1 per robot
  • Camera Orientation: Each Feeder has its own Fixed Downward Camera

Description
Both robots independently pick and place parts. The robots do not share feeders or placement position. The robot work envelopes do not overlap. Both robots have points that are labeled "Park", "Pick" and "Place" in their respective point files.

Sample Code
Main.prg

Function main
    Robot 1
    If Motor = Off Then
         Motor On
    EndIf
    Power Low
    Jump Park

    Robot 2
    If Motor = Off Then Motor On
    Power Low
    Jump Park

    PF_Start 1
    PF_Start 2
Fend

PartFeeding.prg

Function PF_Robot(PartID As Integer) As Integer
    Integer gripperOutput

    Select PartID
        Case 1
            Robot 1
            gripperOutput = 1
        Case 2
            Robot 2
            gripperOutput = 2
    Send

    Do While PF_QueLen(PartID) > 0
        Pick = PF_QueGet(PartID)
        Jump pick
        On gripperOutput; Wait 0.2
        Jump Place
        Off gripperOutput; Wait 0.2
        PF_QueRemove PartID
        If PF_IsStopRequested(PartID) = True Then
            Exit Do
        EndIf
    Loop
    PF_Robot = PF_CALLBACK_SUCCESS

Fend

Program Example 1.3

Example Type:
Parallel processing vision & vibration with robot motion

Configuration

  • Number of Robots: 1
  • Number of Feeders: 1
  • Number of Parts Types: 1
  • Number of Placement Positions: 1
  • Camera Orientation: Fixed Downward Camera

Description
The robot picks up a Part#1 from the parts feeder and places it into a fixture. This continues until all the "Front" parts are removed from the Feeder. When the last available part is being placed (90% of the way through the motion), the feeder will vibrate, the hopper will replenish the feeder if necessary, etc.
This example demonstrates how the feeder action can occur in parallel with the robot motion to optimize throughput.

Sample Code
Main.prg

Function main
    MemOff PartsToPick
    Off Gripper

    Robot 1
    If Motor = Off Then
        Motor On
    EndIf
    Power Low
    Jump Park

    PF_Start(1)

    Xqt RobotPickPlace
Fend

Function RobotPickPlace
    Do
        Wait MemSw(PartsToPick) = On
        If PF_QueLen(1) > 0 Then
             Do
                Pick = PF_QueGet(1)
                PF_QueRemove 1
                Jump pick
                On Gripper; Wait 0.2
                If PF_QueLen(1) = 0 Then
                    Jump Place ! D90; MemOff PartsToPick !
                    Off Gripper; Wait 0.2
                    Exit Do
                Else
                    Jump Place
                    Off Gripper; Wait 0.2
                EndIf
            Loop
        Else
            MemOff PartsToPick
        EndIf
    Loop
Fend

PartFeeding.prg

Function PF_Robot(PartID As Integer) As Integer
    MemOn PartsToPick
    Wait MemSw(PartsToPick) = Off

    PF_Robot = PF_CALLBACK_SUCCESS
Fend

Program Example 1.4

Example Type:
1 Robot, 2 Feeders and 1 Part Per Feeder

Configuration

  • Number of Robots: 1
  • Number of Feeders: 2
  • Number of Parts Types on each Feeder: 1
  • Number of Placement Positions: 1
  • Camera Orientation: Each Feeder has its own Fixed Downward Camera

Description
The robot picks up each part#1 from Feeder#1 and places it into a box. This continues until all the "Front" parts are removed from the Feeder #1. Then the robot picks up each "Front" part from Feeder#2 and places them into the box. The Cameras and Feeders work in parallel with one another.

Sample Code
Main.prg

Function main
    MemOff PartsToPick1; MemOff PartsToPick2
    Off Gripper

    Robot 1
    If Motor = Off Then
        Motor On
    EndIf
    Power Low
    Jump Park

    PF_Start(1)
    PF_Start(2)

    Xqt rbt1
Fend

Function rbt1
    Do
        Call RobotPickPlace(1)
        Call RobotPickPlace(2)
    Loop
Fend

Function RobotPickPlace(PartID As Integer)
    Integer partsToPickMembit

    Select PartID
        Case 1
            partsToPickMembit = IONumber("PartsToPick1")
        Case 2
            partsToPickMembit = IONumber("PartsToPick2")
    Send

    Wait MemSw(partsToPickMembit) = On
    If PF_QueLen(PartID) > 0 Then

         Do
            Pick = PF_QueGet(PartID)
            PF_QueRemove PartID
            Jump pick
            On Gripper; Wait 0.2
            If PF_QueLen(PartID) = 0 Then
                Jump Place ! D90; MemOff partsToPickMembit !
                Off Gripper; Wait 0.2
                Exit Do
            Else
                Jump Place
                Off Gripper; Wait 0.2
            EndIf

            If PF_IsStopRequested(PartID) = True Then
                MemOff partsToPickMembit
                Exit Do
            EndIf
        Loop
    Else
        MemOff partsToPickMembit
    EndIf
Fend

PartFeeding.prg

Function PF_Robot(PartID As Integer) As Integer

    Select PartID
        Case 1
            MemOn PartsToPick1
            Wait MemSw(PartsToPick1) = Off
        Case 2
            MemOn PartsToPick2
            Wait MemSw(PartsToPick2) = Off
    Send

    PF_Robot = PF_CALLBACK_SUCCESS
Fend

Program Example 1.5

Example Type:
1 Robot, 2 Feeders and 1 Part Per Feeder - Mobile Mounted Camera

Configuration

  • Number of Robots: 1
  • Number of Feeders: 2
  • Number of Parts Types on each Feeder: 1
  • Number of Placement Positions: 1
  • Camera Orientation: Each Feeder will use the Mobile Mounted Camera on the robot.
    (there are no Fixed Downward cameras for this example)

Description
Then the robot moves the Mobile Mounted camera over Feeder#1 and takes a picture. The robot picks up each part from Feeder#1 and places it into a box. This continues until all the "Front" parts are removed from the Feeder. Then the robot moves the Mobile Mounted camera over Feeder#2 and takes a picture. The robot picks up each correctly oriented part from Feeder#2 and places them into the box.

KEY POINTS


If you use a mobile camera equipped with multiple feeders with backlights, a separate vision sequence is used for each part associated with each feeder.

Sample Code
Main.prg

Function main
    MemOff PartsToPick1; MemOff PartsToPick2
    MemOff mobileCamBefore1; MemOff mobileCamAfter1
    MemOff mobileCamBefore2; MemOff mobileCamAfter2
    MemOff mobileCamInPos1; MemOff mobileCamInPos2

    Robot 1
    If Motor = Off Then
        Motor On
    EndIf
    Power Low
    Jump Park

    PF_Start(1)
    PF_Start(2)
    Xqt rbt1
Fend

Function rbt1
    Do
        Wait MemSw(mobileCamBefore1) = On
        Jump MobileCamShotFeeder1; MemOn mobileCamInPos1
        Wait MemSw(mobileCamAfter1) = On
        MemOff mobileCamInPos1

        Call RobotPickPlace(1)

        Wait MemSw(mobileCamBefore2) = On
        Jump MobileCamShotFeeder2; MemOn mobileCamInPos2
        Wait MemSw(mobileCamAfter2) = On
        MemOff mobileCamInPos2

        Call RobotPickPlace(2)
    Loop
Fend

Function RobotPickPlace(PartID As Integer)
    Integer partsToPickMembit, partCnt, gripperOutput, toolNum

    Select PartID
        Case 1
            partsToPickMembit = IONumber("PartsToPick1")
        Case 2
            partsToPickMembit = IONumber("PartsToPick2")
    Send

    Wait MemSw(partsToPickMembit) = On
    Do While PF_QueLen(PartID) > 0
        P0 = PF_QueGet(PartID)
        Jump P0
        On Gripper; Wait 0.2
        Jump Place
        Off Gripper; Wait 0.2
        PF_QueRemove PartID
        If PF_IsStopRequested(PartID) = True Then
            Exit Do
        EndIf
    Loop
    MemOff partsToPickMembit
Fend

PartFeeding.prg

Function PF_Robot(PartID As Integer) As Integer

    Select PartID
        Case 1
            MemOn PartsToPick1
            Wait MemSw(PartsToPick1) = Off
        Case 2
            MemOn PartsToPick2
            Wait MemSw(PartsToPick2) = Off
    Send

    PF_Robot = PF_CALLBACK_SUCCESS
Fend

Function PF_MobileCam(PartID Integer, Action As Integer) As Integer
    Integer mobileCamBeforeMembit, mobileCamAfterMembit, mobileCamInPosMembit

    Select PartID
        Case 1
            mobileCamBeforeMembit = IONumber("mobileCamBefore1")
            mobileCamAfterMembit = IONumber("mobileCamAfter1")
            mobileCamInPosMembit = IONumber("mobileCamInPos1")
        Case 2
            mobileCamBeforeMembit = IONumber("mobileCamBefore2")
            mobileCamAfterMembit = IONumber("mobileCamAfter2")
            mobileCamInPosMembit = IONumber("mobileCamInPos2")
    Send

    Select Action
        Case PF_MOBILECAM_BEFORE
            ' Request for robot move to camera position
            MemOff mobileCamAfterMembit
            MemOn mobileCamBeforeMembit
            Wait MemSw(mobileCamInPosMembit) = On
        Case PF_MOBILECAM_AFTER
            ' Request for robot move after part vision acquisition
            MemOff mobileCamBeforeMembit
            MemOn mobileCamAfterMembit
            Wait MemSw(mobileCamInPosMembit) = Off
    Send

    PF_MobileCam = PF_CALLBACK_SUCCESS
Fend

Program Example 1.6

Example Type:
Specifying the number of parts to pick

Configuration

  • Number of Robots: 1
  • Number of Feeders: 2
  • Number of Parts Types on each Feeder: 1
  • Number of Placement Positions: 1
  • Camera Orientation: Each Feeder has its own Fixed Downward Camera

Description
The robot picks up four Part#1 from Feeder#1 and place them individually. The robot will then pick up five Part#2 from Feeder#2 and place them. The Cameras and Feeders work in parallel with one another.
This example illustrates how the robot can pick up a specific number of parts from each feeder. The sample code also supports picking all available parts by setting the numToPick parameter to "ALL_AVAILABLE".
If "Front" parts remain on either feeder after picking the desired quantity, the feeder will not vibrate unnecessarily.

Sample Code
Main.prg

#define ALL_AVAILABLE -1

Function main
    MemOff PartsToPick1; MemOff PartsToPick2
    Off Gripper

    Robot 1
    If Motor = Off Then
        Motor On
    EndIf
    Power Low
    Jump Park

    PF_Start(1)
    PF_Start(2)

    Xqt rbt1
Fend

Function rbt1
    Do
        Call RobotPickPlace(1, 4)	'part 1...pick & place 4 times
        Call RobotPickPlace(2, 5)	'part 2...pick & place 5 times
    Loop
Fend

Function RobotPickPlace(PartID As Integer, numToPick As Integer)
    Integer partsToPickMembit, partCnt

    Select PartID
        Case 1
            partsToPickMembit = IONumber("PartsToPick1")
        Case 2
            partsToPickMembit = IONumber("PartsToPick2")
    Send

    partCnt = 0
    Do
        Wait MemSw(partsToPickMembit) = On
        If PF_QueLen(PartID) > 0 Then
            Pick = PF_QueGet(PartID)
            PF_QueRemove PartID
            Jump pick
            On Gripper; Wait 0.2
            partCnt = partCnt + 1
            If PF_QueLen(PartID) = 0 Then
                Jump Place ! D90; MemOff partsToPickMembit !
                Off Gripper; Wait 0.2
                If (partCnt = numToPick) Or (numToPick = ALL_AVAILABLE) Then
                    Exit Do
                EndIf
            Else
                Jump Place
                Off Gripper; Wait 0.2
                If (partCnt = numToPick) Then
                     Exit Do
                EndIf
             EndIf
         Else
             MemOff partsToPickMembit
         EndIf
         If PF_IsStopRequested(PartID) = True Then
            MemOff partsToPickMembit
            Exit Do
         EndIf
    Loop
Fend

PartFeeding.prg

Function PF_Robot(PartID As Integer) As Integer

    Select PartID
        Case 1
            MemOn PartsToPick1
            Wait MemSw(PartsToPick1) = Off
        Case 2
            MemOn PartsToPick2
            Wait MemSw(PartsToPick2) = Off
     Send

    PF_Robot = PF_CALLBACK_SUCCESS
Fend

Program Example 1.7

Example Type:
Ensuring that the Robot matches the Robot # that was used for the Part

Configuration

  • Number of Feeders: More than 1
  • Number of Parts Types on each Feeder: 1
  • Camera Orientation: Each Feeder has its own Fixed Downward Camera

Description
When using multiple feeders, it is common that the robot makes motion in a multitask rather than inside the PF_Robot callback. In other words, the PF_Robot callback simply loads part locations (points) into the Part Feeding Queue.
A robot motion task uses the points in the queue. When the code is structured in this fashion, it is recommended that the robot motion task verifies that current robot # matches the robot # that was selected for the part.
This additional check will ensure that the robot does not use the wrong points and cannot crash the robot.

Sample Code
Main.prg

Function RobotPickPlace(PartID As Integer, numToPick As Integer)

    If PF_Info(PartID, PF_INFO_ID_ROBOT_NO) <> Robot Then
        Print "Robot does not match the robot # for the current part"
        Quit All
    EndIf

    'Robot Motion Code
Fend

Program Example 1.8

Example Type:
Acquiring a new image and loading the queue after every pick

Configuration

  • Number of Robots: 1
  • Number of Feeders: 1
  • Number of Parts Types: 1
  • Number of Placement Positions: 1
  • Camera Orientation: Fixed Downward Camera

Description
The robot picks up a Part#1 from the parts feeder and places it into a fixture. After each pick and place operation, a new image will be acquired and the queue will be reloaded.
For this example, we are concerned that surrounding parts may be disturbed during pick up. The PF_Robot callback return value "PF_CALLBACKRESTART" will force vision to re-run for all parts and all part queues will be reloaded.
This method is not efficient but "PF_CALLBACKRESTART" can be useful in certain circumstances where acquiring an image every cycle can improve performance accuracy. The vision and feeder vibration occurs in parallel with robot motion.

Sample Code
Main.prg

Function main
    MemOff PartsToPick
    Off Gripper

    Robot 1
    If Motor = Off Then
        Motor On
    EndIf
    Power Low
    Jump Park

    PF_Start(1)

    Xqt RobotPickPlace
Fend

Function RobotPickPlace
    Do
        Wait MemSw(PartsToPick) = On
        If PF_QueLen(1) > 0 Then
            Pick = PF_QueGet(1)
            PF_QueRemove 1
            Jump pick
            On Gripper; Wait 0.2
            Jump Place ! D90; MemOff PartsToPick !
            Off Gripper; Wait 0.2
        Else
            MemOff PartsToPick
        EndIf
    Loop
Fend

PartFeeding.prg

Function PF_Robot(PartID As Integer) As Integer
    MemOn PartsToPick
    Wait MemSw(PartsToPick) = Off

    PF_Robot = PF_CALLBACK_RESTART
Fend

Program Example 1.9

Example Type:
Sorting a Part by Front and Back orientation

Configuration

  • Number of Robots: 1

  • Number of Feeders: 1

  • Number of Parts Types on the Feeder: 1

  • Number of Placement Positions: 2 (one for the Front side and one for the Back side)

  • Camera Orientation: Fixed Downward Camera over Feeder#1

  • Part 1 General Page:

  • Part 1 Vision Page:

Description
For this application, the robot will sort the parts based upon their Front and Back orientation. Front side parts will be placed at a point labeled "PlaceFront" and Back side parts will be placed in another point labeled "PlaceBack".
The pick order does not matter for this application. The robot will pick / place as many Front parts as it can and then pick / place as many Back parts as it can.
When "Needs Flip" is uncheck but vision objects have been selected in "Vision object for front of part" and "Vision object for back of part", the system will load both the Front & Back parts into the coordinate queue and set the Part Orientation value accordingly.
Remember that the "Needs Flip" setting tells the system that you want parts in a certain orientation. By Unchecking this setting, you are telling the system that you want both orientations.

In this case, the Front parts will automatically have their orientation data (in the part coordinate queue) set to constant "PF_PARTORIENT_FRONT".
The Back parts will automatically have their orientations set to constant "PF_PARTORIENT_BACK".

Sample Code
Main.prg

Function main
    If Motor = Off Then
        Motor On
    EndIf
    Power Low
    Jump Park
    PF_Start 1
Fend

PartFeeding.prg

Function PF_Robot(PartID As Integer) As Integer
    Do While PF_QueLen(PartID) > 0
        P0 = PF_QueGet(PartID)
        Jump P0
        On Gripper; Wait 0.2
        If PF_QuePartOrient(PartID) = PF_PARTORIENT_FRONT Then
            Jump PlaceFront
        ElseIf PF_QuePartOrient(PartID) = PF_PARTORIENT_BACK Then
            Jump PlaceBack
        EndIf
        Off Gripper; Wait 0.2
        PF_QueRemove PartID
        If PF_IsStopRequested(PartID) = True Then
            Exit Do
        EndIf
    Loop
    PF_Robot = PF_CALLBACK_SUCCESS

Fend

Program Example 1.10

Example Type:
Using the PF_Vision Callback

Configuration

  • Number of Robots: 1
  • Number of Feeders: 1
  • Number of Parts Types on the Feeder: 1
  • Number of Placement Positions: 1
  • Camera Orientation: Fixed Downward Camera over Feeder#1

Description
This example illustrates how to use the PF_Vision callback to acquire an image and load the parts coordinate queue with the vision results. To use this function, select "User processes vision for part via PF_Vision callback" in Epson RC+ 8.0 Menu - [Tools] - [Part Feeding] - [Vision].

Sample Code
Main.prg

Function main
    If Motor = Off Then
        Motor On
    EndIf
    Power Low
    Jump Park
    PF_Start 1
Fend

PartFeeding.prg

Function PF_Robot(PartID As Integer) As Integer
    Do While PF_QueLen(PartID) > 0
        P0 = PF_QueGet(PartID)
        Jump P0
        On Gripper; Wait 0.2
        Jump Place
        Off Gripper; Wait 0.2
        PF_QueRemove PartID
        If PF_IsStopRequested(PartID) = True Then
            Exit Do
        EndIf
    Loop
    PF_Robot = PF_CALLBACK_SUCCESS

Fend

Function PF_Vision(PartID As Integer, ByRef numBack As Integer) As Integer
    Boolean found
    Integer i, numFront
    Real RB_X, RB_Y, RB_U, RB_Z

    ' Pick Z coordinate
    RB_Z = -132.0

    ' Initialize coordinates queue
    PF_QueRemove PartID, All

    PF_Backlight 1, On

    ' Detect the parts
    VRun UsrVisionSeq
    PF_Backlight 1, Off

    VGet UsrVisionSeq.Geom01.NumberFound, numFront	'Front Parts
    VGet UsrVisionSeq.Geom02.NumberFound, numBack	'Back Parts
    If numFront <> 0 Then
        For i = 1 To numFront
            VGet UsrVisionSeq.Geom01.RobotXYU(i), found, RB_X, RB_Y, RB_U
            If found Then
                PF_QueAdd PartID, XY(RB_X, RB_Y, RB_Z, RB_U)
            EndIf
        Next
    EndIf

    PF_Vision = PF_CALLBACK_SUCCESS

Fend

Program Example 1.11

Example Type:
Picking a Multi-sided Part

Configuration

  • Number of Robots: 1
  • Number of Feeders: 1
  • Number of Parts Types on the Feeder: 1
  • Number of Unique Sides on the Part: 3
  • Number of Placement Positions: 3 (one placement position for each side of the part)
  • Camera Orientation: Fixed Downward Camera over Feeder#1

Description
For this example, there is 1 physical part type on the feeder. The part has 3 unique sides (Right side, Left side and Top side). The robot can pick up the part in any one of the 3 orientations.
From the perspective of the vision system, each side is a different part (even though it is actually 1 physical part). Part Feeding supports 4 unique parts running on the same feeder at the same time. Consequently, we are going to create a separate Part for each side. We will make 3 Part Vision sequences and name them "Left", "Right" and "Top".
Each vision sequence will use a Geometric object to locate the part in its specific orientation. In the Part Feeding dialog, we will create 3 Parts - Part 1, 2 and 3.
Part 1 will locate the part in the "Left" side orientation.
Part 2 will locate the part in the "Right" side orientation.
Part 3 will locate the part in the "Top" side orientation.
"Needs Flip" will be unchecked for all 3 Parts. All 3 parts will use the same Part Blob Vision Sequence called "PartBlob".



Teach the Pick Z for each Part (the pick height may be different for each side of the part). Left side parts will be placed at a point labeled "PlaceLeft". Right side parts will be placed at a point labeled "PlaceRight". Top side parts will be placed at a point labeled "PlaceTop". The robot will pick / place all the parts in the Left orientation, then pick / place all the parts in the Right orientation and lastly it will pick / place all the parts in the Top orientation.

Sample Code
Main.prg

Function main
    If Motor = Off Then
        Motor On
    EndIf
    Power Low
    Jump Park
    PF_Start 1, 1, 2
Fend

PartFeeding.prg

Function PF_Robot(PartID As Integer) As Integer

    Do While PF_QueLen(PartID) > 0
        P10 = PF_QueGet(PartID)
        Jump P10
        On Vacuum; Wait 0.2
        Select PartID
            Case 1
                Jump PlaceLeft
            Case 2
                Jump PlaceRight
            Case 3
                Jump PlaceTop
        Send
        Off Vacuum; Wait 0.2
        PF_QueRemove PartID
    Loop

    PartID = PartID + 1
    If PartID > 3 Then PartID = 1
    PF_ActivePart PartID
    PF_Robot = PF_CALLBACK_SUCCESS

Fend

KEY POINTS


This example illustrates a simple method of handling a multi-side part by using the Multi-Part functionality. Another method is for the "User to Process Vision" via the PF_Vision callback. When using PF_QueAdd, User Data can be included with the part coordinates. The user data could be a numerical value that represents the part orientation (i.e., 1 = Left, 2=Right, 3=Top). The PF_QueUserData function would be used to get the orientation value so that the part can be placed in the correct location. The code would also need to account for height differences in the part sides.

Program Example 1.12

Example Type:
Using the PF_Vision Callback and the Part Sequence uses Multi-Search

Configuration

  • Number of Robots: 1
  • Number of Feeders: 1
  • Number of Parts Types on each Feeder: 1
  • Number of Placement Positions: 1
  • Camera Orientation: Fixed Downward Camera over Feeder#1

Description
The PF_Vision callback is used when the Part Sequence vision processing is difficult (i.e., the application requires multiple vision sequences to detect the part or several different lighting controls are required etc…).

This example illustrates how to use the PF_Vision callback to acquire an image and load the parts coordinate queue with the vision results. To use this function, select "User processes vision for part via PF_Vision callback" in Epson RC+ 8.0 Menu - [Tools] - [Part Feeding] - [Vision].

This example uses multi-search for the Part Sequence. Multi-search is a feature where an object will search for each result of the CenterPointObject property or a Frame object. In multi-search, the found results may not be found sequentially. PF_Vision shows how to iterate through all the results to find the found results.

  • Example of multi-search with CenterPointObject:
  1. Create an object to find multiple parts, such as a Blob
  2. Create another object, such as a Polar, that will use the Blob as its CenterPointObject.
  3. Set the CenterPntObjResult property to All.
  4. Run the sequence. You will see an instance of the Polar object for each Blob result that was found.
  • Example of multi-search with Frame:
  1. Create an object to find multiple parts, such as a Blob
  2. Create a Frame object and set the OriginPoint property to the Blob.
  3. Set the OriginPntObjResult property to All.
  4. Create another object, such as a Polar, that will use the Frame.
  5. Set the FrameResult property to All.
  6. Run the sequence. You will see an instance of the Frame object for each Blob result that was found, and an instance of the Polar object for each Frame result.

Sample Code
Main.prg

Function main
    If Motor = Off Then
        Motor On
    EndIf
    Power Low
    Jump Park
    PF_Start 1
Fend

PartFeeding.prg

Function PF_Robot(PartID As Integer) As Integer

    Do While PF_QueLen(PartID) > 0
        P10 = PF_QueGet(PartID)

        Select PF_QuePartOrient(PartID)
            Case PF_PARTORIENT_FRONT ' Front
                Tool 1	' Tool to pick Front
                ' Pick
                Jump P10 ! D90; On Vacuum !
                Wait 0.1
                ' Place
                Jump FrontPlace
                Off Vacuum
                Wait 0.1
            Case PF_PARTORIENT_BACK ' Back
                Tool 2 ' Tool to pick Back
                ' Pick
                Jump P10 ! D90; On Vacuum !
                Wait 0.1
                ' Place
                Jump BackPlace
                Off Vacuum
                Wait 0.1
        Send

        PF_QueRemove PartID

        If PF_IsStopRequested(PartID) = True Then
            Exit Do
        EndIf

    Loop

    PF_Robot = PF_CALLBACK_SUCCESS

Fend


Function PF_Vision(PartID As Integer, ByRef numBack As Integer) As Integer

    Integer i, numFront, numBack, numResults, count
    Boolean found
    Real x, y, z, u

    z = -170	' Set the pick Z coordinate to the desired height for your application

    PF_QueRemove 1, All

    PF_Backlight 1, On
    VRun FindPart

    VGet FindPart.Front.NumberFound, numFront
    VGet FindPart.Front.NumberOfResults, numResults
    count = 0
    For i = 1 To numResults
        VGet FindPart.Front.RobotXYU(i), found, x, y, u
        If found Then
            count = count + 1
            P999 = XY(x, y, z, u) /R
            PF_QueAdd 1, P999, PF_PARTORIENT_FRONT
        EndIf
        If count = numFront Then
            Exit For
        EndIf
    Next

    VGet FindPart.Back.NumberFound, numBack
    VGet FindPart.Back.NumberOfResults, numResults
    count = 0
    For i = 1 To numResults
        VGet FindPart.Back.RobotXYU(i), found, x, y, u
        If found Then
            count = count + 1
            P999 = XY(x, y, z, u) /R
            PF_QueAdd 1, P999, PF_PARTORIENT_BACK
        EndIf
        If count = numBack Then
            Exit For
        EndIf
    Next

    PF_Backlight 1, Off
    PF_Vision = PF_CALLBACK_SUCCESS

Fend