两个Items放在一个Container上

Simulation时,需要使用相机+Flow。可以在Pick程序的GetItmTgt程序前,先使用NextItmTgtType获取下一个Place的Container的第一个Item类型,然后使用该Container中的Item类型,指定GetItmTgt所需要获取的对应的Item,这样可以确保Item和Container中的Item一一对应,而不至于无序放置。

PROC Pick(num Index)
    VAR num PlaceType;
    VAR num PickType;
    IF Index>0 THEN
        WObjPick:=ItmSrcData{Index}.Wobj;
        NextItmTgtType ItmSrcData{PlaceWorkArea{1}}.ItemSource,PlaceType;
        TEST PlaceType
        CASE 0:
            PickType:=0;
        CASE 2:
            PickType:=2;
        ENDTEST
        GetItmTgt ItmSrcData{Index}.ItemSource,PickTarget\ItemType:=PickType;

        !GetItmTgt ItmSrcData{Index}.ItemSource,PickTarget;
        TriggL\Conc,RelTool(PickTarget.RobTgt,0,0,-ItmSrcData{Index}.OffsZ),MaxSpeed,ItmSrcData{Index}.VacuumAct1,z20,PickAct1\WObj:=WObjPick;
        TriggL\Conc,PickTarget.RobTgt,LowSpeed,ItmSrcData{Index}.SimAttach1,z5\Inpos:=ItmSrcData{Index}.TrackPoint,PickAct1\WObj:=WObjPick;
        GripLoad ItemLoad;
        TriggL RelTool(PickTarget.RobTgt,0,0,-ItmSrcData{Index}.OffsZ),LowSpeed,ItmSrcData{Index}.Ack,z20,PickAct1\WObj:=WObjPick;
    ELSE
        ErrWrite "Missing item distribution","Cannot pick because no item distribution contains current work area."\RL2:="Please check configuration";
        SafeStop;
    ENDIF
ENDPROC

WalkTheData

该程序在ppaBase.sys系统模块中定义,运行该程序会在”HOME:\TheData.log”文件中记录当前的Conveyor WorkAreas (NonCnvWOData{MaxNoSources}) 和Indexed WorkAreas (ItmSrcData{MaxNoSources}) 值。通常建议把该指令写在如下PickPlace函数的While循环前面。

PROC PickPlace()
    ConfL\Off;
    IF RestartOK=FALSE THEN
        SystemStopAction\Halt;
        RAISE PPA_RESTART;
    ENDIF
    MoveL SafePos,VeryLowSpeed,fine,Gripper\WObj:=wobj0;
    SetGO goVacBlow1,0;
    ResetAx4 ROB_ID;
    NotifyRunning;
    IF (FirstTime=TRUE) THEN
        WaitTime 1;
        FOR i FROM 1 TO MaxNoSources DO
            IF (ItmSrcData{i}.Used) THEN
                WaitTime 0.2;
                QStartItmSrc ItmSrcData{i}.ItemSource;
            ENDIF
        ENDFOR
        EnumerateWorkAreas;
        InitTriggs;
        InitPickTune;
        PickRateInit;
        FirstTime:=FALSE;
        WaitTime 0.2;
    ENDIF
    WalkTheData;
    WHILE TRUE DO
        IF (StopProcess=TRUE) THEN
            StopProcess:=FALSE;
            SafeStop;
        ENDIF
        PickPlaceSeq;
        IncrPicks;
        IF (CheckAx4Rev()=FALSE) THEN
            MoveL SafePos,MaxSpeed,fine,Gripper\WObj:=wobj0;
            ResetAx4 ROB_ID;
        ENDIF
    ENDWHILE
ERROR
    TEST ERRNO
    CASE PPA_RESTART:
        RAISE ;
    ENDTEST
ENDPROC


ItmSrcData
Index:       1
Used:        TRUE
ItmSrc Name: ItmSrcCnv1
ItmSrc Id:   28
ItmSrcType:  1
ufmec:       CNV1
VacActDelay: 0.02
VacRevDelay: 0.02
VacOffDelay: -0.02
TunePos x:   0
TunePos y:   0
TunePos z:   0
Followtime:  0.035
OffsZ:       30
 
