State Machines in Structured Text
How State Machines Changed My Controls Engineering Approach


From Long Ladder Logic to State Machines
If you're anything like me, you know how challenging it is to create complex, long-ladder logic programs to drive industrial equipment. Before I was introduced to state machines in 2019, I spent my time in the ladder logic world (like most controls guys), creating detailed routines to capture every aspect of a process. However, no matter how hard I tried, repairing and maintaining those programs was a time-consuming task, sometimes a nightmare.
Then along came state machines — and all of that changed.
State machines added a further level of structure and flexibility that made it easier to control complex scenarios and reduced the chances of mistakes. State machines allow you to break down a process into well-defined states, which are easier to visualize, modify, and debug. I never switched back to just using procedural ladder logic programming after starting to use state machines.
My tool of choice is Structured Text, because of its flexibility. However, just like many other professionals out there, I am a proponent of using the right tool for the job. If ladder makes sense to build a simple logic, I still do use ladder logic as it has its visual benefits.
Why State Machines are a Game-Changer?
State machines offer many advantages 🎯:
Modular Logic: Breaking down processes into states makes it easier to deal with complexity and keeping the logic organized.
Improved Troubleshooting: It is easier to identify where the process broke down by tracking the current and previous states or adding these states to a log if needed.
Control Logic Flexibility: State machines give you control of transitions so that you can deal with unusual situations smoothly
Lets walk through an example:
The Garage Door Opener State Machine
As an example to showcase the power of state machines, I employed a simple and typical example lets call it: a smart garage door opener.
Being an industrial refrigeration controls engineer, I wanted to make a generic example to share without referencing any proprietary work. While I am not a garage door opener building specialist, I believe this is an application most of us can relate to and learn from. So if you happen to build garage doors openers for a living, and are reading this post, please give me some grace on my code 😊
Disclaimer: Please do not use the code below for production code, anything provided on this blog is for educational / information-sharing purposes only. The code provided does not reflect real-world garage door operations. Always consult a qualified application or mechanical engineer for industrial/commercial control systems. Any damage, injury, or loss resulting from the use of this sample code is solely the user's responsibility.
Learning the State Machine
Ok so now that we are done with the scary disclaimer...
So, what exactly is a State Machine? 🤔
There are many ways to build one, but I chose to create this using CODESYS and Structured Text (ST), which has quickly become my favorite development environment (sorry, Studio5000! 😅). That said, I’ll admit I still miss the flexibility of building ladder logic in Studio5000 (RSLogix5000) from time to time.
But let’s get back on track! 🚀
When using Structured Text, a state machine is essentially just a case statement. Each constant or value (so to speak) within the case statement represents a different state of the machine.
Below is the state machine for the example garage door opener:
Idle/Closed State: The door rests in a standby position, ready for a command.
Opening State: The motor is propelling the door upward.
Fully Opened State: The door is open and ready for a close command.
Closing State: The motor is propelling the door downward.
Obstruction Detected (Laser): Laser sensor detects blockage on close.
Obstruction Detected (Overload): Motor overload on opening or closing is detected.
Emergency Stop: E-stop button brings all activities to a halt.
Now a picture, servers as a thousand words, below is a quick visual of how this would look like if we were to create a logic diagram that closely resembles a Sequential Flow Chart (SFC).
You might be wondering: “But wait! Aren’t some states missing?” 🤔
And you’d be absolutely right! CODESYS offers a fantastic Sequential Function Chart (SFC) builder, and you could definitely write this entire program using SFC (To clarify any confusion, this diagram I just quickly made with draw.io not CODESYS). However, when it comes to handling asynchronous conditions—like jumping to the emergency_stop state—or performing checks such as motor overload and safety sensor verification, I’ve found that implementing these in Structured Text (ST) is often more straightforward and easier to maintain.
But before we dive into the code, let’s talk about how we’re handling error conditions and how we could log state transitions for future troubleshooting. 📝🔎
Smart Error Handling with Previous State Memory
One of the coolest things that we can do when we write our own state machine in Structured Text is that we can make it remember the prior state so that when errors are fixed, the system can resume where it left off. For instance, if an overload obstruction is sensed while closing, the door will return to the closing state automatically after the obstruction is removed and the operator resets the error. Similarly if an obstruction is detected by the safety laser, the state machine will stop the door and reverse the direction by going to the opening state. Although I am not doing this in this example, you could also create an array for the ePreviousState and push to this array all the ePreviousState to have it as reference. Or you could use a built in logging feature to log the states and the errors to-be displayed on the HMI for example.
The Structured Text (ST) Code
Below is a snapshot of the ST code that brings this logic to reality:


Unit Testing is Necessary
Before any state machine (even for a simple system like this one) can be deployed, unit testing is a good idea that should not be skipped. All possible transitions and error states must be simulated to ensure the system behaves as intended. While this particular example is training-oriented, production systems require extensive testing for safety and operation.
Conclusion
State machines have become a cornerstone of how I design control systems. If you're still typing away at long, deeply nested blocks of ladder logic, I encourage you to explore state machines and experience the benefits by giving it a try. While this garage door example isn’t production-ready, I hope it highlights the flexibility and power of state machine design.
If you haven’t tried CODESYS IDE yet, I highly recommend giving it a shot! 💡 If you're transitioning from the AB world (like I did), there’s definitely a learning curve. But once you get the hang of it, CODESYS offers a fantastic development environment packed with built-in features.
👉 What do you think? Are there other processes where you could apply a state machine?
💬 Enjoyed this post? Would you like me to dive deeper or even create a video to demonstrate unit testing this garage door example? Let me know! 🎥😊


Onwards to Mapping the Outputs
Using this method, it becomes super easy to tie in the outputs to the logic. When building logic using a State Machine usually each output will be defined by a state. Now this is not always the case though, in more complex system, there will be other interlocks and conditions that you will have to consider to safely manage your outputs.

