You are not registered yet. Please click here to register!


 
 
plc storereviewsdownloads
This board is for PLC Related Q&A ONLY. Please DON'T use it for advertising, etc.
 
Try our online PLC Simulator- FREE.  Click here now to try it.

New Here? Please read this important info!!!


Go Back   PLCS.net - Interactive Q & A > PLCS.net - Interactive Q & A > LIVE PLC Questions And Answers

Reply
 
Thread Tools Display Modes
Old December 10th, 2019, 01:29 PM   #1
Lucask
Member
Denmark

Lucask is offline
 
Join Date: Apr 2017
Location: Jutland
Posts: 13
Structured text

Hi,

I'm trying to get some good habits regarding structured text.

So that's why I'm looking for some info from others with experience in that area.

I've added a small program where the same output is controlled in each step (or where it is needed)

Would you handle it like this.

Case Istate of

0:
Motor1:=FALSE;

IF Statement_1 then
Istate:=10;
END_IF

10:
Motor1:=TRUE;

IF Statement_2 then
Istate:=20;
END_IF

20:
Motor1:=FALSE;

IF Statement_3 then
Istate:=30;
END_IF

30:
Motor1:=TRUE;

And so on...

End_Case

Or more like when making a Ladder program, where the output is only set one place, and then controlled by the steps.

Like this:

If Istate = 10 OR Istate = 30 then
Motor1:=TRUE;
ELSE Motor1:=FALSE;


Thanks!
  Reply With Quote
Old December 10th, 2019, 02:12 PM   #2
AustralIan
Member
Germany

AustralIan is offline
 
Join Date: Jan 2013
Location: Germany
Posts: 1,144
1st way is easier to follow the sequence.
2nd way is easier to trace back an output.

Be consistent.

I prefer the second way.

But your if else statement is better as:
Motor1 := ( Istate = 10 ) OR ( Istate = 30 ) ;

Also, if your controller supports ENUM you should definitely use them instead of numbers.
  Reply With Quote
Old December 10th, 2019, 02:14 PM   #3
Jobbe9000
Member
Denmark

Jobbe9000 is offline
 
Join Date: Dec 2011
Location: Esbjerg
Posts: 33
Well..... Both ways will work.
Personally i prefer the first way you do it.
In case you had 50 steps where you would set Motor1 to true, the if statement would be quite a hassle to look at.

Both ways will work fine though.
Some people will tell you to be consistent with the way you choose.. some people will tell you to use the best way suited in the specific case.

Instead of choosing which of the 2 ways to do it, I would focus more on your layout of the code.

1: Use indentation

IF bStatement1 THEN
bOutput1 := TRUE;
ELSE
bOutput1 := FALSE;
END_IF;

2: Keep Keywords in either lower case or UPPER case

3: Keep consistent naming of your tags.
In the example code your example you use prefix Istate and not on Statement_1

In my case iState looks more readable to me.... but that is because i use lower camel case tag naming myself.

4: Use constants for state names in your case statement, instead of 10, use a constant with a value of 10. This makes it easier to read, and you wont end up having to change "10" a thousand places in case you end up needing to change the state number.

5: Use a have a init or reset step, where all tags set in the statemachine is reset to their initial values.

Take a look at PlcOpen's programming guidelines.
It is really good reading.
  Reply With Quote
Old December 10th, 2019, 02:35 PM   #4
Engineer_MG
Member
United States

Engineer_MG is offline
 
Engineer_MG's Avatar
 
Join Date: Mar 2012
Location: USA
Posts: 77
For simple boolean control the second way is better.

I use CASE for complicated sequences, benefits

1. You can store last active step (good for debugging in a sequence and restarting conditions)

2. Jump to a defined step when there is a global alarm
etc.

Sample as below ( I copied this from my PLC code so the formatting is messed up in this page):


IF g_xMachineAlarm THEN
g_iSequencer := 999;
END_IF

