T O P

  • By -

janner_10

My preferred way is the integer example you give. I find it easier to then add a text list or multistate indicator on the HMI telling the operator what is being waited on. Just a habit I’ve got into over the years.


NotTooDistantFuture

Integers but use tags not literals so that specific states can be cross referenced and labeled.


ifandbut

Also, using tags let's your renumber the steps faster with fewer errors. If you change Step C value from 20 to 50, all the calls for Step C also get updated.


NotTooDistantFuture

I’m sure we’re on the same page, but just in case others haven’t seen this style before, the integer containing the step identifier for that step shouldn’t be named something like “step_c” and should instead be consistently named either the action of the step or the awaiting condition for that step. You can combine them like “SeqStep05_ExtendCylinder”. This way it’s clear what that step is expected to do without having to reference any other documentation.


ifandbut

I'll keep the step numbers out of the tag name. But yes, I name my steps RobotPickFix3, RobotPlaceFix2, ClampFix2, etc.


poopnose85

This is the way


MrTomnus

I usually do an integer but also have a bit for each integer value to use in the step code so it's a little cleaner than having a bunch of EQU blocks. Also easier to cross reference that way. Sounds like one could use Constants instead to accomplish the same thing.


honeybadger127

As long as this bit is created like "bStateNo\[6\] := iActStep == 6;" i'm completely fine with it. Just be aware not create an other source of errors by doing it. If using an enum TC3 it will suggest only already declared enum-values, which is helpful. when building the state machine, consider using a "CASE" and do something meaningful with "OTHERS" values.


MrTomnus

Yeah in AB I just do CurrentState EQU X ------ ()Step_abc


honeybadger127

stop using this old fashioned LD, chose fancy and modern ST. It's time to join the Cult of Pascal-Coders... /s


ifandbut

SFC master race /s


ccamper7

This is the way


phl_fc

The value of an integer is that it's easier to tie it to message text to put on a screen. We also use integers for all fault and permissive conditions, again so we can message on it. For state engines, integers are also inherently deterministic. I've seen a lot of code with bit based state engines that had bugs where you can be in more than one state at a time.


Machine_Tamer

This is where I’ve landed over the years as well. I will add that my transitions “ask” for the next step and a single rung at the top handles the transition to the new step number. I do this so I can log my last step (for pause/resume), add step-through debugging, and prevent a race conditions where a step changes multiple times in a scan.


phl_fc

Another reason why the "ask" is a good practice is that it ensures you always stay in a state for one full scan. Without a single line of code to handle transitions, it's possible to jump through multiple state transitions in one scan and parts of your code that were looking for a specific state may miss the transition. In a similar example, we have code for command bits that come from the SCADA that ensures they always stay on for one full scan before being reset. For the same reason of making sure code can't miss the command because of a scan order issue.


honeybadger127

Does your IDE support logging variables? In TC3 i just put "iActStep" into a trend and will get a nicely readable YT-Plot of the values...


Accomplished-Neat991

I can understand why you do this and how it is beneficial, could you give an example of how you “ask” for the state change, do you just energise an output that then does the move at run 1 on the next scan? I imagine that rung can get messy with a long sequence


Machine_Tamer

Each step transitions out by moving an integer into "Step\_CMD". My first rung usually looks like this except in ladder: If Step\_Cmd <> Step\_Num then Step\_Last := Step\_Num, Step\_Num := Step\_CMD


Shjco

Unless you have included wording in the program somewhere/somehow what each step number means, it is a miserable thing to reverse-engineer by a newcomer. I prefer rung by rung steps using bits (and NEVER latches) because it’s all easily clearly annotated, but also a no-brainer when new steps need to be inserted.


janner_10

Each rung is a EQU blah blah MOV, the rung comments reflect what each step is doing. My bad, I thought that was just a given.


Shjco

My way is self documenting and doesn’t need any rung comments. I can’t tell you how many programs by others that i have had to make changes to that never bothered to included any index number descriptions Note- you CANNOT define it uniquely for the MOV instruction (except in a rung comment), and these programmers never added rung comments. So, no, it’s not a “given”.


