RobotStudio event

Random function

I have to create a random function that generates a number between 1 and 100 and if the number is greater than 50, do one cycle, if less than another.
How can i do using rapid code?

Comments

  • lemster68
    lemster68 ✭✭✭
    You could start by posting this question in the forum category for Rapid programming.  This one is for robotstudio feedback.   :p

    Or you can try this:

    FUNC num fRandomGenerator()
          VAR num nRandom;
          VAR num nMinute;
          VAR num nSecond;
          VAR num nArrayPointer1;
          VAR num nArrayPointer2;
          ! you could also put numbers out of order within the array elements, allow duplicates if you like
          VAR num myNumArray10x10{10,10}:=[[1,2,3,4,5,6,7,8,9,10],[91,92,93,94,95,96,97,98,99,100],[21,22,23,24,25,26,27,28,29,30],[61,62,63,64,65,66,67,68,69,70]
          ,[51,52,53,54,55,56,57,58,59,60],[41,42,43,44,45,46,47,48,49,50],[31,32,33,34,35,36,37,38,39,40],[71,72,73,74,75,76,77,78,79,80]
          ,[81,82,83,84,85,86,87,88,89,90],[11,12,13,14,15,16,17,18,19,20]];
          ! Random number generation based on minutes and seconds of system time
          nMinute:=GetTime(\Min);      
          nSecond:=GetTime(\Sec);
          IF nMinute = 0 THEN
            ! Cannot point to array index 0, will cause array index out of bounds
            nArrayPointer1 := 1;
          ELSEIF nMinute >= 1 AND nMinute <= 6 THEN
            nArrayPointer1 := 1;
          ELSEIF nMinute >= 7 AND nMinute <= 12 THEN
            nArrayPointer1 := 2;
          ELSEIF nMinute >= 13 AND nMinute <= 18 THEN
            nArrayPointer1 := 3;
          ELSEIF nMinute >= 19 AND nMinute <= 24 THEN
            nArrayPointer1 := 4;
          ELSEIF nMinute >= 25 AND nMinute <= 30 THEN
            nArrayPointer1 := 5;
          ELSEIF nMinute >= 31 AND nMinute <= 36 THEN
            nArrayPointer1 := 6;
          ELSEIF nMinute >= 37 AND nMinute <= 42 THEN
            nArrayPointer1 := 7;
          ELSEIF nMinute >= 43 AND nMinute <= 48 THEN
            nArrayPointer1 := 8;
          ELSEIF nMinute >= 49 AND nMinute <= 54 THEN
            nArrayPointer1 := 9;
          ELSEIF nMinute >= 55 AND nMinute <= 60 THEN
            nArrayPointer1 := 10;
          ENDIF
          IF nSecond = 0 THEN
            ! Cannot point to array index 0, will cause array index out of bounds
            nArrayPointer2 := 1;
          ELSEIF nSecond >= 1 AND nSecond <= 6 THEN
            nArrayPointer2 := 1;
          ELSEIF nSecond >= 7 AND nSecond <= 12 THEN
            nArrayPointer2 := 2;
          ELSEIF nSecond >= 13 AND nSecond <= 18 THEN
            nArrayPointer2 := 3;
          ELSEIF nSecond >= 19 AND nSecond <= 24 THEN
            nArrayPointer2 := 4;
          ELSEIF nSecond >= 25 AND nSecond <= 30 THEN
            nArrayPointer2 := 5;
          ELSEIF nSecond >= 31 AND nSecond <= 36 THEN
            nArrayPointer2 := 6;
          ELSEIF nSecond >= 37 AND nSecond <= 42 THEN
            nArrayPointer2 := 7;
          ELSEIF nSecond >= 43 AND nSecond <= 48 THEN
            nArrayPointer2 := 8;
          ELSEIF nSecond >= 49 AND nSecond <= 54 THEN
            nArrayPointer2 := 9;
          ELSEIF nSecond >= 55 AND nSecond <= 60 THEN
            nArrayPointer2 := 10;
          ENDIF
          nRandom:=myNumArray10x10{nArrayPointer1,nArrayPointer2};
          RETURN nRandom;      
        ENDFUNC
    

    I just put it together, it is yet untested, should work.
    Lee Justice
  • lemster68
    lemster68 ✭✭✭
    I have been testing, it works.  I like it better with the array jumbled up, like this:

    VAR num myNumArray10x10{10,10}:=[[51,22,3,14,5,86,77,8,29,70],[91,42,93,74,95,16,97,38,99,90],[21,2,23,24,35,26,37,28,9,30],[61,72,83,84,65,76,67,18,79,50]
          ,[1,12,33,54,75,36,57,88,59,40],[41,92,43,34,45,46,17,78,49,80],[31,82,53,44,25,56,27,98,19,20],[71,62,13,94,55,66,7,48,69,10]
          ,[81,32,63,4,85,6,87,58,89,100],[11,52,73,64,15,96,47,68,39,60]];
    


    Lee Justice
  • DenisFR
    DenisFR ✭✭✭
    edited June 2020
    Hello,
    Here, what I use:
      !To get Ramdom more random
      LOCAL VAR num callCount;

      !Get a random number between 0 and 1
      LOCAL FUNC num RANDOM()
        VAR num val:=1;
      
        var pos pos_current;
        pos_current := CPos(\Tool:=tool0 \WObj:=wobj0);
        !
        !1 seeding, Seed by position
        val:=val*(Abs(ROUND(pos_current.x*100, \Dec:=0)) +1); !+1 to avoid mul by 0 scenario
        val := 789 + val MOD 1000; !777 is just a bogus valu, since the mod might give 0
        !
        !Feel free to seed with y,z, more
        !
        !2. seeding, Seed by time
        val :=val * ( GetTime(\Sec)+1);
        val :=val * ( GetTime(\Min)+1);
        !
        !3 seeding, increment callcount and handle large number
        callCount := callCount +1;
        IF callCount > 1000 THEN
            callCount := 234;
        ENDIF
        !
        !finally a division to get something interesting large float number
        val := val / callCount;
        !
        !get a value between 0 and 1 using COS ( math)
        RETURN (0.5 + COS(val)/2);
        !
      ENDFUNC

  • lemster68
    lemster68 ✭✭✭
    I made a revision so that the numbers used are tracked, therefore using only once, until all have been used.  Then it will be reset.

    MODULE RANDOM_GEN
        ! REV 1, added bool array to track numbers already used, no duplicates.
        ! Added counter for total of numbers used
        ! Boolean array to keep track of which numbers have been used
        PERS bool bUsedArray{10,10}:=[[TRUE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE],[TRUE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE]
        ,[TRUE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE],[FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE],[FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE]
        ,[FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE],[FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE],[FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE]
        ,[FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE],[FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE]];
        ! Counter for how many total numbers, number range.  In this case, 1-100
        PERS num nNumbersUsed;
        
        FUNC num fRandomGenerator()
          VAR num nRandom;
          VAR num nMinute;
          VAR num nSecond;
          VAR num nArrayPointer1;
          VAR num nArrayPointer2;
          CONST num myNumArray10x10{10,10}:=[[51,22,83,14,5,86,77,8,29,70],[91,42,93,74,45,16,87,38,99,90],[21,2,23,24,35,26,37,28,89,30],[61,72,3,84,65,76,67,18,79,50]
          ,[1,12,33,54,75,36,57,88,59,40],[41,92,43,34,95,46,17,78,49,80],[31,82,53,44,25,56,27,98,19,20],[71,62,13,94,55,66,7,48,69,10]
          ,[81,32,63,4,85,6,97,58,9,100],[11,52,73,64,15,96,47,68,39,60]];
          ! Random number generation based on minutes and seconds of system time
          nMinute:=GetTime(\Min);      
          nSecond:=GetTime(\Sec);
          IF nMinute = 0 THEN
            ! Cannot point to array index 0, will cause array index out of bounds
            nArrayPointer1 := 1;
          ELSEIF nMinute >= 1 AND nMinute <= 6 THEN
            nArrayPointer1 := 1;
          ELSEIF nMinute >= 7 AND nMinute <= 12 THEN
            nArrayPointer1 := 2;
          ELSEIF nMinute >= 13 AND nMinute <= 18 THEN
            nArrayPointer1 := 3;
          ELSEIF nMinute >= 19 AND nMinute <= 24 THEN
            nArrayPointer1 := 4;
          ELSEIF nMinute >= 25 AND nMinute <= 30 THEN
            nArrayPointer1 := 5;
          ELSEIF nMinute >= 31 AND nMinute <= 36 THEN
            nArrayPointer1 := 6;
          ELSEIF nMinute >= 37 AND nMinute <= 42 THEN
            nArrayPointer1 := 7;
          ELSEIF nMinute >= 43 AND nMinute <= 48 THEN
            nArrayPointer1 := 8;
          ELSEIF nMinute >= 49 AND nMinute <= 54 THEN
            nArrayPointer1 := 9;
          ELSEIF nMinute >= 55 AND nMinute <= 60 THEN
            nArrayPointer1 := 10;
          ENDIF
          IF nSecond = 0 THEN
            ! Cannot point to array index 0, will cause array index out of bounds
            nArrayPointer2 := 1;
          ELSEIF nSecond >= 1 AND nSecond <= 6 THEN
            nArrayPointer2 := 1;
          ELSEIF nSecond >= 7 AND nSecond <= 12 THEN
            nArrayPointer2 := 2;
          ELSEIF nSecond >= 13 AND nSecond <= 18 THEN
            nArrayPointer2 := 3;
          ELSEIF nSecond >= 19 AND nSecond <= 24 THEN
            nArrayPointer2 := 4;
          ELSEIF nSecond >= 25 AND nSecond <= 30 THEN
            nArrayPointer2 := 5;
          ELSEIF nSecond >= 31 AND nSecond <= 36 THEN
            nArrayPointer2 := 6;
          ELSEIF nSecond >= 37 AND nSecond <= 42 THEN
            nArrayPointer2 := 7;
          ELSEIF nSecond >= 43 AND nSecond <= 48 THEN
            nArrayPointer2 := 8;
          ELSEIF nSecond >= 49 AND nSecond <= 54 THEN
            nArrayPointer2 := 9;
          ELSEIF nSecond >= 55 AND nSecond <= 60 THEN
            nArrayPointer2 := 10;
          ENDIF
          WHILE nRandom = 0 DO
          IF NOT bUsedArray{nArrayPointer1,nArrayPointer2} THEN
            nRandom:=myNumArray10x10{nArrayPointer1,nArrayPointer2};
            bUsedArray{nArrayPointer1,nArrayPointer2}:=TRUE;
          ELSE
            FOR i FROM 1 TO 10 DO
              FOR j FROM 1 TO 10 DO
                IF bUsedArray{i,j} = FALSE THEN
                  bUsedArray{i,j}:= TRUE;
                  nRandom:=myNumArray10x10{i,j};
                  IF (i <= 10) AND (j <= 10) THEN
                    IF nRandom = 0 STOP;
                    Incr nNumbersUsed;
                    ! all of the array positions have been used, this is the
                    ! last one, time to reset all to FALSE
                    IF nNumbersUsed = 100 ResetBool;
                    RETURN nRandom;      
                  ENDIF
                ENDIF
              ENDFOR
            ENDFOR
          ENDIF
          ENDWHILE
          IF nRandom = 0 STOP;
          Incr nNumbersUsed;
          ! all of the array positions have been used, this is the
          ! last one, time to reset all to FALSE
          IF nNumbersUsed = 100 ResetBool;
          RETURN nRandom;      
        ENDFUNC
        
        PROC testFunc()
          VAR num nTest;
          
          nTest:=fRandomGenerator();
          TPWrite "Random number generated is: "\Num:=nTest;
          WaitTime 5;
        ENDPROC
      
        PROC ResetBool()
          FOR i FROM 1 TO 10 DO
            FOR j FROM 1 TO 10 DO
              bUsedArray{i,j}:=FALSE;
            ENDFOR
          ENDFOR
          nNumbersUsed:=0;
        ENDPROC
    ENDMODULE

    Lee Justice
  • lemster68
    lemster68 ✭✭✭
    I noticed today that I left some of the bUsed array TRUE after I had been testing.  If you would like to use this code please make sure that you make them all FALSE first.  Too late for me to edit that post.  :s
    Lee Justice
  • Nowadays you can use Rand()
    -----------------
    David
    Swedish freelance ABB robot programmer