Structured text sequencing

Snap25

Lifetime Supporting Member
Join Date
Dec 2014
Location
Michigan
Posts
237
I've been using SL for all my computations, scaling, & I/O mapping. Now I want to convert a ladder logic latch and unlatch step based process..

I think I have an idea how to do it, but wanted to get some advice on the best way to do it. I know there our multiple ways to do it and there necessarily a right or wrong way of doing things.. but there is definitely better ways than others!

Does anyone care to share any 5000 projects with a few SL routines?
 
Before I read any of the replies, I was playing around with some ideas last night. Here is a generic example..

(* System will pump out of the tank and will utilized a variety of different valves depending on the stage of the pump out. *)

IF system_auto & NOT system_alarm THEN
filter_steps [:=] 1;
filter_active [:=] 1;

END_IF;

IF filter_steps = 1 & level_sensor < tank_level_A_sp THEN
filter_steps := 2;

ELSIF filter_steps = 2 & level_sensor < tank_level_B_sp THEN
filter_steps : 3;

ELSIF filter_steps = 3 & level_sensor < tank_level_C_sp THEN
filter_steps : 0;
filter_active : 0;

END_IF;


IF filter_active = 1 THEN


CASE filter_steps OF

1,2,3: valve33 & valve34 & pump1;
2: valve50;
3: valve60 & valve61;

END_CASE;

ELSIF system_alarm OR NOT system_auto THEN
filter_active :=0;

END_IF;




Would something like this be efficient? I'm not familiar with machine state instruction, I'll have to find it in the help notes.
 
Well, I found all the (ST)equipment phase instructions.. Looks like I'm going to spend all day reading!

Anyone have any of these instructions in a project they would like to share?
 
Is there a reason you're using a non-retentive assignment for step 1 and a retentive assignment for step 2? (and I assume steps 2 and 3, you're missing some syntax.)
 
This led me to another question regarding the CASE...OF construct.

Does it only execute one selector path at a time?

Example : I'm need "valve33", "valve34", & "pump1" to be true during all 3 paths during the construct. My initiate thought was to not enter certain valves multiple times if I needed them true during multiple selectors. Will it this work this way?

CASE filter_steps OF

1,2,3: valve33 :=1 & valve34 :=1 & pump1 :=1;
2: valve50 :=1;
3: valve60 & valve61 :=1;

ELSE valve33 :=0 & valve34 :=0 & pump1 :=0; valve50 :=0; valve60 & valve61 :=0;

END_CASE;


Or do I need to do it format the text like this ...


CASE filter_steps OF

1: valve33 :=1 & valve34:=1 & pump1:=1;
2: valve50 :=1;valve33 :=1 & valve34 :=1 & pump1 :=1;
3: valve60 :=1 & valve61 :=1 ;;valve33 :=1 & valve34 :=1 & pump1 :=1;

ELSE valve33 :=0 & valve34 :=0 & pump1 :=0; valve50 :=0; valve60 & valve61 :=0;


END_CASE;
 
It's easier to understand if you do something like below.

It's not identical in function to what you had but just an example.
filter_active would control if the sequence is running or not. If it's not running the pump is stopped.

You'll start the sequence by setting filter_steps:=1 in auto.

If you get a system alarm you'll still stay in the same sequence step (pump stops). Sequence will then continues from where it was after alarm condition is cleared.

Code:
[COLOR=SeaGreen]// Alarm? Stop sequence![/COLOR]
[B]if [/B]system_alarm [B]then[/B]
   filter_active:=0;
[B]end_if;[/B]

[COLOR=SeaGreen]// Manual? Stop and reset filter![/COLOR]
[B]if [/B]not system_auto [B]then[/B]
   filter_steps:=0; filter_active:=0;
[B]end_if;[/B]

[COLOR=SeaGreen]// are we running sequence?[/COLOR]
[B]if[/B] filter_active>0 [B]then[/B]

   [B]case [/B]filter_steps [B]of[/B]
      0  : [COLOR=SeaGreen]// wait for start[/COLOR]
           pump1:=false;

      1  : [COLOR=SeaGreen]// set valves and start pump[/COLOR]
           valve33:=true;  valve34:=true;
           valve50:=false; valve60:=false; valve61:=false;
           pump1:=true;
           
           [COLOR=SeaGreen]// wait for level to sink[/COLOR]
           [B]if [/B]level_sensor < tank_level_A_sp [B]then[/B]
              filter_steps:=2;
           [B]end_if;[/B]
           
      2  : [COLOR=SeaGreen]// change valves[/COLOR]
           valve50:=true;
           valve33:=false; valve34:=false;
           valve60:=false; valve61:=false;
           pump1:=true;

           [COLOR=SeaGreen]// wait for level to sink[/COLOR]
           [B]if [/B]level_sensor < tank_level_B_sp [B]then[/B]
              filter_steps:=3;
           [B]end_if;[/B]

      3  : [COLOR=SeaGreen]// change valves[/COLOR]
           valve60:=true;   valve61:=true;
           valve33:=false;  valve34:=false;
           valve50:=false;
           pump1:=true;

           [COLOR=SeaGreen]// wait for level to sink[/COLOR]
           [B]if [/B]level_sensor < tank_level_C_sp [B]then[/B]
              filter_steps:=0; [COLOR=SeaGreen]// we are done[/COLOR]
           [B]end_if;[/B]