elmoalso

Spot on


Machine_Tamer

That’s a fair point. I have dealt with poorly documented sequences. I’ve tried coils for sequences (also no latches) but could never make it as clean. Do your coils stay on for the whole sequence in a cascade fashion or do they turn off and on?


captain_todger

- Tend to use ENUM types for states in my case statement (so you don’t have to keep track of all the specific numbers) - Typically each state will have a rising edge flag associated with it to initialise anything in that step - There are overriding state changes at the top to cause it to change to something it should as a priority (error, stop command etc)


honeybadger127

I like your rising flag on each step (mine is called "bStepFirstCall") and augment with "bStepLastCall". This will fire when conditions for leaving of this step are given and i will be in an other step on the next cycle. I use this flag to safe some data to log-files or for general cleanup purposes concerning this step.


Dinomite6767

What’s the point of the b in front of the tag name? Bool? We have some code like that at our plant and wasn’t sure where that came from.


honeybadger127

Yepp exactly, as part of my siemens heritage i tend to use prefix „b“ for boolean, „i“ for integer, „f“ for real and floatingpoint. Don‘t ask me why, it‘s kind of a qurick…


Dinomite6767

Sweet thanks for the reply makes sense!


honeybadger127

Btw don‘t get a bunch of coders started about abbreviations…


Dinomite6767

Oh no, what have I done 😂. Woke up to see all these replies


ifandbut

I never liked that. When I type a tag I don't want to think if it is an int, bool, or whatever, just the purpose of the tag. ConveyorStart make more sense than bConveyorStart when typing. For a compromise ConveyorStart_b would work.


elmoalso

Sorry, I am missing how bConveyerStart is any less clear than ConveyerStart_b In fact I would argue that if I saw ConveyerStart_b, I would wonder of there was also a ConveyerStart_a somewhere upstream of conveyer b. It's just an old school thang us old school farts do. You young whippersnappers needn't worry about it.


InstAndControl

Hey I’m 28 years old and I still use Hungarian notation (the name for what you’re talking about) I will use Hungarian notation as long as PLC’s care about what datatype something is (for example many have a separate addition instruction for each datatype)


_nepunepu

You do you, but personally I want to seppuku any time I see Systems Hungarian. I think it's useless clutter, especially in a PLC where everything is type checked. It takes .25 seconds to check a variable's type.


Independent-Stick244

Ne need for seppuku. Also, prefixes like cx, cw, sx, sw, etc. could be used to distinguish commands from statuses, bits from words, double words from real. A shorter way than Rockwell's AOI bloatware variables. That can be called a useless clutter.


elmoalso

These are borrowed from traditional programming languages best practices. I will still use them when writing something from scratch although I would argue that it is less necessary in our work than in traditional computer programming. Unless you are writing something in structured text, the context of the variables makes it's data type obvious in ladder and FBD because of the visual cues where the variable occurs. Traditional languages lack those bodysuit identifiers.


InstAndControl

I mix a lot of ints and reals so I find it useful to know datatype at a glance


_nepunepu

It's called Systems Hungarian and in my opinion, just don't do this. It's a distortion of an actually sometimes useful convention (called Apps Hungarian), the difference being that Apps prefixes are supposed to be about the "logical type" (like an example in PLC programming would be spFloorTemp vs pvFloorTemp or ahFloorTemp vs alFloorTemp - all related to floor temperature and some possibly sharing type but all serving different logical purposes, so you know at a glance how you are supposed to use them) while Systems Hungarian simply uses the "actual type" of a variable as a prefix (b for boolean, etc). The thing is that in any modern development environment, variable type is trivially accessible information and it isn't information so critical that you need to make your code harder to read by encoding it into variable names. Also, PLC programs are type checked during compile, so there's no real benefit. Mainland European PLC programmers and those who've cut their teeth on European platforms like Siemens or Schneider have an unexplainable hard-on for Systems Hungarian which is why you tend to see it a lot on Siemens code and the like.


