RobotStudio event

Wait for condition in a subroutine

I'm trying to create an alternative WaitUntil routine, where I can perform certain tasks while waiting for specific conditions to be met.
I'm thinking the routine should look something like this:

PROC MyOwn_WaitUntil(bool Cond\num MaxTime\INOUT bool TimeFlag)
  VAR clock cTimerWait;

  WHILE Cond=FALSE AND (Present(MaxTime)=FALSE OR clkRead(cTimerWait)<MaxTime) DO
    WaitTime 0.05;
    ClkStart cTimerWait;
    !
    ! - DO OTHER STUFF - !
    !
  ENDWHILE

  IF Cond=FALSE AND (Present(MaxTime)=TRUE AND clkRead(cTimerWait)>MaxTime) THEN
    IF Present(TimeFlag)=TRUE THEN
      TimeFlag:=TRUE;
      RETURN ;
    ELSE
      RAISE ERR_WAIT_MAXTIME;
    ENDIF
  ENDIF
    
  RETURN;

ENDPROC

PROC TestWaitUntil()

MyOwn_WaitUntil diSensor1=1\MaxTime:=5;

ENDPROC

The problem in this code is that the parameter "Cond" is not updating, i.e. if diSensor1 equals 0 when entering the routine the parameter Cond is set to FALSE and remains FALSE even when diSensor1 turns on.

Does anyone have suggestions on how to change this code to always get the actual state of "Cond"?