[B]    end_case;[/B]

[B]else[/B]
   [COLOR=SeaGreen]// stop pump when sequence is not running[/COLOR]
   pump1:=false;

[B] end_if;[/B]

PS. CASE statements are the same as a bunch of

if x=1 then
...
elsif x=2 then
...
elseif x>=3 and x<=5 then
...
else
...
end_if;

The first IF statement that is true will be executed.
 
Last edited:
If you wanted to do this (which I don't recommend)
Code:
CASE filter_steps OF
1: valve33 :=1 & valve34:=1 & pump1:=1;
 2: valve50 :=1;valve33 :=1 & valve34 :=1  & pump1 :=1;
 3: valve60 :=1 & valve61 :=1 ;;valve33 :=1 & valve34 :=1  & pump1 :=1;

ELSE valve33 :=0 & valve34 :=0 & pump1 :=0; valve50 :=0; valve60 & valve61 :=0;
END_CASE;
You'll do it like this:

Code:
pump1   := (filter_steps>=1 and filter_steps<=3);
valve33 := (filter_steps>=1 and filter_steps<=3);
valve34 := (filter_steps>=1 and filter_steps<=3);
valve50 := (filter_steps=2);
valve60 := (filter_steps=3);
valve61 := (filter_steps=3);
The pump or values will go true/false depending on the value of the filter_steps.
It's often easier to use bools to represent on/off states.

If you wanted to use integers though, it would be best to make your own function for start/stop or open/close.
For instance a function (called SetX to set pumps and valves) that returns 1 for true and 0 for false.

Code:
pump1     := SetX(filter_steps>=1 and filter_steps<=3);
valve33 := SetX(filter_steps>=1 and filter_steps<=3);
 
Last edited:
Your logic doesn't work. You can never change to step 3 or step 0.
If I understand what you want, it is much simple to get rid of all the if statements and the case statements. Assuming that you are trying to run all pumps when the level is above a low level, and open different valves when between low and medium, and medium and high


Active := Auto & not Alarm
Valve33 := Valve34 := Pump:= Active & (Level > Low)
Valve60 := Valve61 := Active & (Level > Low) & (Level < Med)
valve50 := Active & (Level > Medium) & (Level < High)
 
I think you may want to stick with If-Then type of arrangement so that its easy to troubleshoot for someone down the line.

There are 100 ways to implement the same logic, but it pays dividends if its easily understood.
 
I think you may want to stick with If-Then type of arrangement so that its easy to troubleshoot for someone down the line.

Please explain why If-Then logic is easy to troubleshoot. In the example I gave, the four lines seem very easy for me to follow, and I would expect that someone competent in the art would also be able to follow it fairly easily. In the examples given using an if-then to set bits and the top, then later on an if-then to reset a bit, to me, that is harder to follow and figure out what the intent of the logic is supposed to be doing. Likewise, for the logic in the middle, setting tags using if-then if they meet the condition, then using if-then to reset tag later for a condition that is contrary to the first condition seems much harder to follow, than using logic that determines the condition in one concise line.
 
Alright,

I'm with you on determining a result with one line of code instead of doing set/reset arrangement. However you can still use a If-Then to step through a sequence and then enable outputs based on the sequence value at the end. Never been a big fan of set/reset.

The way you arranged the code is obvious and makes sense to you, and it sounds like you spend a lot of time programming.

For the person who doesn't spend every day programming, like a maintenance tech, your version is probably not so obvious. Shoot maybe it is, but I would probably tend to bet on not having the best and brightest.

My main point is that SCL is newer anyway, and for the person that's jumping into it having worked with ladder their whole career(because ladder is still very popular). Seeing some familiar terms that are based on common language may help them and save some time.
 
I think you may want to stick with If-Then type of arrangement so that its easy to troubleshoot for someone down the line.

There are 100 ways to implement the same logic, but it pays dividends if its easily understood.

I agree, there are a 100 ways to write the same sequence. Although Proofs code looks good and will get the job done, I personality like Petes code.

Personal preference I guess... I can process what's going on a little more clearly.
 

Similar Topics

I have an expression in a structured text routine of a Logix controller that looks more or less like the following: ResultInteger := Integer1 *...
Replies
13
Views
389
Good evening. I display the step number of a SFC on a display. Sometimes, on a trip, it goes quickly through many steps and I need to prove to...
Replies
1
Views
129
I am trying to set up a piece of equipment with a Horner HE-X4R. I'd like to use structured text and so far I'm just trying to get a basic On/off...
Replies
0
Views
70
Good morning. I'm doing a rehab and I need to recycle some part of the old code that won't change and that I need. This is a calculation that...
Replies
22
Views
1,362
I'm writing some structured text that's handling a data structure that comes from a PC. The PC structure is in the "new" LREAL 64-bit floating...
Replies
3
Views
488
Back
Top Bottom