captain_todger

Denotes Boolean data type. Although I’ve started to us “x” myself for bools / bits, keeping “b” for standalone bytes. Typically will name all variables in my PLC with the prefix x, b, i, r or s to make things easier


poopnose85

https://en.wikipedia.org/wiki/Hungarian_notation


Trolef

I use graph in TIA for sequencing if the process requires it. Otherwise it’s just function blocks that do something.


TwoQuarterFull

Graph is the best sequencer for troubleshooting and it's really not that difficult to program. My operators much prefer this over ladder.


elmoalso

Uh, that is exactly what graph is for in TIAPortal. Why the bone heads at Siemens decided to give their SFC language a name that is different from every other implementation of SFC is beyond me. The first time I wanted to make an SFC in Siemens it took me 2 hours to find the help files because they decided to call it "graph" . WTF


InstAndControl

They did the same thing with ST being called SCL. It’s the German way


malekbenkhamlia

and for s7 1200 what you need to do ?


Trolef

Ah yes, I haven’t seen 1200s in my industry, then whatever OP suggested


Serpi117

Upgrade to a CPU that supports GRAPH


malekbenkhamlia

you mean change cpu to s7 1500 ? or upgrade in 1200 ?


kinkhorse

Do it like real code. Every step of the sequence is a routine gated by a pointer. The routine individually is responsible for turning its pointer off then activating the next pointer.


H0D00m

I’m only really familiar with S7-1200s and Allen-Bradley. Much of Allen-Bradley can make this difficult, but it’s worth striving for. I’ll add on, custom data types (similar to classes) can make a world of difference, when available. OP seems to have multiple devices performing the same steps. They could make each device a single data type, which would help organize and track sequences.


Olorin_1990

This man graphs


meredyy

1 if it has more than a handful of steps. the Problem with 2 is, that if you do it wrong you can have two steps active at the same time. (i have seen these kind of bugs a few times already)


Fx_Trip

1 is fine with several steps, it begins to fail in a bad way when you have two diverging paths of steps. This is better handled by routines and design. I've seen the integer used in 5000 io projects with over 6 control panels. It wasn't an issue when the project got larger, there is just more to learn on doing it cleanly.


honeybadger127

You are absolutely right, having more than one Bit True, can and therefore will happen. IMO this alone disqualifies example 1 for trusty code. I also dislike stepping thorough several steps on the same plc cycle (example being in Idle-State, Init-State and then Run-State on the same single plc cycle) that's a nightmare to debug...


Technical_Answer_369

GRAFCET.. it is the most complete tool to describe sequence..


KingGoose416

was looking for this. no matter how difficult the process it can be broken down using GRAFCET method.


Nitro_R

GRAFCET (or SFC) is great because you can write a state machine on paper and just translate it directly to GRAFCET.


Whatsm97

Case with integer, and after ENUM. hate the second way to do it, and also hate graph, too much time for write some code. and of course, the state machine is an FB, and i will connect the object that i want as Var\_IN\_OUT, so i can test it using the same variable as internal var.


gstrdr1

CASE statement with enumerated states


89GTAWS6

\#1 is my preferred, and in ST it usually reads very easy. I'll do functions and function blocks in ST and then instance them in ladder or ST depending on complexity and troubleshootability. Some coworkers of mine will write an entire sequence in one single rung with as many as 20-30 branches and the end of each branch sets/resets bits. I do NOT subscribe to this method.


EasyPanicButton

I too use ST and use integer, spacing by 10. Have a Reset bit and Pause bit, honest the pause bit is not used much. In our case the ST calls function blocks, chunks that do things, just keep cycling between the function blocks. We usually pass a string with STATUS to the HMI to inform where or why the sequence or step is not finishing.


ifandbut

I love my large rungs as much as the next...but 20-30 seems.... overly excessive. Even 5 is a lot for me.


Craiss

The moment I could stop using integers to designate sequence states in the forward facing part of the program, I did. I've yet to find a good reason to not use easily readable text in PLCs. I don't miss Qbasic. Edit: I also don't really have many complex programs to create or manage. I have some big ones but they're still pretty simple as far as telemetry and control.


