Tutorials
The purpose of this section is to demonstrate how to implement both a multi-part application as well as a multi-part / multi-robot application. In many cases we will simply explain the steps to follow but will not explain the details behind what was done. It is assumed that you understand how to create a new part, perform a part calibration and write a program for a one robot / one-part application.
Refer to the following section for further details.
Let’s Use the Part Feeding Option
Tutorial 1: 1 Robot, 1 Feeder, 2 Part Types
For this tutorial, there are two parts running on the same feeder at the same time. The parts are physically different. Part#1 and Part#2 are being used. There is a Fixed Downward camera over the feeder. The robot will pick and place two of Part#1 and then pick and place one of Part#2. This operation will be performed continuously in a loop.
Each part will be picked up with a different gripper (i.e., output bit). The quantity of parts and the pick order are important for this assembly application. The process of alternating between Part#1 and Part#2 will be accomplished using "PF_ActivePart". At first, we will write the code so that the robot motion is performed inside of the PF_Robot callback function. Then we will improve the robot throughput by performing the motion in a separate multitask and by parallel processing the feeder vibration.
Create a new Epson RC+ project.
Calibrate the Fixed Downward camera.
From Vision Guide, create the Part Blob Sequence.
The "Part Blob Sequence" is used for feedback during the Part Calibration and at runtime to make judgements about how to best feed the parts. The Part Blob Sequence detects individual parts or clumps of parts at runtime. The Part Blob Sequence generally contains a single Blob vision object. The Part Blob Sequence will need to have the camera calibration assigned to the Calibration property.
The Blob object’s NumberToFind property should be set to "All". The ThresholdAuto property of the Blob should be set to False (default value).
Place parts on the platform, open the Histogram window and adjust the Threshold High and Low until only the parts are detected. Set the Blob’s MinArea to roughly 0.9 times that of the part’s area. If the part has multiple sides, then set the MinArea so that the part can be found in any orientation. You can have separate Part Blob Sequences for each of the two parts (running on the feeder) but in general you can use the same Part Blob Sequence for all the parts.
Make sure that the Part Blob Sequence can detect each Part that will be running on the feeder. The Blob object’s Search Window should fill as much of the platform area as possible. That said, it is critical that the Blob object only finds the Parts and not the feeder tray itself. If the Part Blob sequence finds any portion of the tray then the system will not function properly.From Vision Guide, create the Part Sequence for each of the two Parts that will be running on the feeder.
Make sure that the Calibration property for each sequence is set. Typically, a Geometric object is used to locate the Front (and a second Geometric object is typically used to find the Back of the part if Flip is required). The vision object’s NumberToFind property is normally set to "All".Go to the [Tools] - [Part Feeding] dialog and add a new part. The "Part Wizard" will walk you through the process of adding a part.
For more details about the Part Wizard, please refer to the following chapter.
Let’s Use the Part Feeding OptionGo to the [Calibration] page for the new Part and click on the [Calibrate] button to start the Calibration Wizard.
Please refer to the following section for details on how to use the Calibration Wizard.
Calibration & TestGo to the [Pick] page for Part#1 and click the [Teach] button.
Jog the robot to the part pick height and teach the "Pick Z".Click the [Add] button in the [Part Feeding] dialog to add Part#2.
Configure the part using the "Part Wizard".Go to the [Calibration] page and click the [Calibrate] button to start the Calibration Wizard.
Go to the [Pick] page for Part#1 and click the [Teach] button.
Jog the robot to the part pick height and teach the "Pick Z".Close the Part Feeding dialog.
The Part Feeding template code (i.e., the Part Feeding callback functions) is automatically created.Teach robot points for "park" and "place" and label them respectively.
Modify the template code as follows.
Main.prg
Function Main
Robot 1
Motor On
Power High
Speed 50
Accel 50, 50
Jump Park
PF_Start 1, 2
Fend
PartFeeding.prg
Global Integer numPicked ' number of parts that have been picked
Function PF_Robot(PartID As Integer) As Integer
Integer numRequired, gripperOutput
Select PartID
Case 1
numRequired = 2 ' number of parts required
gripperOutput = 1
Case 2
numRequired = 1
gripperOutput = 2
Send
Do
If PF_QueLen(PartID) > 0 Then
P0 = PF_QueGet(PartID)
PF_QueRemove (PartID)
Jump P0
On gripperOutput
Wait 0.1
Jump Place
Off gripperOutput
Wait 0.1
numPicked = numPicked + 1
Else
' Not enough parts were picked
PF_ActivePart PartID ' No change in Active Part
PF_Robot = PF_CALLBACK_SUCCESS
Exit Function
EndIf
Loop Until numPicked = numRequired
numPicked = 0
' select the next Active Part
If PartID = 1 Then
PF_ActivePart 2
Else
PF_ActivePart 1
EndIf
PF_Robot = PF_CALLBACK_SUCCESS
Fend
For the sample code shown above, the feeder will vibrate (if necessary) only after the robot has completed its motion to "place" and the PF_Robot function has finished. The code can be restructured such that the feeder vibration will occur in parallel with the robot motion.
The PF_Robot callback will be used to notify a motion task (function Main in this example) that parts are available to be picked up.
Memory IO (labeled "PartsToPick1" and "PartsToPick2") are used to signal when parts are available.
When the last available part is being placed (80% of the way through the motion for this example), the motion task signals the PF_Robot function to finish and return a value. The return values lets the system know that it is ok to acquire new images, vibrate, supply parts from a hopper etc… We will now modify our tutorial code so that the feeder action can occur in parallel with the robot motion.
Main.prg
Function Main
Integer numToPick1, numToPick2, numPicked
Motor On
Power High
Speed 50
Accel 50, 50
Jump Park
MemOff PartsToPick1
MemOff PartsToPick2
numToPick1 = 2
numToPick2 = 1
PF_Start 1, 2
Do
numPicked = 0
Do
Wait MemSw(PartsToPick1) = On
pick = PF_QueGet(1)
PF_QueRemove (1)
Jump pick
On gripper1
Wait 0.1
numPicked = numPicked + 1
If numPicked < numToPick1 And PF_QueLen(1) > 0 Then
Jump Place
Else
' Last part or no more parts available to pick
If numPicked = numToPick1 Then
' Select the next part
PF_ActivePart 2
EndIf
Jump Place ! D80; MemOff PartsToPick1 !
EndIf
Off gripper1
Wait 0.1
Loop Until numPicked = numToPick1
numPicked = 0
Do
Wait MemSw(PartsToPick2) = On
pick = PF_QueGet(2)
PF_QueRemove (2)
Jump pick
On gripper2
Wait 0.1
numPicked = numPicked + 1
If numPicked < numToPick2 And PF_QueLen(2) > 0 Then
Jump Place
Else
' Last part or no more parts available to pick
If numPicked = numToPick2 Then
' Select the next part
PF_ActivePart 1
EndIf
Jump Place ! D80; MemOff PartsToPick2 !
EndIf
Off gripper2
Wait 0.1
Loop Until numPicked = numToPick2
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
Tutorial 2: 2 Robot, 1 Feeder, 2 Part Types
For this tutorial, there are two parts running on the same feeder at the same time. The parts are physically different. Part#1 and Part#2 are being used. There is a Fixed Downward camera over the feeder. Two robots will be sharing the same feeder. The robots will take turns picking from the feeder. Each robot will pick and place its own part. Robot#1 will pick up one of Part#1 and then Robot#2 will pick up one of Part#2.
The pick order matters for this application. The alternating pick order is accomplished with "PF_ActivePart". At first, we will write the code so that the robot motion is performed inside of the PF_Robot callback function. In this case, the robot motion will be sequential. In other words, only one robot will move at a time.
Then we will improve the robot throughput by performing motion in a separate multitasks. The revised tutorial will also include PF_AccessFeeder / PF_ReleaseFeeder. PF_AccessFeeder / PF_ReleaseFeeder are used to ensure that the robots will not collide when picking from the feeder.
- Create a new Epson RC+ project.
- Calibrate the Fixed Downward camera for Robot#1.
- Calibrate the Fixed Downward camera for Robot#2.
- From Vision Guide, create the Part Blob Sequence for Part#1. The Part Blob Sequence generally contains a single Blob vision object. The sequence will need to have the camera calibration that was performed for Robot#1 assigned to the Calibration property. The Blob object’s NumberToFind property should be set to "All".
The ThresholdAuto property of the Blob should be set to False (default value). Place parts on the platform, open the Histogram window and adjust the Threshold High and Low until only the parts are detected. Set the Blob’s MinArea to roughly 0.9 times that of the part’s area.
If the part has multiple sides, then set the MinArea so that the part can be found in any orientation. Make sure that the Part Blob Sequence can detect Part#1.
The Blob object’s Search Window should fill as much of the platform area as possible. That said, it is critical that the Blob object only finds the Parts and not the feeder tray itself. - From Vision Guide, create the Part Blob Sequence for Part#2. The Part Blob Sequence generally contains a single Blob vision object. The sequence will need to have the camera calibration that was performed for Robot#2 assigned to the Calibration property. The Blob object’s NumberToFind property should be set to "All".
The ThresholdAuto property of the Blob should be set to False (default value).
Place parts on the platform, open the Histogram window and adjust the Threshold High and Low until only the parts are detected.
Set the Blob’s MinArea to roughly 0.9 times that of the part’s area.
If the part has multiple sides, then set the MinArea so that the part can be found in any orientation. Make sure that the Part Blob Sequence can detect Part#2. The Blob object’s Search Window should fill as much of the platform area as possible.
That said, it is critical that the Blob object only finds the Parts and not the feeder tray itself. - From Vision Guide, create the Part Sequence which will be used to find Part#1.
Make sure to set the Calibration property to the calibration that was performed for Robot#1.
Typically, a Geometric object is used to locate the Front. (and a second Geometric object is used to find the Back of the part if Flip is required). The vision object’s NumberToFind property is normally set to "All". - From Vision Guide, create the Part Sequence which will be used to find Part#2.
Make sure to set the Calibration property to the calibration that was performed for Robot#2.
Typically, a Geometric object is used to locate the Front. (and a second Geometric object is used to find the Back of the part if Flip is required). The vision object’s NumberToFind property is normally set to "All". - Go to the [Tools] - [Part Feeding] dialog and Add a new part for Part#1. The "Part Wizard" will walk you through the process of adding a part. Make sure that you select Robot#1 on the first page of the Part Wizard.
For more details about the Part Wizard, please refer to the following chapter.
Let’s Use the Part Feeding Option - Go to the [Calibration] page for the new Part#1 and click on the [Calibrate] button to start the Calibration Wizard.
Please refer to the following section for details on how to use the Calibration Wizard.
Calibration & Test - Go to the [Pick] page for Part#1 and click the [Teach] button.
Jog Robot#1 to the part pick height and teach the "Pick Z". - Click the [Add] button in the [Part Feeding] dialog to add Part#2. Configure the part using the "Part Wizard".
Make sure that you select Robot#2 on the first page of the Part Wizard. - Go to the [Calibration] page and click the [Calibrate] button to start the Calibration Wizard.
- Go to the [Pick] page for Part#1 and click the [Teach] button. Jog Robot#2 to the part pick height and teach the "Pick Z".
- Close the Part Feeding dialog.
The Part Feeding template code (i.e., the Part Feeding callback functions) is automatically created. - Modify the template code as follows.
Main.prg
Function Main
Robot 1
Motor On
Power High
Speed 50
Accel 50, 50
Jump Park
Robot 2
Motor On
Power High
Speed 50
Accel 50, 50
Jump Park
PF_Start 1, 2
Fend
PartFeeding.prg
Function PF_Robot(PartID As Integer) As Integer
If PF_QueLen(PartID) > 0 Then
Select PartID
Case 1
Robot 1
P0 = PF_QueGet(1)
PF_QueRemove (1)
Jump P0 /R
On rbt1Gripper
Wait 0.25
Jump Place
Off rbt1Gripper
Wait 0.25
PF_ActivePart 2
Case 2
Robot 2
P0 = PF_QueGet(2)
PF_QueRemove (2)
Jump P0 /L
On rbt2Gripper
Wait 0.25
Jump Place
Off rbt2Gripper
Wait 0.25
PF_ActivePart 1
Send
EndIf
PF_Robot = PF_CALLBACK_SUCCESS
Fend
We will now modify the example code so that the robot motion will be performed in separate multitasks. When one robot is leaving the feeder, the other robot can begin moving toward the feeder. When robots share a feeder with parallel motion, it is critical that the PF_AccessFeeder and PF_ReleaseFeeder commands are used to prevent robot collisions.
In addition, the revised code will parallel process the feeder vibration and robot motion. In this tutorial, when each robot is 80% of the way to its place position, the robot has cleared the camera’s field of view and an image can be acquired.
Furthermore, when each robot is 80% of the way to its place position, it is safe for the other robot to begin moving toward the feeder. Of course, this is just an example. The actual percentage of motion depends on the speed and relative positioning of the robots in your specific situation. Each robot has a point labeled "park" and a point labeled "place". For this tutorial, Robot#1 picks from the feeder in a Righty arm orientation and Robot#2 picks from the feeder in a Lefty arm orientation.
Here is the revised template code.
Main.prg
Function Main
Robot 1
Motor On
Power High
Speed 50
Accel 50, 50
Jump Park
Robot 2
Motor On
Power High
Speed 50
Accel 50, 50
Jump Park
MemOff PartsToPick1
MemOff PartsToPick2
PF_Start 1, 2
Xqt Robot1PickPlace
Xqt Robot2PickPlace
Fend
Function Robot1PickPlace
Robot 1
Do
Wait MemSw(PartsToPick1) = On
PF_AccessFeeder 1
P0 = PF_QueGet(1)
PF_QueRemove (1)
Jump P0 /R
On rbt1Gripper
Wait 0.25
Jump Place ! D80; MemOff PartsToPick1; PF_ReleaseFeeder 1 !
Off rbt1Gripper
Wait 0.25
Loop
Fend
Function Robot2PickPlace
Robot 2
Do
Wait MemSw(PartsToPick2) = On
PF_AccessFeeder 1
P0 = PF_QueGet(2)
PF_QueRemove (2)
Jump P0 /L
On rbt2Gripper
Wait 0.25
Jump Place ! D80; MemOff PartsToPick2; PF_ReleaseFeeder 1 !
Off rbt2Gripper
Wait 0.25
Loop
Fend
PartFeeding.prg
Function PF_Robot(PartID As Integer) As Integer
Select PartID
Case 1
If PF_QueLen(1) > 0 Then
MemOn PartsToPick1
Wait MemSw(PartsToPick1) = Off
PF_ActivePart 2
Else
PF_ActivePart 1
EndIf
Case 2
If PF_QueLen(2) > 0 Then
MemOn PartsToPick2
Wait MemSw(PartsToPick2) = Off
PF_ActivePart 1
Else
PF_ActivePart 2
EndIf
Send
PF_Robot = PF_CALLBACK_SUCCESS
Fend