Index:       2
Used:        TRUE
ItmSrc Name: ItmSrcCnv2
ItmSrc Id:   27
ItmSrcType:  2
ufmec:       CNV2
VacActDelay: 0.02
VacRevDelay: 0.02
VacOffDelay: -0.02
TunePos x:   0
TunePos y:   0
TunePos z:   0
Followtime:  0.035
OffsZ:       30

 
NonCnvWOData
Index:          1
Used:           FALSE
Name:           IdxWobj1
uframe.trans.x: 0
uframe.trans.y: 0
uframe.trans.z: 0
 
Index:          2
Used:           FALSE
Name:           IdxWobj2
uframe.trans.x: 0
uframe.trans.y: 0
uframe.trans.z: 0

多个Pick或Place的WorkArea

简单的站,一般都只有一个PickArea和一个PlaceArea,但是实际的站可能会有多个WorkArea。当一个机器人有多个Pick或者Place的WorkArea时,需要修改PickPlaceSeq函数,才能让机器人去Pick或Place其它WorkArea中的item。如下代码所示,该站中有两个Pick WorkArea,一个Place WorkArea,这个站的作用是从两个传送带上Pick物品,然后放到第三条传送带上。如果不修改程序,那么永远只会抓取第一个传送带的item然后放置到第三条传送带上,第二条传送带的workarea由于工件坐标系存储在PickWorkArea{2}中,没有被调用,所以永远不会被抓取。

PROC PickPlaceSeq()
    Pick PickWorkArea{1};
    !Pick PickWorkArea{2};
    Place PlaceWorkArea{1};
    !Place PlaceWorkArea{2};

    Pick PickWorkArea{2};
    Place PlaceWorkArea{1};
ENDPROC

日志文件夹

使用缓冲区Buffer

当传送带速度不是恒定是,比如Pick的传送带在某一时间内很快,虽然机器人可以正常抓取,但是由于Place传送带的Container来不及供应,导致机器人无处放置Item,此时可以设置一个缓冲区Buffer,让机器人先暂存在Buffer中。当过一段时间,Pick的传送带速度变慢了,此时Place的传送带的Container空出来了,虽然机器人可以正常放置,但因为没有item,导致机器人等待item,此时如果buffer中有数据,就可以从buffer中拾取之前放置的缓存item,然后放置在container中,提供整体生产效率。使用缓存不能使用Start/Stop功能,否则传送带可能会停下来,导致一直取不到item,陷入死循环。

判断是否启用buffer

是否启用buffer包含三种状态:

  1. Picked:=1,pick传送带有item,Place传送带有container,此时正常抓放。
  2. Picked:=2,Pick传送带有item,place传送带没有container,buffer中有item,此时机器人把item抓放到buffer中。
  3. Picked:=3,Pick传送带没有item,Place传送带有Container,buffer中缺item,此时机器人从buffer中拾取item放到contrainer中。

下面程序会先判断pick传送带中是否有item,如果有,就获取pick传送带的item type,如果该type的item有container可以放置,就设置Picked为1,如果没有,就判断该type的item在对应的buffer中有没有放满,如果没满就设置Picked为3,如果满了就啥也不干,可以重新放回队列,也可以直接忽略,放item自动掉落到传送带末端。当检测到pick传送带上没有item时,判断container中可以放置的下一个item和type,当有空位时,检测对应type的itme此时有没有重新在pick传送带上,如果有,则设置Picked=1,正常抓取,如果没有,判断一下buffer中有没有对应type的item,有则设置Picked=2,没有则设置Picked=0。