CASE g_iSequencer OF

0: // Wait for Run execute
g_iLastSequencerStep := 0;

IF g_xRunExecute THEN
g_istepNumExe := 1; // Always start from 1
g_iSequencer := 10;
END_IF

10: // Store current step of the program

g_iLastSequencerStep := 10;

g_iCurrentActiveStep := g_iStepNumExe;
g_iSequencer := 20;

20: // Check Jump

g_iLastSequencerStep := 20;

IF PRg_array[0].astSteps[g_iCurrentActiveStep].iJmpInt > 1 THEN // Jump active
g_iJmpFromStep := g_iCurrentActiveStep;
g_iJmpToStep := Prg_Array[0].astSteps[g_iCurrentActiveStep].iJmpInt;
g_dwCurrentJmpRepCtr := Prg_Array[0].astSteps[g_iJmpFromStep].iRep;
g_xJumpActive := TRUE;
g_iSequencer := 180;
ELSIF PRg_array[0].astSteps[g_iCurrentActiveStep].iJmpInt = 1 THEN
g_xJumpActive := FALSE; // Program end
g_iSequencer := 600;
ELSIF PRg_array[0].astSteps[g_iCurrentActiveStep].iJmpInt = 0 THEN // No Jump , timer disable if rep > 1, timer enable = rep =1
g_dwCurrentRepCtr := Prg_Array[0].astSteps[g_iCurrentActiveStep].iRep;
g_iSequencer := 30;
END_IF



30: // No Jump , Solenoids activation, activate timer for the first time for step changeover and then disable

g_iLastSequencerStep := 30;
g_xCallSolenoidExecute := TRUE;
g_iSequencer := 35;

....

999: // Alarm active, resets

END_CASE

Thanks.



Quote:
Originally Posted by Lucask View Post
Hi,

I'm trying to get some good habits regarding structured text.

So that's why I'm looking for some info from others with experience in that area.

I've added a small program where the same output is controlled in each step (or where it is needed)

Would you handle it like this.

Case Istate of

0:
Motor1:=FALSE;

IF Statement_1 then
Istate:=10;
END_IF

10:
Motor1:=TRUE;

IF Statement_2 then
Istate:=20;
END_IF

20:
Motor1:=FALSE;

IF Statement_3 then
Istate:=30;
END_IF

30:
Motor1:=TRUE;

And so on...

End_Case

Or more like when making a Ladder program, where the output is only set one place, and then controlled by the steps.

Like this:

If Istate = 10 OR Istate = 30 then
Motor1:=TRUE;
ELSE Motor1:=FALSE;


Thanks!
  Reply With Quote
Old December 10th, 2019, 03:53 PM   #5
busarider29
Lifetime Supporting Member
United States

busarider29 is offline
 
Join Date: Aug 2013
Location: Midland, MI
Posts: 125
I tend to do it your first way in ST, especially if I have several variables that need to be set to different states throughout the CASE steps. It's just easier from a programming standpoint and also when stepping through the CASE for debugging.

I know setting something to TRUE/FALSE should be done in one place, like in LD, but from my experience, it's not always very practical in ST.
  Reply With Quote
Old December 10th, 2019, 04:59 PM   #6
James Mcquade
Member
United States

James Mcquade is offline
 
Join Date: Oct 2007
Location: Tennessee
Posts: 2,832
Welcome to the forum.

I am not sure what your application will be, but; please remember who your end user is when programming a plc. It is maintenance. you need to know what their capabilities are in regards to programming and what they are used to.

james
  Reply With Quote
Old December 10th, 2019, 05:39 PM   #7
CapinWinky
Member
United States

CapinWinky is offline
 
CapinWinky's Avatar
 
