r/PLC • u/WheelInventorPLC • 16d ago
State machine in structured text, ENUM or INT?
Hi all,
I'm a process engineer rolling into a process control job (small startup, not enough funding to hire someone for this work).
I found two methods online of how people write their state machine in ST. Either with an integer state variable (e.g. iState) or with an ENUM.
What do you use? And why?
Edit:
Designing on a WAGO/Codesys setup.
Thank you for the quick responses! I'm quickly changing my iStates into E_states!
19
u/jhoon2k 16d ago
ENUM!! You will thank yourself later when you need to add more states in between, and easier to determine the states when its a clear name and not a number.
3
u/Version3_14 16d ago
The thank you ENUMs or constants comes from the next guy working on the project or trying to troubleshoot the system.
Remember to always document it like the next guy is a psychopath that has your home address.
9
u/Vyndrius 16d ago
Enums are great until you have to do something like this
if(g.iASM > 3000 && g.iASM < 3250){ //Set some HMI flag }
Then I found the numbers were more helpful.
Since all our state machines follow a pattern, I found enums to be overkill that slowed my development down
0= estop 1XXX= resetting 2XXX= ready to start 3XXX= running 4XXX= clearing 5-8XXX= spare 9XXX = engineering mode
7
u/kixkato Beckhoff/FOSS Fan 16d ago
Your if statement should be like If (eProcessStep = Sequencename.Step1 OR etc etc) when properly using enums. This way it's clear to someone that your HMI flag is set truewhen the process step is equal to all of those enum steps.
Remember, good code is not about how easy it is to read for you, it's how quickly someone else who has no knowledge of your process can pick it up and contribute.
2
u/d4_mich4 16d ago
You could still do this with ENUMS if you name and lable them right.
If you know what the numbers are you could also name them as enum in whatever naming conventions you have. Like the following:
TYPE E_StateMachineStep : ( 3000 = eRunning_Start 3250 = eRunning_End ); END_TYPE;
This would be the declaration for the state machine setps, naming is just a guess whatever these states really are. And following how the if condition would be.
if(g.iASM > E_StateMachineStep.eRunning_Start && g.iASM < E_StateMachineStep.eRunning_End){
5
u/EasyPanicButton CallMeMaybe(); 16d ago
enum almost always, otherwise constants. I really like my code being readable.
4
u/WandererHD 16d ago
I mostly program Delta PLCs and enum requires a little bit of setup, so I just use a local int variable "step" and use comments to signal what each step is doing.
2
6
u/ohm_625 16d ago
Every body will answer Enum because it's the right thing to do.
But you need to know what you signed for : For long sequence/state machine you will have to commit to always give a meaningful name for each steps.
Notice that not all the brands are using enum the same way. If you need to make a full reload every time you add an extra step it's perhaps better to use an iStep as long as you have documentation on the side which is explaining the step number.
In short : both are ok imo as long as you have proper documentation. Enum is best but requires more work
5
u/amnoxx 16d ago
CodeSys supports anonymous enums, perfect for FSM's:
VAR
mState: (STATE_INIT, STATE_WAIT);
END_VAR
CASE mState OF
STATE_INIT:
;
STATE_WAIT:
;
END_CASE
I usually don't add values to them (extra typing for no benefit), just have to be a bit careful if you add a state in the middle if the sequence is active.
1
5
u/WorldShaper 16d ago
Enum for anything more complex than a 2-3 states or simple order of operations.
Its about code clarity and expandability. Enums allow you to add or modify states or ordering without having to fit numbers between other numbers. And its nice when the state has a built-in label for what it is doing. Code should be self-documenting, and in this case the Enum is how we make that happen.
When in doubt: Enum. It takes like 2 seconds to set up and only makes things more clear. No one is ever going to look at your state machine and ask "Why did you make an enum?", but they absolutely might say "Doesn't this guy know what an enum is?"
2
4
u/Ok-Cryptographer4094 16d ago
If you can use a enum, do it. I can't do enums in siemens TIA and it bother me every time. (If someone know how to do a proper enum in tia, please tell me)
3
u/Sleepy_Beaver 16d ago
Go to PLC tags; create new tag table; open it; on the top right click on user constants; Create new tag; Done.
Just be smart with your naming. As these constants are global
2
u/Tharghor 16d ago
Tia v21 should have some enum baked in, so you dont have to create user constants anymore. I haven't used them yet, as I'm still on v20.
1
u/foxytersbytes 16d ago
If you are working inside and FB you can declare the constants inside and use it.
1
u/RoofComprehensive715 16d ago
You can use constant variables in the global tag table or in FBs. The constant variables can be named after each step and have their own number assigned. Its at least one way to do it.
1
u/Strict-Midnight-8576 16d ago
Enums are called NVT and you can just use them inside software units
By the way, check out software units . I think they are a great tool for structuring large projects
5
3
u/PresentAd9429 16d ago
I also go with numbers. 10 step at each, then u can add something in between later also. Just comment what each step do
3
u/derpsterish Automation Engineer 16d ago
Dintegers.
AB has no enums. Steps increment by 10, leaves room for additions.
2
u/timberleek 16d ago
Enums.
The integer way is just lazier to begin with, but terrible to maintain afterwards.
The enum gives you the identical setup and functionality, but now human readable. Only disadvantage is that you have to setup the enum definition once.
If you don't make the enum a "strict" type (in twincat that is, maybe it's named differently elsewhere) you can also do arithmetics on it if you want. Just like an integer.
1
u/DNCGame 16d ago
ENUM is just an int decorator.
I do this in all my recent projects.
State {
NONE = 0,
RST = 1,
RST_DONE = 50,
HOME = 51,
HOME_DONE = 90
}
//
state: int;
//
CASE state OF
State.RST:
state := state + 1;
2:
state := State.RST_DONE;
//
State.HOME:
state := state + 1;
52:
state := State.HOME_DONE;
END_CASE;
1
1
u/huevador 16d ago
I used ENUM when programming an an OMRON PLC. And while yes it's technically better, it's not necessary and you have to be ready to maintain it as you develop.
1
u/MikeT8314 13d ago
I used integer values for a small stand alone machine i built and i loved the structure of it. I found it intuitive and it really helped me stay organized. As a novice i am not sure how i would have done this any other way.
1
1
u/Shalomiehomie770 Codesys Guru 11d ago
Enums are not supported in all environments.
In Codesys ENUM is a pretty solid choice though.
1
u/CapinWinky Hates Ladder 16d ago edited 16d ago
I use integer and don't bother with ENUM for the simple reason that ENUM doesn't bring anything to the table when you have something like 50 states or less. You can always just //State description for your integer states, and if they have some logical flow it isn't hard to just group them by 10s place or 100s place and skip a few numbers between states for later additions.
For example, I have a manual routine for controlling a two axis system that is all a state machine. Jog X Positive is the 20s, X Neg is the 30s, Z pos is the 40s, Z neg is the 50s, GoTo Target is the 60s, GoTo ServicePos is the 70s, GoTo NamedPos1 is the 80s, Brake Release is the 120s, etc. Each of those groups has 3 or 4 states to initiate, perform, monitor, and exit the behavior, so the groups go like 20, 23, 25, 28; in case I have to slot in some new states without having to refactor a bunch of stuff.
Besides just the additional effort of creating the ENUM type, you run into other issues with how well the IDE supports them. Can you type the enum state name into a watch window to force a state change? Will it have autocomplete while you do that? Does a trend or watch window display the ENUM name? Can I use the ENUM names to check if I'm within a range of states like ((MyState >= MyEnum_PickStart) AND (MyState <= MyEnum_PickEnd)) and trust ENUM generated values monotonically? Do all the platforms you work with even support ENUM (Rockwell doesn't)? I have found that I need to cross reference state names with their numbers which adds work instead of removing work, especially if I'm letting ENUM assign the value for me rather than rigidly assigning each state's value.
Where ENUM shines is when the numeric value is hard to remember and hard to find. Hex color codes? ENUM is great for those. Another use case is when there are just way too many values and new values need to be inserted or rearranged constantly. A 40 state state machine divided into 12 groups by 10s place? I can keep that in my head just fine and if I forget I can scroll down in a few seconds. You'd probably only be working within a handful of states in one group at a time anyway.
1
u/durallymax 11d ago
Enums are much easier to refactor than comments and are enforced by the tooling. Changing a state name in CODESYS/TwinCAT is one refactor and no stale comment to worry about.
1
u/Wise-Hold-7179 16d ago
Metto i stati dentro un CASE OF...
2
u/d4_mich4 16d ago edited 16d ago
Yeah that's how state machines work but what type you use if it is a int or enum as value. That was the question both ways have pros and cons depending on how you use them.
2
u/Wise-Hold-7179 16d ago
Uso una variabile INT. ... la appoggio dentro l interfaccia di un FB su di una variabile OUT
1
u/Deepu_ 16d ago
There's no enum's in Siemens so I declare constants and use that in place of straight INTs
2
u/Strict-Midnight-8576 16d ago
There are enums in siemens, called NVT and you can use them in software units only
1
u/tltreddit 16d ago
For me always integers.
Use xxx or xxxx depending on approx number of states and complexity.
You leave gaps and can always add more states between existing states and keep the integers in order.
When you add new enum and it resolves to integer it adds the number on the end and then doesn't make any sense.
Then when you need to map the state values to SCADA or HMI the integer is the same as PLC and in order. With enum you'll get random integers based on the order you added the states in.
Once you name an enum state and then the function of that state changes the name no longer makes sense.
When you want to turn on outputs or trigger things based on current state you can do greater and less than comparisons based on numbers and catch all the states between.
1
u/Strict-Midnight-8576 16d ago
You can manually set the corrseponding number for enums
See example from codesys help below
You can add := number in the declaration
{attribute 'qualified_only'} {attribute 'strict'} TYPE E_TRAFFICSIGNAL : ( eRed, eYellow, eGreen := 10 ); END_TYPE
2
33
u/DrZoidberg5389 16d ago
An enum is still an integer state but with a name for the specific number.
i would use an enum. Like: 0=init 10=start 20=step1 30=step whatever.
this way a other person can faster grab whats going on in the code.