PROC PickPlaceSeq()
    VAR num GQL:=0;


    Picked:=0;
    WHILE Picked=0 DO
        IType:=0;
        !=== PickPosAvailable ? ===
        GQL:=GetQueueLevel(ItmSrcData{PickWorkArea{1}}.ItemSource\MinLimit:=InFlowEnter\MaxLimit:=InFlowExit);
        If GQL>0 THEN
            NextItmTgtType ItmSrcData{PickWorkArea{1}}.ItemSource,IType;
            !=== Matching Item on outfeeder ? ===
            GQL:=GetQueueLevel(ItmSrcData{PlaceWorkArea{1}}.ItemSource\ItmType:=IType\MinLimit:=OutFlowEnter\MaxLimit:=OutFlowExit);
            IF GQL>0 THEN
                Picked:=1;
            ELSE
                !=== Empty pos in buffer? ===
                IF BufferIndex{IType}<BufferMax{IType} THEN
                    Picked:=3;
                ELSE
                    !=== What to do with the item on the infeeder? ===
                    GetItmTgt ItmSrcData{PickWorkArea{1}}.ItemSource,PickTarget\ItemType:=IType;
                    TEST DropAction
                    CASE 0:
                        AckItmTgt ItmSrcData{PickWorkArea{1}}.ItemSource,PickTarget,TRUE;
                    CASE 1:
                        AckItmTgt ItmSrcData{PickWorkArea{1}}.ItemSource,PickTarget,FALSE;
                    CASE 2:
                        AckItmTgt ItmSrcData{PickWorkArea{1}}.ItemSource,PickTarget,FALSE\Skip:=TRUE;
                    ENDTEST
                    Picked:=0;
                ENDIF
            ENDIF
        ELSE
            GQL:=GetQueueLevel(ItmSrcData{PlaceWorkArea{1}}.ItemSource\MinLimit:=OutFlowEnter\MaxLimit:=OutFlowExit);
            If GQL>0 THEN
                NextItmTgtType ItmSrcData{PlaceWorkArea{1}}.ItemSource,IType;
                !=== Matching Item on Infeeder ? ===
                GQL:=GetQueueLevel(ItmSrcData{PickWorkArea{1}}.ItemSource\ItmType:=IType\MinLimit:=InFlowEnter\MaxLimit:=InFlowExit);
                IF GQL>0 THEN
                    Picked:=1;
                ELSE
                    !=== Matching pos in buffer? ===
                    IF BufferIndex{IType}>0 THEN
                        Picked:=2;
                    ELSE
                        Picked:=0;
                    ENDIF
                ENDIF
            ELSE
                Picked:=0;
            ENDIF
        ENDIF

        TEST Picked
        CASE 0:
            !=== No pick, no place ===
            WaitTime 0.1;
        CASE 1:
            !=== pick infeed, place outfeed ===
            Pick PickWorkArea{1},IType;
            Place PlaceWorkArea{1},IType;
        CASE 2:
            !=== pick buffer, place outfeed ===
            PickBuffer PickWorkArea{1},IType;
            Place PlaceWorkArea{1},IType;
        CASE 3:
            !=== pick infeed, place buffer ===
            Pick PickWorkArea{1},IType;
            PlaceBuffer PlaceWorkArea{1},IType;
        ENDTEST
    ENDWHILE
ENDPROC

抓取item到buffer中

PROC PickBuffer(num Index,num TypeNr)
    VAR num zboffs;
    BufferX{TypeNr}:=(BufferIndex{TypeNr}-1)*BufferPitch{TypeNr};
    WObjPick:=Wobj0;
    zboffs:=BufferZ{TypeNr};
    TriggL\Conc,Offs(RelTool(BufferPos{TypeNr},0,0,-ItmSrcData{Index}.OffsZ),BufferX{TypeNr},0,0),MaxSpeed,ItmSrcData{Index}.VacuumAct1,z20,PickAct1\WObj:=WObjPick;
    TriggL\Conc,Offs(BufferPos{TypeNr},BufferX{TypeNr},0,zboffs),LowSpeed,ItmSrcData{Index}.SimAttach1,z5\Inpos:=ItmSrcData{Index}.TrackPoint,PickAct1\WObj:=WObjPick;
    GripLoad ItemLoad;
    MoveL Offs(RelTool(BufferPos{TypeNr},0,0,-ItmSrcData{Index}.OffsZ),BufferX{TypeNr},0,0),LowSpeed,z20,PickAct1\WObj:=WObjPick;
    Decr BufferIndex{TypeNr};