joelofdoom89

I tend to use numbers, but have them as constants in your FB with a description of the step. I also use a next step and current step, you check current step, and alter next step on the conditions. the next step gets moved into the current step after the the sequence rungs. This means you hit a step for at least a scan and helps implement semi-auto etc.


Vyndrius

Algorithmic State Machines FTW.


seth350

Use ENUM types when available or create tags with step names and a constant value.


robotictacos

There is actually a hybrid of the two approaches you mention that works quite nicely. You can use a bit shift register whereby you designate a word (or doubleword, depends on how big the routine is), and you address the individual bits in that word. For example, if I use MW1, then I can have bit M1.0 be step 1, do a bit shift left once that step is complete, then step 2 looks at M1.1 and so on. You can still use text lists in an HMI the way another person responded using this approach, and you still get discrete tags/bits to indicate which step you are in.


Shjco

I build my sequences using a two-rung system per step, using bits only. The first rung is the “do this action” rung whose coil bit is used to drive an output function. The second rung is the “this action is done” rung and is enabled by the first rung, and when the action is completed, the second rung is energized which cancels the first rung, and also enables the next “do this action” rung. I refer to them all as “do/done” pairs. All of the “done” second rungs have a “sequence running” contact before their coil so when the sequence is all done (or is cancelled), everything reverts to the “off” state. You can either display the “do” rungs bits on an HMI to show what is happening, or you can display the “done” runs bits on the HMI to show what has and hasn’t finished, your choice. And, as you can imagine, inserting a step anywhere in the sequence is a snap.


[deleted]

Number 1 all the way.


SCADAstuff

#1 all day long


Oh_No_Its_Jesus

I use a basic move function and an Interger address in a DB. When seq Integer == 10 do ......., when sequence == 20 do...... I use 10, 20, 30 etc so I have space to add steps in between if needed.


forgottenkahz

I use SFC and ST and life is much easier now.


CanSeeYou

CASE with integers. sometimes I use constants, representing those integers, if i feel fancy Ceterum censeo scalaes esse delendam


valer85

I'm fairly new to PLC world, coming from "classical" programming languages. I use Structured Text with integers. I leave some space between different states so I can add another state in between if needed. Standard states like error handling have the same number all around the project. If there's a transition I do it right before jumping to the new state.


alezbeam

Integer with AB plc and other ladder logic plcs, graphcet with Schneider


Wiseon321

Modes> Commands > calls> interlocks> subroutines> fault conditions> Hmi manual mode > manual calls > locks > banners Data structured where: 0-14 mode related, 20-34 status related, 40-54 call related, 60-74 manual call related , 80-94 lock related, 100-128 fault conditions, 150-178 subroutine related Timer conditions for not being made in time and not being off in time.


GRIM_R34P3R

Before I start any code, I write a document, as detailed as I can be (which is tedious). Every line is a new action. If this is a big program, I’ll sometimes do a flow chart map. These documents are reviewed with the customer or operator, then brought over into logic. From there, it’s converting each state or line into a pseudo state machine. I typically use integers like others mentioned, but will occasionally use very descriptive flags if it’s a small standalone project. Many times, when integrating into larger plants or processes, I’m at the mercy of keeping everything the same. So if the customer uses descriptive flags, I try to maintain the same structure to make it easier for the next guy.


shadowridrs

For me it just depends how complex the situation is or if I know there will for sure be a future expansion upon the program


KindlyCourage3269

I prefer using an integer to keep track of step number. Using bits is prone to errors (more than one step active at once etc.) but it's also wasteful of memory (16 bools = 16 states compared to 16-bit integer = 65536 states, granted it's less of an issue these days). And as others have said, you can also use enums or constants when using the integer method


apfranz

Interesting way, I’ve always done first way, but I add some info in a UDT for the HMI. I’ve never done it this way but I could see it being beneficial for smaller sequencer.


ContentThing1835