Join Date: Aug 2011
Location: Virginia
Posts: 547
I've done a lot of state machines for a lot of different kinds of machines and processes. I've settled on setting/unsetting statuses and outputs in each state. I also check in each state if the command that got me in there is still active and if not, I bail back out to the wait state. This does make each of my states have some copied lines in overhead, but it provides maximum flexibility and readability, which has proven more important on a regular basis.

Setting outputs at the end of the state machine based on the active state is simply too hard to follow when state machines get large and it inevitably requires additional conditions besides just the state number if reaction time is a factor. There is a way around the reaction time issue that is fairly clever, but I don't particularly like it. Here is an example (I don't do this):

20..25: //This state code will work for states 20 to 25
<Some Code>
IF(MyCondition) Then
MyState:=21;
END_IF
<SomeCode>


MyOutput:= (MyState=5) OR (MyState=21);

This lets you turn on the output the same scan your condition is true instead of waiting a scan to go the next state.


Instead, I just do stuff like this:

20: //Wait to do the thing state
StatusDoingThing:= 0;
IF(DoTheThing) Then
MyState:= 25;
TheThing.DoIt:= 1;
END_IF

25: //Do the thing
StatusDoingThing:= 1;
IF(NOT(DoTheThing)) Then
MyState:= 0;
TheThing.DoIt:= 0;
ELSE
IF(TheThing.NextStepReady) Then
TheThing.DoNextThing:= 1
MyState:= 30;
END_IF
END_IF

etc...
__________________
-----------------------------------------------------
Cycling power is a sign of weakness.
  Reply With Quote
Old December 10th, 2019, 06:41 PM   #8
janner_10
Lifetime Supporting Member
United Kingdom

janner_10 is offline
 
Join Date: Dec 2014
Location: Tewkesbury
Posts: 1,038
Use it when it's easier to, use ladder when it's easier to.

Don't be obsessed with using ST when ladder could be better.

Also Comments Comments Comments
  Reply With Quote
Old December 11th, 2019, 03:37 AM   #9
cardosocea
Member
United Kingdom

cardosocea is offline
 
Join Date: Nov 2016
Location: Fields of corn
Posts: 1,614
Quote:
Originally Posted by janner_10 View Post
Use it when it's easier to, use ladder when it's easier to.

Don't be obsessed with using ST when ladder could be better.
This is the correct answer...
  Reply With Quote
Old December 11th, 2019, 06:23 AM   #10
LadderLogic
Member
United States

LadderLogic is offline
 
LadderLogic's Avatar
 
Join Date: Jun 2003
Location: Chicagolandia
Posts: 1,371
Quote:
Originally Posted by janner_10 View Post
Don't be obsessed with using ST when ladder could be better.
The opposite is true too
__________________
Don't trust, don't fear, don't beg...
  Reply With Quote
Old December 11th, 2019, 07:12 AM   #11
ndzied1
Lifetime Supporting Member
United States

ndzied1 is offline
 
ndzied1's Avatar
 
Join Date: Aug 2002
Location: Chicago, Illinois
Posts: 2,513
For state machines I have found it very useful to define a string variable and update it for each state with the "name" of the state. For sure it's useful when debugging and also could be brought out to an HMI for describing the sequence to the operator.

I put it on the same line as the number or constant defining the start of the step and it usually takes the place of a comment I would have put there anyway.

Code:
iState: INT;
sStateName: STRING;
-----
CASE iState OF
   0: sStateName := 'Waiting for Start';
     .
     .
   1: sStateName := 'Down @ Pickup, Gripper Open';
     .
     .
   2: sStateName := 'Close Griper @ Pickup';
     .
     .
   3: sStateName := 'Raise @ Pickup, Gripper Closed';
     .
     .
   4: sStateName := 'Extend to Drop-off';
     .
     .
   5: sStateName := 'Lower @ Drop-off';
     .
     .
     .
     .

END_CASE
__________________
nOrM
======================
nOrM=Norman Dziedzic Jr.
I've never been to China but my phone has.
  Reply With Quote