ENDPROC

PROC PlaceBuffer(num Index,num TypeNr)
  VAR num zboffs;
  Incr BufferIndex{TypeNr};
  BufferX{TypeNr}:=(BufferIndex{TypeNr}-1)*BufferPitch{TypeNr};
  WObjPlace:=Wobj0;
  zboffs:=BufferZ{TypeNr};
  MoveL\Conc,Offs(RelTool(BufferPos{TypeNr},0,0,-ItmSrcData{Index}.OffsZ),BufferX{TypeNr},0,0),MaxSpeed,z20,PickAct1\WObj:=WObjPlace;
  TriggL\Conc,Offs(BufferPos{TypeNr},BufferX{TypeNr},0,zboffs),LowSpeed,ItmSrcData{Index}.VacuumRev1\T2:=ItmSrcData{Index}.VacuumOff1\T3:=ItmSrcData{Index}.SimDetach1,z5\Inpos:=ItmSrcData{Index}.TrackPoint,PickAct1\WObj:=WObjPlace;
  GripLoad load0;
  MoveL Offs(RelTool(BufferPos{TypeNr},0,0,-ItmSrcData{Index}.OffsZ),BufferX{TypeNr},0,0),LowSpeed,z20,PickAct1\WObj:=WObjPlace;
ENDPROC

变量

  1. BufferMax,存储中item的最大缓存数量,数组元素的个数对应着item的type数量,程序中设置的是一个3个元素的数组,所以支持三种type的item,每个item允许最大缓存3个。
  2. BufferIndex,每个type的item当前在buffer中的数量
  3. BufferPitch,每个type的item每次在缓存Buffer区域中,X轴的偏移量
  4. BufferX,通过BufferPitch和BufferPitch计算的下一个item在buffer中的X坐标
  5. BufferZ,每个type的item在buffer中的高度
  6. BufferPos,每个type的item在buffer中的第一个item的位置。

     !***********************************************************
     !  Global BUFFER Variables
     !  Robtarget BufferPos must be defined in wobj0
     !***********************************************************
     TASK PERS robtarget BufferPos{3}:=[ [[-200,-10,-1084],[0,-1,0,0],[0,0,0,0],[0,0,0,0,0,0]] , [[0,-10,-1084],[0,-1,0,0],[0,0,0,0],[0,0,0,0,0,0]] , [[200,-10,-1084],[0,-1,0,0],[0,0,0,0],[0,0,0,0,0,0]] ];
     VAR num BufferMax{3}:=[4,4,4];      !Number of items i a buffer
     VAR num BufferPitch{3}:=[50,50,50]; !distance between buffer positions
     VAR num DropAction:=0;         !What to do if an item can not be used. 0=Ack 1=Nack 2=Skip
     VAR num BufferZ{3}:=[0,0,0];   !Buffer Z-adjustments
    	
     VAR num InFlowEnter:=-250;     !Set to same as pickarea Enter limit
     VAR num InFlowExit:=250;       !Set to litte before pickarea Exit limit
     VAR num OutFlowEnter:=-250;    !Set to same as placearea Enter limit
     VAR num OutFlowExit:=250;      !Set to litte before placearea Exit limit
    	
     VAR num BufferX{3};
     VAR num BufferY{3};
     VAR num BufferIndex{3}:=[0,0,0];
     VAR num IType:=0;
     VAR num Picked:=0;
    

确认PickType和PlaceType是否一致