Comments

  • I'm not sure if it helps but have you tried INOUT ? 
    PROC MyOwn_WaitUntil(INOUT bool Cond\num MaxTime\INOUT bool TimeFlag)
    Systemintegrator - Web / C# / Rapid / Robotstudio

    If I helped, please press Vote Up  :smile:

    ☑️2024 - RobotStudio® User Group
  • I have tried both INOUT and VAR bool. They "work" in that sense the variable inside the routine is updated, but the input parameter must be one simple variable. It does not work with for example digital inputs or numerical comparisons.
  • lemster68
    lemster68 ✭✭✭
    Make it a function. The TestDI function already exists for the datatype for Inputs, SignalDI.
    Lee Justice
  • mandolas
    mandolas
    edited October 7
    Hi ...
    For this to work correctly you must work with Alias ​​associated with the entries you want.
    Here is an example:
    PROC RobotHeating(string sAliasDIExecHeating)
            !########
            VAR num presentDayL:=1;
            !########
    	
    
            ! Associate the Alias ​​...
            AliasIO sAliasDIExecHeating,aliasDiExecActionL;
    
            ! Wait if the signal is 0 ...
            IF (aliasDiExecActionL=1) THEN
                presentDayL:=GetTime(\WDay);
            ELSE
                IF aliasDiExecActionL=0 THEN
                    WaitUntil aliasDiExecActionL=1;
    				
                    presentDayL:=GetTime(\WDay);
                ENDIF
            ENDIF
        ERROR
             TPErase;
    
            TEST ERRNO
            CASE ERR_ALIASIO_DEF:
                ErrWrite "ERR_ALIASIO_DEF",""
                
                EXIT;
            CASE ERR_ALIASIO_TYPE:
                RETRY;
            CASE ERR_NO_ALIASIO_DEF:
                RETRY;
            CASE ERR_OVERFLOW
            DEFAULT:
                Stop;
            ENDTEST
    ENDPROC

    MODULE ModPRG()
        VAR string sAliasDIExecHeating;
        
        PROC main()
            sAliasDIExecHeating:="PLC_Rx_HeatingAx"
            RobotHeating sAliasDIExecHeating;
        ENDPROC
    ENDMODULE

    'PLC_Rx_HeatingAx' is the name of the signal, as it is in the EIO.cfg file

    I hope this helps.
    Good work.
  • lemster68
    lemster68 ✭✭✭
    Simmu said:
    I have tried both INOUT and VAR bool. They "work" in that sense the variable inside the routine is updated, but the input parameter must be one simple variable. It does not work with for example digital inputs or numerical comparisons.
    A routine can have many parameters, not just one.  They can also be of different datatypes and can also be optional parameters.  I will provide an example:

    MODULE LEERULZ
      !
      ! This module contains two routines, rEnter and rExit which are 
      ! intended to be universal handshake routines for requesting
      ! entry from the cell controller to enter an area, fixture or
      ! robot interference zone.  When called, the user must pass in
      ! the parameters and switches unique to the user's installation.
      ! I.E., Digital inputs and digital outputs from your IO map, your
      ! tool and workobjects, if used.  Nothing is hard-coded, so there
      ! is no need to rewrite these routines for your particular
      ! project.  Both routines have Backward handlers so the user will
      ! be able to step backwards through the procedure call.  The robot
      ! will move back to where it came from using the parameter passed
      ! which should be the parameter robtarget or jointtarget from which
      ! it came when requesting entry or exit.  Then It will set or reset
      ! the digital output for clear as appropriate to enter or exit.
      ! pass in the parameter for the path interpolation used, linear, joint
      ! or MoveAbsJ. Or, the default will be joint interpolation.
      ! Example procedure call:
      ! rEnter "Station 1", doSta1EntRequest, diSta1ClearEnter1, doSta1InFixture, tGripper\WObj:=wobjStation1\swMoveJoint\pPreviouspoint:=p10;
      !
      ! Older S4C, S4C+ robots require developer functions option, I think, to use functions 
      ! like ArgName().  I think in newer IRC5 such things are now standard.
    		
      PROC rEnter(
        string area,
        VAR signaldo request,
        VAR signaldi signal,
        VAR signaldo notclear,
        PERS tooldata tool,
        \PERS wobjdata WObj
        \switch swMoveAbs
        |switch swMoveLin
        |switch swMoveJoint
        \robtarget pPreviouspoint
        |jointtarget jposPrevious)
    
        VAR num nDummy;
        VAR bool bTimeFlag;
        VAR errnum erBreakFlag;
        CONST string stFixClear:="Clear signal has been received, ";
    
        IF (NOT Present(pPreviouspoint)) AND (NOT Present(jposPrevious)) THEN
          TPErase;
          TPWrite "Neither a robtarget nor a jointtarget   were provided!!!";
          TPWrite "Please remedy this from where this";
          TPWrite "procedure was called.";
          TPWrite "Backwards execution will NOT be possible!!!";
        ENDIF
        IF (Present(jposPrevious)) AND (NOT Present(swMoveAbs)) THEN
          TPErase;
          TPWrite "The optional switch for MoveAbsJ was    not provided";
          TPWrite " but a jointtarget was!!!";
          TPWrite "Please remedy this from where this";
          TPWrite "procedure was called.";
          TPWrite "Backwards execution will NOT be possible!!!";
        ENDIF
        Set request;
        WaitUntil signal=1\MaxTime:=2\TimeFlag:=bTimeFlag;
        IF bTimeFlag AND OpMode()=OP_MAN_PROG THEN
          TPWrite "Waiting for Clear signal, ";
          TPReadFK nDummy,ArgName(signal),"","",""," ",""\DIBreak:=signal\BreakFlag:=erBreakFlag;
        ELSE
          TPWrite "Waiting for Clear signal, ";
          TPWrite ArgName(signal);
          WaitDI signal,1;
        ENDIF
        TPWrite stFixClear;
        TPWrite ArgName(signal);
        Reset notclear;
        Reset request;
      BACKWARD
        IF (NOT Present(pPreviouspoint)) AND (NOT Present(jposPrevious)) THEN
          TPErase;
          TPWrite "Neither a robtarget nor a jointtarget were provided!!!";
          TPWrite "Please remedy this from where this procedure";
          TPWrite "was called.";
        ENDIF
        IF Present(swMoveAbs) THEN
          MoveAbsJ jposPrevious,v500,fine,Tool\WObj?WObj;
        ELSEIF Present(swMoveLin) THEN
          MoveL pPreviouspoint,v500,fine,Tool\WObj?WObj;
        ELSE
          MoveJ pPreviouspoint,v500,fine,Tool\WObj?WObj;
        ENDIF
        TPWrite "Robot clearing " + area;
        Set notclear;
        RETURN;
      ENDPROC
    
      PROC rExit(
        string area,
        VAR signaldo request,
        VAR signaldi signal,
        VAR signaldo notclear,
        PERS tooldata tool,
        \PERS wobjdata WObj
        \switch swMoveAbs
        |switch swMoveLin
        |switch swMoveJoint
        \robtarget pPreviouspoint
        |jointtarget jposPrevious)
    
        VAR num nDummy;
        VAR bool bTimeFlag;
        VAR errnum erBreakFlag;
        CONST string stExiting:="Robot exiting ";
        CONST string stReturning:="Robot Returning ";
    
        IF (NOT Present(pPreviouspoint)) AND (NOT Present(jposPrevious)) THEN
          TPErase;
          TPWrite "Neither a robtarget nor a jointtarget   were provided!!!";
          TPWrite "Please remedy this from where this";
          TPWrite "procedure was called.";
          TPWrite "Backwards execution will NOT be possible!!!";
        ENDIF
        IF (Present(jposPrevious)) AND (NOT Present(swMoveAbs)) THEN
          TPErase;
          TPWrite "The optional switch for MoveAbsJ was    not provided";
          TPWrite " but a jointtarget was!!!";
          TPWrite "Please remedy this from where this";
          TPWrite "procedure was called.";
          TPWrite "Backwards execution will NOT be possible!!!";
        ENDIF
        Set request;
        WaitUntil signal=1\MaxTime:=2\TimeFlag:=bTimeFlag;
        IF bTimeFlag AND OpMode()=OP_MAN_PROG THEN
          TPWrite "Waiting for Clear signal, ";
          TPReadFK nDummy,ArgName(signal),"","",""," ",""\DIBreak:=signal\BreakFlag:=erBreakFlag;
        ELSE
          TPWrite "Waiting for Clear signal, ";
          TPWrite ArgName(signal);
          WaitDI signal,1;
        ENDIF
        TPWrite stExiting+area;
        ! The VAR signaldo notclear is not set here
        ! because some motion is necessary to get the 
        ! robot actually clear.  If it were set here
        ! then the robot is not clear because no Motion
        ! has occurred yet.
        Reset request;
      BACKWARD
        Reset notclear;
        IF Present(swMoveAbs) THEN
          MoveAbsJ jposPrevious,v500,fine,Tool\WObj?WObj;
        ELSEIF Present(swMoveLin) THEN
          MoveL pPreviouspoint,v500,fine,Tool\WObj?WObj;
        ELSE
          MoveJ pPreviouspoint,v500,fine,Tool\WObj?WObj;
        ENDIF
        TPWrite stReturning+area;
        RETURN;
      ENDPROC
    ENDMODULE

    Lee Justice
  • Thanks for your input, but I still haven't come closer to a solution. The idea from my side was to be able to replace existing WaitUntil instructions with "MyOwn_WaitUntil", a procedure where I can input the exact same parameters as with a regular WaitUntil, but also be able to add my own code aswell. In my case this would be for example to tell a PLC what the robot is waiting for using a group output.

    This is all fine, except for the input parameter "Condition" that is not being updated with the actual value.
    In the example below I have not found a way to always get the updated value of (bFixturesReady=TRUE AND diSignal1=1) inside the proc. INOUT and VAR would work if I always just used a bool and nothing else. The same for signaldi, I could get this to work aswell. But the idea was to make a general procedure to manage all sorts of conditions.

    Anyone have any more ideas?

    MyOwn_WaitUntil bFixtureReady=TRUE AND diSignal1=1\MaxTime:=5\Visualize\Message:=""Waiting for Signal"

  • lemster68
    lemster68 ✭✭✭
    That was why I had originally suggested making it a function.
    Lee Justice
  • This is not what you asked, but this is how I have solved it previously. 
        PROC MyProc()
            !Do pre-job
            WaitUntil AwaitCondition(diSensor1=1);
            WaitUntil AwaitCondition(boolMotorRunning=TRUE);
            !Do post-job
        ENDPROC
        
        FUNC bool AwaitCondition(bool Cond)
            !Condition is true, return true and continue program.
            IF Cond = TRUE RETURN TRUE;
            !Condition is false, execute logic while waiting
            !
            ! - DO OTHER STUFF - !
            !
            RETURN FALSE;
        ENDFUNC
    You can then handle:
    \<span>num MaxTime\INOUT bool TimeFlag</span>
    in the regular WaitUntil instruction. 

    As long as the condition is false your "DO OTHER STUFF" will execute. 
    When condition is true program will continue. 
    You can use any condition with this function. 
    Systemintegrator - Web / C# / Rapid / Robotstudio

    If I helped, please press Vote Up  :smile:

    ☑️2024 - RobotStudio® User Group