Old December 11th, 2019, 07:25 AM   #12
ndzied1
Lifetime Supporting Member
United States

ndzied1 is offline
 
ndzied1's Avatar
 
Join Date: Aug 2002
Location: Chicago, Illinois
Posts: 2,513
You can write an entire IF/THEN statement on a single line if the conditions are short and it makes sense. It can sometimes encapsulate the idea of what you are trying to do in a cleaner fashion than 3 separate lines. BUT, it's not for everything.

Here are lines doing an analog conversion for some flow meters. Vibration on the machine means that when there is no flow, the pickups still get some signal and show a very small flow. Forcing these small values to zero does not effect the process and makes the HMI clearer for the operators.

Code:
InputFlow[0]     := AnalogConversion(FM3,20000,4000,15.85,0.0);
IF InputFlow[0]  < MIN_FLOW THEN InputFlow[0]  := 0.0; END_IF;

OutputFlow[0]    := AnalogConversion(FM4,20000,4000,15.85,0.0);
IF OutputFlow[0] < MIN_FLOW THEN OutputFlow[0] := 0.0; END_IF;

InputFlow[1]     := AnalogConversion(FM1,20000,4000,15.85,0.0);
IF InputFlow[1]  < MIN_FLOW THEN InputFlow[1]  := 0.0; END_IF;

OutputFlow[1]    := AnalogConversion(FM2,20000,4000,15.85,0.0);
IF OutputFlow[1] < MIN_FLOW THEN OutputFlow[1] := 0.0; END_IF;
__________________
nOrM
======================
nOrM=Norman Dziedzic Jr.
I've never been to China but my phone has.
  Reply With Quote
Old December 11th, 2019, 09:01 AM   #13
theColonel26
Lifetime Supporting Member
United States

theColonel26 is offline
 
theColonel26's Avatar
 
Join Date: Feb 2014
Location: West Michigan
Posts: 380
Quote:
Originally Posted by AustralIan View Post
1st way is easier to follow the sequence.
2nd way is easier to trace back an output.

Be consistent.

I prefer the second way.

But your if else statement is better as:
Motor1 := ( Istate = 10 ) OR ( Istate = 30 ) ;

Also, if your controller supports ENUM you should definitely use them instead of numbers.
Yes be Consistent
ENUM +1000

Quote:
Originally Posted by Jobbe9000 View Post
Well..... Both ways will work.
Personally i prefer the first way you do it.
In case you had 50 steps where you would set Motor1 to true, the if statement would be quite a hassle to look at.

Both ways will work fine though.
Some people will tell you to be consistent with the way you choose.. some people will tell you to use the best way suited in the specific case.

Instead of choosing which of the 2 ways to do it, I would focus more on your layout of the code.

1: Use indentation

IF bStatement1 THEN
bOutput1 := TRUE;
ELSE
bOutput1 := FALSE;
END_IF;

2: Keep Keywords in either lower case or UPPER case

3: Keep consistent naming of your tags.
In the example code your example you use prefix Istate and not on Statement_1

In my case iState looks more readable to me.... but that is because i use lower camel case tag naming myself.

4: Use constants for state names in your case statement, instead of 10, use a constant with a value of 10. This makes it easier to read, and you wont end up having to change "10" a thousand places in case you end up needing to change the state number.

5: Use a have a init or reset step, where all tags set in the statemachine is reset to their initial values.

Take a look at PlcOpen's programming guidelines.
It is really good reading.


Quote:
Originally Posted by James Mcquade View Post
Welcome to the forum.

I am not sure what your application will be, but; please remember who your end user is when programming a plc. It is maintenance. you need to know what their capabilities are in regards to programming and what they are used to.