!***********************************************************
!
! Procedure PickPlaceSeq
!
!   The Pick and Place sequence.
!   Edit this routine to modify from which work areas to pick and place.
!   Needs to be changed if more than one pick work area is used.
!   Needs to be changed if more than one place work area is used.
!
!***********************************************************
PROC PickPlaceSeq()
    VAR num PickType:=1;
    VAR num PlaceType:=1;
    NextItmTgtType ItmSrcData{PlaceWorkArea{1}}.ItemSource,PlaceType;
    PickType:=PlaceType;
    TEST PickType
    CASE 0:
        Pick PickWorkArea{1};
    CASE 2:
        Pick PickWorkArea{2};
    CASE 4:
        Pick PickWorkArea{3};
    DEFAULT:
    ENDTEST

    !        NextItmTgtType ItmSrcData{PlaceWorkArea{1}}.ItemSource,PlaceType;
    !        Logging "NextType: PickType="+ValToStr(PickType)+", PlaceType="+ValToStr(PlaceType)+" "+ValToStr(PickType=PlaceType);
    !        WHILE PickType<>PlaceType DO
    !            GetItmTgt ItmSrcData{PlaceWorkArea{1}}.ItemSource,PlaceTarget;
    !            AckItmTgt ItmSrcData{PlaceWorkArea{1}}.ItemSource,PlaceTarget,TRUE;
    !            NextItmTgtType ItmSrcData{PlaceWorkArea{1}}.ItemSource,PlaceType;
    !            Logging "NextType: PickType="+ValToStr(PickType)+", PlaceType="+ValToStr(PlaceType)+" "+ValToStr(PickType=PlaceType);
    !        ENDWHILE

    Place PlaceWorkArea{1};
ENDPROC

!***********************************************************
!
! Procedure Pick
!
!   Executes a pick movement.
!   Edit this routine to modify how the robot shall
!   execute the pick movements.
!   Needs to be changed if more than one activator is used.
!
!***********************************************************
PROC Pick(num Index)
    IF Index>0 THEN
        WObjPick:=ItmSrcData{Index}.Wobj;
        GetItmTgt ItmSrcData{Index}.ItemSource,PickTarget;
        Logging "Pick: PickType="+ValToStr(PickTarget.Type);
        TriggL\Conc,RelTool(PickTarget.RobTgt,0,0,-ItmSrcData{Index}.OffsZ),MaxSpeed,ItmSrcData{Index}.VacuumAct1,z20,PickAct1\WObj:=WObjPick;
        TriggL\Conc,PickTarget.RobTgt,LowSpeed,ItmSrcData{Index}.SimAttach1,z5\Inpos:=ItmSrcData{Index}.TrackPoint,PickAct1\WObj:=WObjPick;
        GripLoad ItemLoad;
        TriggL RelTool(PickTarget.RobTgt,0,0,-ItmSrcData{Index}.OffsZ),LowSpeed,ItmSrcData{Index}.Ack,z20,PickAct1\WObj:=WObjPick;
    ELSE
        ErrWrite "Missing item distribution","Cannot pick because no item distribution contains current work area."\RL2:="Please check configuration";
        SafeStop;
    ENDIF
ENDPROC

!***********************************************************
!
! Procedure Place
!
!   Executes a place movement.
!   Edit this routine to modify how the robot shall
!   execute the place movements.
!   Needs to be changed if more than one activator is used.
!
!***********************************************************
PROC Place(num Index)
    IF Index>0 THEN
        WObjPlace:=ItmSrcData{Index}.Wobj;

        GetItmTgt ItmSrcData{Index}.ItemSource,PlaceTarget;
        Logging "Place: PickType="+ValToStr(PickTarget.Type)+", PlaceType="+ValToStr(PlaceTarget.Type)+" "+ValToStr(PickTarget.Type=PlaceTarget.Type);
        WHILE PickTarget.Type<>PlaceTarget.Type DO
            AckItmTgt ItmSrcData{PlaceWorkArea{1}}.ItemSource,PlaceTarget,TRUE;
            GetItmTgt ItmSrcData{Index}.ItemSource,PlaceTarget;
            Logging "Place: PickType="+ValToStr(PickTarget.Type)+", PlaceType="+ValToStr(PlaceTarget.Type)+" "+ValToStr(PickTarget.Type=PlaceTarget.Type);
        ENDWHILE

        Logging "Place: PickType="+ValToStr(PickTarget.Type)+", PlaceType="+ValToStr(PlaceTarget.Type);
        MoveL\Conc,RelTool(PlaceTarget.RobTgt,0,0,-ItmSrcData{Index}.OffsZ),MaxSpeed,z20,PickAct1\WObj:=WObjPlace;
        TriggL\Conc,PlaceTarget.RobTgt,LowSpeed,ItmSrcData{Index}.VacuumRev1\T2:=ItmSrcData{Index}.VacuumOff1\T3:=ItmSrcData{Index}.SimDetach1,z5\Inpos:=ItmSrcData{Index}.TrackPoint,PickAct1\WObj:=WObjPlace;
        GripLoad load0;
        TriggL RelTool(PlaceTarget.RobTgt,0,0,-ItmSrcData{Index}.OffsZ),LowSpeed,ItmSrcData{Index}.Ack,z20,PickAct1\WObj:=WObjPlace;
    ELSE
        ErrWrite "Missing item distribution","Cannot place because no item distribution contains current work area."\RL2:="Please check configuration";
        SafeStop;
    ENDIF