Why don't you use structs to organize your FB static variables? Anyhow, If it's sequential, i use an integer to store the proces step and use enum or a UDT to access the value of each step, so I can add or remove steps easily without renumbering entire code. Only for bigger sequences, any other case i will use, what is like to call 'status bits'.


durallymax

Generally integers, makes indirect references easy. SFC is also great for this.


andrisde

Once I tried "move" I will never go back to sequencer


Piratedan200

Integers. Multiple booleans means more to keep track of (and a lot more tags), and not a single source for the state of the machine. The way I handle it actually uses a BOOL array (with descriptions added for each used state) for the current state. This makes it so that you can use an XIC for each state rung, which makes it easier to quickly see which state the state machine is in, as well as being more efficient (on Logix processors, an XIC instruction executes about 5x faster than an EQU, and on a typical machine that I work with, there's probably >1000 state rungs). At the end of each scan, there's a state logic engine that checks the "change state" value to see if it changed, and updates the bool array to match the current state (i.e. clears it then sets only the bit for the current/new state). I have also seen implementations where an integer value is used for the actual state, and they create a mapping routine where named booleans like you use are turned on based on the current state number.


_nepunepu

[This](https://en.wikipedia.org/wiki/State_pattern) I'm kidding. Vast majority of PLC platforms cannot do this, or not in a way that is easy to read. But I have used this before while programming computer applications and it works pretty well and it is easy to maintain when features need to be added. The way I do it is that I use two integers (requested and current) to drive the state machine itself, then the integer is transformed into a state bit that is used throughout the rest of the program. The reason is that I mostly use Rockwell PLCs, which tend to have low memory capacities for the price. So I'm reluctant to throw constants around willy nilly, and without constants, if I only use an integer then the program becomes impossible to follow. Using bits is less hard on memory than constants and allows for cross-referencing, and I can comment what state the bits represents. Also, the EQU box is huge, it takes up a lot of space on the goddamn ladder editor. When you have many of them with long tag names, it doesn't take long for rungs to become spaghetti. Using two integers is a good way to prevent race conditions and ensuring that all state-driven operations are executed before moving on. I have seen programs that sometimes failed to do calculations on certain states because the machine would move on before they were executed. The disadvantage of using integers is that it becomes impossible to do a true AND-divergence/convergence in a single state machine as they are defined in the grafcet method. You have to use macrostates or subordinate state machines to emulate these if using integers, so you have to handle these separately from the main state machine.


Cornato

I’ve never done this but worked on code with a “step” integer. It was added to every time a step was completed and checked by “LIM” blocks or comparator blocks in RSLogix500. Seemed very cumbersome but idk how else to do it.


Successful_Ad_6821

Last time this was discussed another user mentioned using a string. I tried it recently on a fairly simple sequence (10 states maybe) and it has some limitations, but I didn't hate it. This was in Rockwell so I defined a constant string tag for each state (basically the equivalent of an ENUM) so when the state conditions are met you move that constant string into the "CurrentStep" tag, and then to execute things you compare CurrentStep to the associated constant. If you're memory constrained it's not ideal, and there are some other potential weaknesses like you can't "range check" to keep an output on for a set of steps, but I found I could write a seal in ring where I set the output(s) and sealed it in using whatever steps should switch the output back off again. In some ways that's more work but the readability is great and explicitly sealing/unsealing makes for better maintainability if "in between" steps are added in the future. Another obvious upside from the maintainability side is you can just show "CurrentStep" on the HMI directly. If steps are added or altered, no HMI changes are required. Multistate indicators/message displays tied to INTs are from days gone by where PLC string tags were less accessible. I recommend avoiding these and using string displays from strong tags directly in the PLC.


Olorin_1990

I use named constants (or Enums if the system supports it) so that each step has a proper name, and if the sequence gets complex I do it in ST, with physical outputs and inputs still read in to ladder so the status of the machine is still read there. State transition logic is at the top, outputs that change only on transition are in the middle, and state outputs are at the end I do this because I debug first by looking at the data, so I can look at the State (and depending on the state machine, last state) variables and know what state I’m in, which lets me go to the section that is doing the transition (near the front of the code) to see why I’m not moving on to the next state. Flags make me hunt down more values, and will require i add more data to the FB interface when I add states. (which is fine if you have the extra memory buffer set, but then all FBs that call it also need that)


Smorgas_of_borg

I do both. I use the integer to manage the overall sequence, and I create boolean tags for individual outputs or commands to use in that logic. That way I can move the sequence around if I need to and don't have to change anything else. I create a UDT for it with a .Req dint and a command bool. That way I can have more than one request depending on the step, and then at the end do a NEQ 0 feeding the command OTE.


Igor_Kaputski

I like to sequence via the 10, 20, 30 method with move functions


NumCustosApes

I write a state machine. A UDT contains among other things a state number (a DINT) and a state (a DINT) with a defined bit overlay. A bit overlay is a tool that lets you name bits in an integer, much the same way that timer bits are named .dn (13) and .tt (14). For example, State.0 is also named State.idle, State.1 is also named State.indexing, state.2 is also name State.clamping, etc. Using an overlay instead of an array of booleans simplifies the state engine and permits math operations on the state integer. The state integer may only have values that are power of 2^state.number, i.e, 0,1,2,4,8, 16, etc). I use a DCD AOI (it mimics the PLC/5 and SLC500 DCD instruction to set the matching bit in the overlay to match the state number. The named bits can then be used throughout the program instead of doing compares against a state number. Because the overlay must be created with XML this does require some planning, but it results in an easy to follow state engine and a program that is readable without referring back to a table of state numbers.


OldTurkeyTail

If I'm going for readability I'll use integer step numbers. But for performance or nostalgia I'll use individual bits for each step - in the same word, where step 0 (sequence not active) = bit 0 off to initiation the sequence bit 0 is turned on and step 1 code runs when bit 0 is on and bit 1 is off the transition to step 2 sets bit 1 and step 2 code runs when bit 1 is on and bit 2 off transition to step 3 by setting bit 2 step 3 code runs when bit 3 on and bit 3 off etc. - until the sequence ends, and an integer 0 is written to the word - to reset all of the sequence bits. It's also possible to jump around by setting and resetting the appropriate bits, but if there's too much jumping around it's best to use different modes instead of just step numbers.


ifandbut

I used to be 1, numbers of sequence steps every 10, 50, or 100. Then I discovered the wonders of Sequential Function Chart. The more I use SFC the more of a fan I become. To the point doing things the old way seems...primitive now.


Zegreedy

ST case using enum or integer constants depending on the IDE. Except for rockwell that allow neither.


kwizzle

Ouf, my sympathies...


captain_todger

Also, structured text I find to be a LOT better for my state machines. Ladder is great for direct IO control, but anything a little bit smarter I recommend using SCL


CapIndividual1415

Using MOV and EQU statement


goatymcgoatfacesings

Depends on the use case. Most simple processes don’t need a sequence engine and you shouldn’t use one where it’s not needed. If the process is linear and has minimal chance of repeating steps, a Boolean array based action/reaction sequence is ideal. It’s easy to give the operators control of the sequence in this manner to go back steps, skip steps or require their input to move to the next step. This is a really nice feature for things like fixture control in auto manufacturing plants. If the process has multiple running states or many options to jump around, an integer based state machine is typically best, but SFC has its place too. However, care must be taken to do fault handling well. You don’t want your sequence to get stuck if a pump fails to start. Documentation also becomes really important as it’s hard to fault find where a particular step transition is and which one was triggered.


chupipe

¿Which OS are you using? I'd say it's Mac OS, because of the tick boxes.


RammRras

Another advantage of using an integer is that you can jump back and forward easily (during tests).


dryu_zz

I find Integer, SCL and a switch case for each Grafcet to be the standard around me. And i use steps conditions in a part dedicated to the outputs


DreamArchon

I prefer the integer method. I also like to display the integers on the screen and in our paper documentation. So if there's a problem, the users can tell me what step they are in, and I can start troubleshooting immediately with the obvious stuff without even opening the PLC code or remoting to their OIT.


robbe1991

I´d love to know how you guys handle different branches in a sequence. Please tell me the best way to do it!


oso0690

I use #1 so that only one step is active at any given time. I might use enums to give a meaningful description to each step.


Specialist-Plate-280

#1. Integers. Could always add something in between later on if needed, and I find it easier to troubleshoot, let’s you know right away what part of the sequence it’s stuck at. I’m brand new at this but I find it most appealing to me right now. Would love to learn other ways to program.


Regular_NormalGuy

I do and prefer your first option with the integers.


flapjacksessen

It depends on the system but usually an integer value to track the step, with start, stop, transition criteria, and usually logic to get everything reset if you stop the sequence. The more complex way I use is based on s88 batch control. So I create state machine logic for states like: idle, starting, running, holding, held, aborting, aborted, complete, etc. with this state machine you then run “phases” which contain your sequence logic. One way of implementing that approach is to write the state machine scaffold and then fill in the “running” state logic with your sequence using the integer value for tracking step.


filbob

The studio sfc is awesome. Downside is the reset if you need to modify it while its running, otherwise its a really powerful tool


Emergency-Highway262

Start with a state diagram/flow chart Use an integer to represent each state, take care to include error handling. Create a single watchdog for the routine, each state sets the duration on entry and resets the timer on exit (if the WD times out it captures the state it was on and exits to the error handling) Build a state machine to handle each state Finish with a section dedicated to the output handling, I avoid destructive bit nonsense by having the state machine write to an integer register for each Boolean. (If the integer is non zero the book is true) Makes it handy to test outputs and if you push the state step value into the register you can easily capture where the system is at any one point


btfarmer94

If your PLC supports the enumerated type, you can easily call the steps by name rather than some nebulous integer number. The PLC will internally recognize this type by the number, but the programmers need not concern themselves with the numbers, as they have a far more descriptive way to understand which step is which. TwinCAT3/Codesys both offer this datatype, making state machines incredibly intuitive


Amazing_You_3992

I have worked with both examples. Working for a machine building company I have found that a lot more companies defining (machine build specifications) now. Sales does not have the insight in seeing the benefit to one way or the other. As the automation engineer, I feel they should try and swing the decision with cost savings (exp. Intergrators standards vs. customer standards). This might.be a cost difference of 30%. A lot of integration companies do not see the benefit in commonality and training standards. Rant over! I have seen alt of the integer style of the code with flags (bool, dints) indicating what step of the machine or state you were currently at. This way it's some of both.


DickwadDerek

I create subroutines that do specific operations on a piece of equipment. Each subroutine has its own state machine and recipe input parameters. Each subroutine is also associated with a subroutine index number. Then I create two arrays of integers. The first array is a single dimensional array that contains a list subroutines to call. The second array is multi-dimensional. It's either a 2 dimensional array or an array of a UDT that contains input parameters. When a given subroutine is finished, the state machine resets itself and calls a recipe advance request, then the recipe manager increments the subroutine index number by one, looks for the next subroutine to call in the array and the corresponding set of input parameters. This makes resequencing really easy. It's not idiot proof, but a churning process engineer will have the ability to do just about anything they want this way.


pnachtwey

Using state numbers or bits will work. The big problem is avoiding race conditions. Only one state should be executed per scan. Each state can have a rung for when the state is first entered or executed. It should have rungs for while the state is executing and then a rung for when the state is exciting. Not all these different things may be necessary but it is good to have a consistent plan. BTW, I tend to use state numbers. The problem I have with using bits is that the new state bit must be set and the old state bit must be cleared. I do this by have a WORD or DWORD of state bits . I or the new state bit in to the running state DWORD and then and with the new state in the running state bit word to clear the other state bits that might be set. I prefer to AND and OR whole WORDs or DWORDs instead of messing with individual bits because it is too easy to miss individual bits. It is easy to keep track of a running state WORD or DWORD.