Case statement

sarathbabu
2012-05-02
2012-09-20
  • sarathbabu - 2012-05-02

    In Case statement

    case integer of
    1..n:
    end_case
    where n is an integer
    It is showing error,when am building it

    I need to execute the sequence 10 times if n=10,but n is a configurable value by the user it can be an integer.

    Can any one help me on this?

     
  • kberlin - 2012-05-02

    Hello,

    If it's the same sequence that you would like to do N times I would instead recommend a FOR-case. Something like:

    i: INT;
    MaxCount: INT;
    aThings: ARRAY [0..100] OF INT;
    xDoIt: BOOL;
    IF xDoIt THEN
      FOR i := 1 TO MaxCount DO
        aThings[i] := i;
      END_FOR
      xDoIt := FALSE;
    END_IF
    

    The above code will fill the array aThings up to index MaxCount when the BOOL xDoIt is set to TRUE.

    I hope this helps.

    Best regards,
    Kristian Berlin

     
  • sarathbabu - 2012-05-03

    Hi Berlin

    Thanks for the reply

    1).I have lot of timers and I have to reset them when repeating the sequence.

    2).for loop is too fast it is finishing the count in no time,for 1 sequence.

    3).There is no jump statement ST Language,so I went for case statement.

    Below is my Code:

    IF g_TIU[i_TiuNo].HeaterTest.bTest THEN
    tofdelay(in:=NOT tofdelay.Q AND g_TIU[i_TiuNo].HeaterTest.bTest AND i=0 ,pt:=t#1s);
    btofdelay:=tofdelay.Q;

    IF NOT bdelay THEN
    g_TIU[i_TiuNo].STICScriptNo:=eTempset;
    END_IF

    IF btofdelay OR bdelay THEN
    p_TIU[i_TiuNo].bSTICRunScriptHeater:=TRUE;
    ELSE
    p_TIU[i_TiuNo].bSTICRunScriptHeater:=FALSE;
    END_IF

    IF (g_TIU[i_TiuNo].STICScriptNo=31 AND i=0) THEN
    (RsScript(SET:=p_TIU[i_TiuNo].bSTICRunScriptHeater,RESET1:=g_TIU[i_TiuNo].STICRunScript);
    g_TIU[i_TiuNo].STICRunScript:=RsScript.Q1;
    )
    i:=i+1;
    END_IF

    (*RsScript(SET:=p_TIU[i_TiuNo].bSTICRunScriptHeater,RESET1:=g_TIU[i_TiuNo].STICRunScript);
    g_TIU[i_TiuNo].STICRunScript:=RsScript.Q1;*)
    

    IF i=1 THEN
    tondelay(in:=NOT tondelay.Q AND NOT bdelay AND TRUE,pt:=r_TCUConfig[i_TiuNo].TIUHeaterTimer);
    bdelay:=tondelay.Q;
    END_IF
    currenttime:=tondelay.ET;
    IF bdelay THEN

    g_TIU[i_TiuNo].STICScriptNo:=eTempget;
    i:=i+1;
    

    END_IF

    IF btofdelay OR bdelay THEN
    p_TIU[i_TiuNo].bSTICRunScriptHeater:=TRUE;
    ELSE
    p_TIU[i_TiuNo].bSTICRunScriptHeater:=FALSE;
    END_IF

    (RsScript(SET:=p_TIU[i_TiuNo].bSTICRunScriptHeater ,RESET1:=g_TIU[i_TiuNo].STICRunScript);
    g_TIU[i_TiuNo].STICRunScript:=RsScript.Q1;
    )

    IF i=15 THEN

    (RsScript(SET:=p_TIU[i_TiuNo].bSTICRunScriptHeater ,RESET1:=g_TIU[i_TiuNo].STICRunScript);)
    p_tiu[i_tiuno].bHeaterTestCompleted:=TRUE;

    END_IF

    END_IF

    I have to repeat the above sequence by 'n' times based on users input

     
  • kberlin - 2012-05-03

    How about adding a counter that you increment by one every time you've done the sequence and and IF-case to see if you have performed the sequence enough times?

     
  • shooter - 2012-05-03

    gooday sarathbabu
    Your code will not work, probably as the timers are every loop starting.

    Case statement can be used here, however for or do while is better here probably.
    please give us a flowdiagram what you want. because the code used by you is very garbled.
    if you have to test on a timer use this timers output. timeron.q and timeroff.q
    you can not use timers inside a array, however you can use RTC in an array.
    something like it takes 5000 msec for step 1 use array[1]:=5000
    if starttime > arraytime + RTC do something.
    this way you keep the times correct, with timers it is not very precise (takes about 10 msec)

     

    Related

    Talk.ru: 1

  • sarathbabu - 2012-05-04

    Hi Berlin

    1).If I keep counter with in FOR loop it is executing the sequence once and the counter is updated with in that time,before the sequence go to start.

    2).I need to reset the timers also before it goes to start.

    Hi Shooter

    1).Please find the attached image for the flow.It is too simple but timers reset and 'n' times repetition of the sequence are the critical part.

    IMG: seq.JPG

     
  • shooter - 2012-05-04

    your bit A is still on after 20 seconds
    but i made a program exactly as yours is.
    i made it in SFC to follow your flow.

    20120505.pro [26.51 KiB]

     
  • sarathbabu - 2012-05-04

    Hi,

    1).SFC is solving the problem.

    2).Any reason why cannot we use FOR loop for this kind of sequence?

     
  • shooter - 2012-05-04

    For is also possible, but when you draw a simple flowchart it is easier to make an SFC

    with FOR you can do
    FOR a = 1 to variable
    ton1
    ton2
    next a

    i made an SFC but it is not correct, as your flowdiagram is not correct.

     
  • sarathbabu - 2012-05-04

    Hi
    1).I have corrected my flow chart.
    2).With out SFC is it possible in for loop using a counter
    Thanks

    IMG: seq.JPG

     
  • shooter - 2012-05-05

    flowchart still not correct.
    yes within a for loop it is possible, just check if timer is expired and then move on.
    use wait for this, but the program stops now.
    if you haVE MORE AS ONE PROG RUNNING THIS IS BAD PRACTICE.

     
  • sarathbabu - 2012-05-07

    Shooter,

    In the sequence k:k+1; is supposed to increment once,in the flow but it is incremented in no time with in the FOR loop.

    Attached is the flow chart

    IMG: flow.JPG

    IMG: flow.JPG

     
  • shooter - 2012-05-07

    your sequence is still not correct.
    now it is 1 second on
    20 seconds off
    2 seconds on because the third timer is followed by the first timer.
    probably you want to wait for 20 seconds again, but this you can do by jumping one step lower.
    A PLC is always looping its programs, and checks if values are true, this is to avoid a standstill somewhere in a POU and rest of machine is not controlled anymore.
    you can achieve your goal with

    WHILE NOT timer.Q DO
    nothing:=true;
    END_WHILE

     
  • sarathbabu - 2012-05-07

    Thanks for the idea.

    Hope fully this flow chart should be correct to some extent

    IMG: test2.JPG

     
  • Andreaz - 2012-09-05

    late reply, but here's an implementation in ST with a case based state machine, only one timer is needed as its used for both on and off states.

    PROGRAM POU
    VAR_INPUT
       // Start the sequence
       Start: BOOL;
       // Number of repeats
       Repeats: INT := 10;
    END_VAR
    VAR_OUTPUT
       // Output signal
       A: BOOL;
    END_VAR
    VAR
       State: WORD;
       Counter: INT;
       
       Timer: TON;
    END_VAR
    VAR CONSTANT
       STATE_START : WORD := 0;
       STATE_ON    : WORD := 1;
       STATE_OFF   : WORD := 2;
       STATE_STOP  : WORD := 3;
    END_VAR
    CASE State OF
    STATE_START:
       IF Start THEN
          Timer(IN:= FALSE);   
          
          Counter:= 0;
          State  := STATE_ON;
       END_IF
    // Puts the signal on for 1 sec
    STATE_ON:
       A:= TRUE;
       
       Timer(IN:= TRUE, PT:= T#1S);
       IF Timer.Q   THEN
          // Reset timer
          Timer(IN:= FALSE);   
          
          State  := STATE_OFF;
       END_IF
    // Put the signal off for 20 sec
    STATE_OFF:
       A:= FALSE;
       
       Timer(IN:= TRUE, PT:= T#20S);
       IF Timer.Q   THEN
          // Reset timer
          Timer(IN:= FALSE);   
          Counter:= Counter + 1;
          
          IF Counter < Repeats THEN
             State:= STATE_ON;
          ELSE
             State:= STATE_STOP;
          END_IF;
             
       END_IF
    // Done   
    STATE_STOP:
       // Wait for start signal to be removed, else the sequence will be restarted
       IF NOT Start THEN
          State:= STATE_START;
       END_IF   
       
    END_CASE
    
     
  • sarathbabu - 2012-09-10

    Hi

                Good and simple but is it possible to keep no.of repeats as a variable instead of a constant.
    

    repeat:=n;

    where n can be any integer

    Thanks

     
  • shooter - 2012-09-20

    yes the number can be a variable, but
    when you need it variable use
    While counter<endnumber do
    end_while

    in a CASE it is not possible to use a VAR for the cases.
    constants are possible

    CASE INT1 OF
    INT1 is a normal Variable of the INT type (byte etc possible.
    1, 5: BOOL1 := TRUE;
    above 1 and 5 must be a constant
    BOOL3 := FALSE;
    2: BOOL2 := FALSE;
    BOOL3 := TRUE;
    10..20: BOOL1 := TRUE;
    BOOL3:= TRUE;
    ELSE
    BOOL1 := NOT BOOL1;
    BOOL2 := BOOL1 OR BOOL2;
    END_CASE;

     

Log in to post a comment.