ENDPROC

3进1出

FUNC bool IsPickPlaceMatched(num PickIndex,num PlaceIndex)
    VAR bool PickPlaceMatched:=FALSE;
    VAR num PickType:=1;
    VAR num PlaceType:=1;
    VAR num WaitTime:=1;
    VAR bool TimeOutPick:=TRUE;
    VAR bool TimeOutPlace:=TRUE;
    Logging "Trying to match PickIndex="+ValToStr(PickIndex)+", PlaceIndex="+ValToStr(PlaceIndex)+" ...";
    NextItmTgtType ItmSrcData{PickIndex}.ItemSource,PickType\MaxTime:=WaitTime/2\TimeFlag:=TimeOutPick;
    NextItmTgtType ItmSrcData{PlaceIndex}.ItemSource,PlaceType\MaxTime:=WaitTime/2\TimeFlag:=TimeOutPlace;
    IF TimeOutPick=FALSE AND TimeOutPlace=TRUE THEN
        Logging "PickType="+ValToStr(PickType)+", but no container";
    ELSEIF TimeOutPick=TRUE AND TimeOutPlace=FALSE THEN
        Logging "PlaceType="+ValToStr(PlaceType)+", but no item";
    ELSEIF TimeOutPick=FALSE AND TimeOutPlace=FALSE THEN
        IF PickType=PlaceType THEN
            PickPlaceMatched:=TRUE;
            Logging "PickType=PlaceType="+ValToStr(PickType);
        ELSE
            Logging "PickType="+ValToStr(PickType)+", PlaceType="+ValToStr(PlaceType);
        ENDIF
    ENDIF
    RETURN PickPlaceMatched;
ENDFUNC

!***********************************************************
!
! Procedure PickPlaceSeq
!
!   The Pick and Place sequence.
!   Edit this routine to modify from which work areas to pick and place.
!   Needs to be changed if more than one pick work area is used.
!   Needs to be changed if more than one place work area is used.
!
!***********************************************************
PROC PickPlaceSeq()
    VAR num PickType:=1;
    VAR num PlaceType:=1;
    VAR num WaitTime:=1;
    VAR bool TimeOutPick:=TRUE;
    VAR bool TimeOutPlace:=TRUE;
    VAR num PickIndex:=0;

    IF IsPickPlaceMatched(PickWorkArea{1},PlaceWorkArea{1}) THEN
        PickIndex:=1;
    ELSE
        IF IsPickPlaceMatched(PickWorkArea{2},PlaceWorkArea{1}) THEN
            PickIndex:=2;
        ELSE
            IF IsPickPlaceMatched(PickWorkArea{3},PlaceWorkArea{1}) THEN
                PickIndex:=3;
            ENDIF
        ENDIF
    ENDIF

    IF PickIndex>0 THEN
        Pick PickWorkArea{PickIndex};
        Place PlaceWorkArea{1};
    ENDIF

ENDPROC