james
Wrong, this kind of mind set is how we end up with such terribly written PLC code in the US. You should write code for other competent PLC programmers to understand. That doesn't mean make an inconsistent mess with a whole lot of "clever" logic, but it does mean take full advantage of the Programming tools that the environment provides you and try to maintain good DRY (Don't Repeat Yourself) and SOC (Separation of Concerns) practices. I see so much code that is written by Controls "Engineers" that is a giant knot of spaghetti with glue sauce, when I try to explain DRY and SOC practices to them I might as well be speaking Klingon. Anything other than Copy/Paste throw a NO there, put a NC there is to scary to try to grasp.



I'm not a degree-ed Engineer (no BS in Engineering that is), but I do consider myself to be an engineer. Engineering is a mind set and a way of thinking. I have encounters controls engineers that have real Engineering Degrees and I don't consider them engineers because they create messes.


This topic may need it's own thread.


Quote:
Originally Posted by janner_10 View Post
Use it when it's easier to, use ladder when it's easier to.

Don't be obsessed with using ST when ladder could be better.

Also Comments Comments Comments
Yes

Quote:
Originally Posted by LadderLogic View Post
The opposite is true too
and yes

Quote:
Originally Posted by ndzied1 View Post
You can write an entire IF/THEN statement on a single line if the conditions are short and it makes sense.
IMO that makes it harder to read, especially if you go back and forth between styles in the same project.
  Reply With Quote
Old December 11th, 2019, 09:35 AM   #14
busarider29
Lifetime Supporting Member
United States

busarider29 is offline
 
Join Date: Aug 2013
Location: Midland, MI
Posts: 125
Quote:
Originally Posted by theColonel26 View Post
Wrong, this kind of mind set is how we end up with such terribly written PLC code in the US. You should write code for other competent PLC programmers to understand. That doesn't mean make an inconsistent mess with a whole lot of "clever" logic, but it does mean take full advantage of the Programming tools that the environment provides you
With the risk of high-jacking this thread, I whole-heartily agree with the above. Take advantage of the tools that are provided, including the programming languages. Use the language that is best for the routine you're coding.

"Keep the maintenance people in mind when writing PLC code" is essentially implying to write it all in LD so the maintenance people can understand. If one cannot understand IF_THEN_ELSE, then that person should be nowhere near the PLC in my opinion. It's written in plain English (IF_THEN_ELSE). How much easier does it need to be? Okay, so you might have to learn what a CASE statement is and a FOR loop. No different than the numerous instructions outside of a XIC, XIO, and OTE in a RSLogix ladder program that one had to learn!
  Reply With Quote
Old December 11th, 2019, 10:03 AM   #15
ndzied1
Lifetime Supporting Member
United States

ndzied1 is offline
 
ndzied1's Avatar
 
Join Date: Aug 2002
Location: Chicago, Illinois
Posts: 2,513
Quote:
Originally Posted by theColonel26 View Post
IMO that makes it harder to read, especially if you go back and forth between styles in the same project.
Stylistic choice I guess. As I said, it's not for everything.
__________________
nOrM
======================
nOrM=Norman Dziedzic Jr.
I've never been to China but my phone has.
  Reply With Quote
Reply
Jump to Live PLC Question and Answer Forum

Bookmarks


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

Similar Topics
Thread Thread Starter Forum Replies Last Post
MSG Instruction via Structured Text jfd7851 LIVE PLC Questions And Answers 5 August 10th, 2016 11:15 AM
Structured text in factorytalk view studio? Crailberry LIVE PLC Questions And Answers 1 July 2nd, 2016 04:05 PM
Structured Text & RSLogix - good reference books & docs? ChrisOfMaryland LIVE PLC Questions And Answers 4 November 4th, 2009 01:10 PM
Structured Text for automating experiments? I'm new... ChrisOfMaryland LIVE PLC Questions And Answers 1 November 4th, 2009 12:40 PM
Documentation on Structured Text cmulder LIVE PLC Questions And Answers 13 June 11th, 2003 11:10 AM


All times are GMT -4. The time now is 10:58 PM.


.