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”?

I’m not sure if it helps but have you tried INOUT ?
PROC MyOwn_WaitUntil(INOUT bool Cond\num MaxTime\INOUT bool TimeFlag)

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.

Make it a function. The TestDI function already exists for the datatype for Inputs, SignalDI.

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.

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

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”

That was why I had originally suggested making it a function.

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:

\num MaxTime\INOUT bool TimeFlag

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.