!***********************************************************
!
! Procedure Pick
!
!   Executes a pick movement.
!   Edit this routine to modify how the robot shall
!   execute the pick movements.
!   Needs to be changed if more than one activator is used.
!
!***********************************************************
PROC Pick(num Index)
    VAR num PickType:=1;
    VAR num PlaceType:=1;
    VAR bool PickPlaceMatched:=FALSE;
    IF Index>0 THEN
        WObjPick:=ItmSrcData{Index}.Wobj;

        WHILE NOT PickPlaceMatched DO
            GetItmTgt ItmSrcData{Index}.ItemSource,PickTarget;
            NextItmTgtType ItmSrcData{PlaceWorkArea{1}}.ItemSource,PlaceType;
            PickPlaceMatched:=PickTarget.Type=PlaceType;
            Logging "Pick "+ValToStr(Index)+" : PickType="+ValToStr(PickTarget.Type)+", PlaceType="+ValToStr(PlaceType)+" "+ValToStr(PickPlaceMatched);
            IF NOT PickPlaceMatched THEN
                AckItmTgt ItmSrcData{Index}.ItemSource,PickTarget,FALSE\Skip:=TRUE;
            ENDIF
        ENDWHILE

        TriggL\Conc,RelTool(PickTarget.RobTgt,0,0,-ItmSrcData{Index}.OffsZ),MaxSpeed,ItmSrcData{Index}.VacuumAct1,z20,PickAct1\WObj:=WObjPick;
        TriggL\Conc,PickTarget.RobTgt,LowSpeed,ItmSrcData{Index}.SimAttach1,z5\Inpos:=ItmSrcData{Index}.TrackPoint,PickAct1\WObj:=WObjPick;
        GripLoad ItemLoad;
        TriggL RelTool(PickTarget.RobTgt,0,0,-ItmSrcData{Index}.OffsZ),LowSpeed,ItmSrcData{Index}.Ack,z20,PickAct1\WObj:=WObjPick;
    ELSE
        ErrWrite "Missing item distribution","Cannot pick because no item distribution contains current work area."\RL2:="Please check configuration";
        SafeStop;
    ENDIF
ENDPROC

!***********************************************************
!
! Procedure Place
!
!   Executes a place movement.
!   Edit this routine to modify how the robot shall
!   execute the place movements.
!   Needs to be changed if more than one activator is used.
!
!***********************************************************
PROC Place(num Index)
    VAR bool PickPlaceMatched:=FALSE;
    IF Index>0 THEN
        WObjPlace:=ItmSrcData{Index}.Wobj;

        WHILE NOT PickPlaceMatched DO
            GetItmTgt ItmSrcData{Index}.ItemSource,PlaceTarget;
            PickPlaceMatched:=PickTarget.Type=PlaceTarget.Type;
            Logging "Place "+ValToStr(Index)+" : PickType="+ValToStr(PickTarget.Type)+", PlaceType="+ValToStr(PlaceTarget.Type)+" "+ValToStr(PickPlaceMatched);
            IF NOT PickPlaceMatched THEN
                AckItmTgt ItmSrcData{Index}.ItemSource,PlaceTarget,FALSE\Skip:=TRUE;
            ENDIF
        ENDWHILE

        MoveL\Conc,RelTool(PlaceTarget.RobTgt,0,0,-ItmSrcData{Index}.OffsZ),MaxSpeed,z20,PickAct1\WObj:=WObjPlace;
        TriggL\Conc,PlaceTarget.RobTgt,LowSpeed,ItmSrcData{Index}.VacuumRev1\T2:=ItmSrcData{Index}.VacuumOff1\T3:=ItmSrcData{Index}.SimDetach1,z5\Inpos:=ItmSrcData{Index}.TrackPoint,PickAct1\WObj:=WObjPlace;
        GripLoad load0;
        TriggL RelTool(PlaceTarget.RobTgt,0,0,-ItmSrcData{Index}.OffsZ),LowSpeed,ItmSrcData{Index}.Ack,z20,PickAct1\WObj:=WObjPlace;
    ELSE
        ErrWrite "Missing item distribution","Cannot place because no item distribution contains current work area."\RL2:="Please check configuration";
        SafeStop;
    ENDIF
ENDPROC

多个传送带Item,一个Container传送带

当多个item放到一个container时,为了避免错放,需要添加GetItmTgt指令的ItemType参数。GetItmTgt ItmSrcData{Index}.ItemSource,PlaceTarget\ItemType:=PickTarget.Type;

PROC PickPlaceSeq()
    VAR num PickType:=1;
    VAR num PlaceType:=1;
    VAR num WaitTime:=1;
    VAR bool TimeOutPick:=TRUE;
    VAR bool TimeOutPlace:=TRUE;
    VAR num PickIndex:=0;

    NextItmTgtType ItmSrcData{PlaceWorkArea{1}}.ItemSource,PlaceType;
    PickType:=PlaceType;
    TEST PickType
    CASE 0:
        Pick PickWorkArea{1};
    CASE 2:
        Pick PickWorkArea{2};
    CASE 4:
        Pick PickWorkArea{3};
    DEFAULT:
    ENDTEST

    Place PlaceWorkArea{1};
    
ENDPROC

!***********************************************************
!
! Procedure Pick
!
!   Executes a pick movement.
!   Edit this routine to modify how the robot shall
!   execute the pick movements.
!   Needs to be changed if more than one activator is used.
!
!***********************************************************
PROC Pick(num Index)
    VAR num PickType:=1;
    VAR num PlaceType:=1;
    VAR bool PickPlaceMatched:=FALSE;
    IF Index>0 THEN
        WObjPick:=ItmSrcData{Index}.Wobj;

        GetItmTgt ItmSrcData{Index}.ItemSource,PickTarget;

        TriggL\Conc,RelTool(PickTarget.RobTgt,0,0,-ItmSrcData{Index}.OffsZ),MaxSpeed,ItmSrcData{Index}.VacuumAct1,z20,PickAct1\WObj:=WObjPick;
        TriggL\Conc,PickTarget.RobTgt,LowSpeed,ItmSrcData{Index}.SimAttach1,z5\Inpos:=ItmSrcData{Index}.TrackPoint,PickAct1\WObj:=WObjPick;
        GripLoad ItemLoad;
        TriggL RelTool(PickTarget.RobTgt,0,0,-ItmSrcData{Index}.OffsZ),LowSpeed,ItmSrcData{Index}.Ack,z20,PickAct1\WObj:=WObjPick;
    ELSE
        ErrWrite "Missing item distribution","Cannot pick because no item distribution contains current work area."\RL2:="Please check configuration";
        SafeStop;
    ENDIF
ENDPROC

!***********************************************************
!
! Procedure Place
!
!   Executes a place movement.
!   Edit this routine to modify how the robot shall
!   execute the place movements.
!   Needs to be changed if more than one activator is used.
!
!***********************************************************
PROC Place(num Index)
    VAR bool PickPlaceMatched:=FALSE;
    IF Index>0 THEN
        WObjPlace:=ItmSrcData{Index}.Wobj;

        GetItmTgt ItmSrcData{Index}.ItemSource,PlaceTarget\ItemType:=PickTarget.Type;

        MoveL\Conc,RelTool(PlaceTarget.RobTgt,0,0,-ItmSrcData{Index}.OffsZ),MaxSpeed,z20,PickAct1\WObj:=WObjPlace;
        TriggL\Conc,PlaceTarget.RobTgt,LowSpeed,ItmSrcData{Index}.VacuumRev1\T2:=ItmSrcData{Index}.VacuumOff1\T3:=ItmSrcData{Index}.SimDetach1,z5\Inpos:=ItmSrcData{Index}.TrackPoint,PickAct1\WObj:=WObjPlace;
        GripLoad load0;
        TriggL RelTool(PlaceTarget.RobTgt,0,0,-ItmSrcData{Index}.OffsZ),LowSpeed,ItmSrcData{Index}.Ack,z20,PickAct1\WObj:=WObjPlace;
    ELSE
        ErrWrite "Missing item distribution","Cannot place because no item distribution contains current work area."\RL2:="Please check configuration";
        SafeStop;
    ENDIF
ENDPROC