Why good ladder logic looks like it was written by an 8 year old

When traditional PC programmers see ladder logic, they think ladder logic programmers are terrible programmers. Being both a .NET developer and a ladder logic programmer, this has caused me a lot of frustration and confusion over the years. I have one foot in each world, and yet I choose to write C# programs one way and ladder logic programs another. Why?

Let’s ignore the fact that most traditional programmers just don’t grok ladder logic at all, because their minds think about programs sequentially rather than in parallel. The real reason they hate ladder logic is because ladder logic programmers avoid things like loops, indexed addressing and subroutines. To them, this means you’re programming at the level of an 8 year old.

The thing is, I know how to use loops, arrays, and subroutines, not to mention object oriented programming and functional programming constructs like s-expressions, closures and delegates. Still, I choose to write simple and straightforward ladder logic. Why would I, an experienced programmer, choose to write programs like an 8 year old? Do I know something they don’t?

I spend a lot of time trying to get people to think about why they do things a certain way. Everyone wants that simple rule of thumb, but it’s far more valuable to understand the first principles so you can apply that rule intelligently. Decades of computer science has given us some amazing tools. Unfortunately, a carpenter with twice as many tools in her tool box is simply twice as likely to pick the wrong tool for the job if she doesn’t understand the problem the person who invented that tool was trying to solve.

The first time you show a new programmer a “for” loop, they think, “Amazing! Instead of typing the same line out a hundred times, I can just type 3 lines and the computer does the same thing! I can save so much typing!” They think this because they’re still an idiot. Don’t get me wrong, I was an idiot about this too, and I’m still an idiot about most things. What I do know, however, is that for loops solve a much more important problem than saving you keystrokes. For loops are one of many tools for following the Once and Only Once (OAOO) Principle of software development.

The OAOO principle focuses on removing duplication from software. This is one of the most fundamental principles of software development, to the point where it’s followed religiously. This principle is why PC programmers look at ladder logic and instantly feel disgust. Ladder logic is full of duplication. I mean, insanely full of duplication. So how can you blame them? God said, “let there not be duplication in software,” and ladder logic is full of duplication, thus ladder logic is the spawn of Satan.

That’s because programmers who believe the OAOO principle is about removing duplication are idiots too. Don’t they ever wonder, “why is it so important to remove duplication from our code?” Should we really worry about saving a few bytes or keystrokes? NO! We focus on:

  1. Making it do what it’s supposed to do
  2. Making it obvious to the reader what the program does
  3. Making it easy to make changes when the requirements change

… in that order.

In fact, #3 is the real kicker. First of all, satisfying #3 implies you must have satisfied #2, so ease of understanding is doubly important, and secondly, satisfying #3 implies you can predict what will change.

Imagine if you have to print the numbers from 1 to 5. If I asked a C# programmer to write this, they’d likely write something like this:

for(var i = 1; i <= 5; i++)
{
    Console.WriteLine("{0}", i);
}

… of course I could write this:

Console.WriteLine("1");
Console.WriteLine("2");
Console.WriteLine("3");
Console.WriteLine("4");
Console.WriteLine("5");

Why is the first way better? Is it because it uses fewer keystrokes? No. To answer this question, you need to know how the requirements of this piece of code might change in the future. The for loop is better because many things that might change are only expressed once. For instance:

  • The starting number (1)
  • The ending number (5)
  • What to repeat (write something to the screen)
  • What number to print
  • How to format the number it prints

If the requirements of any of these things change, it’s easy to change the software to meet the new requirements in the first case. If you wanted to change the code so it prints every number with one decimal place, the second way clearly requires 5 changes, where the first way only requires one change.

However, what if the requirements changed like this: print the numbers from 1 to 5, but for the number 2, spell out the number instead of printing the digit.

Okay, so here’s the first way:

for(var i = 1; i <= 5; i++)
{
    if(i == 2)
    {
        Console.WriteLine("two");
    }
    else
    {
        Console.WriteLine("{0}", i);
    }
}

… or if you wanted to be more concise (but not much more readable):

for(var i = 1; i <= 5; i++)
{
    Console.WriteLine(i == 2 ? "two" : i.ToString());
}

Here’s the change using the second way:

Console.WriteLine("1");
Console.WriteLine("two");
Console.WriteLine("3");
Console.WriteLine("4");
Console.WriteLine("5");

Here’s the thing… given the new requirements, the second way is actually more readable and more clearly highlights the “weirdness”. Does the code do what it’s supposed to do? Yes. Can you understand what it does? Yes. Would you be able to easily make changes to it in the future? Well, that depends what the changes are…

Now think about some real-life ladder logic examples. Let’s say you have a machine with some pumps… maybe a coolant pump and an oil pump. Your programmer mind immediately starts listing off the things that these pumps have in common… both have motor starters with an overload, and both likely have a pressure switch, and we might have filters with sensors to detect if the filters need changing, etc. Clearly we should just make a generic “pump” function block that can control both and use it twice, right?

NO!

Look, I admit that there might be some advantage to this approach during the design phase if you had a system with 25 identical coolant pumps and your purchasing guy says, “Hey, they don’t have the MCP-1250 model in stock so it’s going to be 8 weeks lead time, but they have the newer model 2100 in stock and he can give them to us for the same price.” Maybe it turns out the 2100 model has two extra sensors you have to monitor so having a common function block means it takes you… 20 minutes to make this change instead of an hour. We all know how much you hate repetitive typing and clicking.

On the other hand, when this system goes live, making an identical change to every single pump at exactly the same time is very rare. In fact, it’s so rare that it’s effectively never. And even if that were to ever actually happen, the amount of programming time it actually saves you is so tiny compared to the labor cost of actually physically modifying all those pumps that it’s effectively zero.

However, since these are physically different pumps, you’re very likely to have a problem with one pump. When your machine is down and you’re trying to troubleshoot that pump, do you want to be reading through some generic function block that’s got complicated conditional code in it for controlling all 50 different types of pumps you’ve ever used in your facility, or do you want to look at code that’s specific to that pump? And maybe the motor overload on that pump is acting up and you need to put a temporary bypass in to override that fault. Do you really want to modify a common function block that affects all the other pumps, or do you want to modify the logic that only deals with this one pump? What’s more likely to cause unintended consequences?

So this is why ladder logic written by experienced automation programmers looks like it was written by an 8 year old who just started learning Visual Basic .NET last week. Because it’s better and we actually know why.

11 thoughts on “Why good ladder logic looks like it was written by an 8 year old

  1. Ed Stevens

    Good post: there should be more discussion in general about how to structure PLC or DC’s code. It’s indeed true that control modules (valves, motors,…) are better written out instead of trying to cram everything in one function block. On the other hand it is also good practice to have a well-tested function block at the core that takes care of the basic functionalities (manual/auto mode, start/stop, interlock, …) and the interface with the corresponding faceplate on the HMI.

    Now the big question is if it’s normal that automation engineers spend a big chunk of their time programming like 8-year olds? It is repetitive work so by definition it should be automated. The whole industry should move to code generation based on templates. And that would give another dimension to the discussions about program structures because those will happen around specific template examples.

  2. Michele

    Great article!
    I used to write a lot of ladder logic, due to my previous firm using Allen Bradley plc, and I always came to this website to check for best practices.
    The example of the pump is pure gold. I have seen far too many programmers who tried to apply OOP to real hardware, while things just needed to be simple and straightforward to be debugged.
    A problem arise when the logic is reusable, like a complex action that has to be performed in various steps of the cycle. In this case I am not sure that duplicated code is the solution.
    I saw programmers try to write reusable code and subroutines by not abstracting the machine state, and this led to a big ball of spaghetti code where global variables were referenced in subroutines all around the program.
    I absolutely agree that duplicated code is not evil in plc programs, but I also think that a plc programmer has to be able to identify whether it is appropriate to write it, by keeping in mind that the program must be easy to read, easy to debug and easy to be modified.

  3. Owen

    When I made the transition from C# to ladder logic I had the exact same initial thoughts, though unfortunately I immediately started using Structured Text and wrote complex AOI’s. When I made the transition to an integration role, I immediately heard how much technicians hate AOI’s, much less anything in Structured Text. From the plant floor perspective, when a machine is down and money is being burned, it’s all about clarity and the ability to change function- even just temporarily for testing. Individual physical devices need dedicated individual logic.

    I think that the elegance can be achieved by using very organized program structure and initially generating code from templates, like a previous comment mentioned.

    As for AOI’s, nowadays I find myself thinking, “Can I re-use this logic in the language in general?” In that I case I make an AOI. Never for the sake of a device, but for the language itself. For example, I needed a photoeye that changes to “blocked” after a delay and “cleared” after a delay. I could have written a “photoeye” AOI, but instead I wrote a “de-bounce” AOI.

  4. Ryan Maw

    What if, down the road, your Console.WriteLine example had to change, again, to print out 100 numbers? I think we would all choose the loop, even if there were two or three exceptions. We might break the loop down into three loops covering different ranges of numbers with exceptions in between, but I don’t think it would be a good idea to write 100 lines of Console… One of the reasons I like to use function blocks and sub-routines and loops is because they prevent the little bugs that tend to get in via copy and paste.

    You also seem to pose a sort of false dilemma with the example of the pumps. If we use a function block (AOI) for the pumps, but later add a different model of pump, our choices are not between a single, reusable Swiss-army pump function block and a bunch of separate copy-and-paste code blocks. We also have the third option of making a second function block for the newer model pump.

    I agree it is a pain to wade through function blocks with complicated conditional code. So don’t write them. A small amount of well-commented conditional code is generally acceptable. When it gets too messy, create two separate blocks.

    I agree that clarity and flexibility should be top objectives, but I don’t see these as precluding the use of function blocks, loops, and indirect indexing. These conveniences can certainly be overused, to the point of confusion, but I don’t see how this possibility should abolish their use altogether. Maybe if you had a more compelling example I could be swayed in my thinking. I enjoy your blog, but I believe this topic is more nuanced than you present it to be. Writing good code is hard, and, in part, art.

  5. Ryan Maw

    You know what we need to do, Scott? We need to organize a yearly conference for professional PLC/machine programmers. Not a vendor-run product show-and-tell type of event but something for serious programmers where we can both present and attend short classes about issues like machine safety assessments, intellectual property as it applies to the software we write, advanced patterns for PLC code, effective HMI design, etc. As a professional engineer I have always felt a bit unprofessional for spending most of my time doing PLC programming work. It feels like some sort of wild-west of one-offs and dirty hacks, an every-man-for-himself realm nearly devoid of best practices, standards and professionalism. I feel I don`t quite fit into either the business software development world or the professional engineering world.

    I am weary of attending electrical engineering professional development seminars every year for lack of any serious courses more focused on my line of work. As the field of automation continues to expend there will only be a growing demand for a conference catering to people like us.

  6. Scott Whitlock Post author

    Thanks everyone. This is the kind of interesting conversation I’ve been trying to get going. 🙂

    The problem of balance between using more advanced PLC programming concepts such as AOI/function blocks, structured text, and indexed addressing vs. the desire to write a program that a non-programmer such as an electrician can easily navigate and troubleshoot is at the heart of the PLC programming dilemma. The topic of this article, and the responses, all deal with this fundamental mismatch.

    My personal view, based on experience, as that we tend to over-emphasize the time we “save” by using some of these tools, under-estimate the complexity we’ve added, and we under-emphasize the importance of non-programmers being able to understand and quickly change our logic.

    I think most PLC programmers who want to use more advanced concepts work for integrators and their end customers are typically plants with non-programmers to have to maintain these machines, so they should be leaning towards simpler, more repetitive logic. The irony of the situation is that I now work in an environment (in a plant) where we have two very knowledgeable PLC programmers who understand these more advanced concepts and how to use them, and we don’t have non-programmers going up to machines having to troubleshoot the ladder logic, and yet I still hang on to these core principles that I learned during years of doing integration.

    We had a discussion here this week where this exact situation came up. We talked about the drive to use more advanced concepts vs. how easy it would be for someone (even ourselves) to walk up to the machine, find the logic for the device they’re interested in, and troubleshoot it. At least we’re making a conscious decision about the expected level of expertise of the person who walks up to that machine, and I think that’s the most important take-away from this whole topic.

    @RyanMaw – I would certainly like to attend such a conference, and would be interested in doing a talk. I would also be interested in going to talks about safety systems, etc. However, organizing such a conference is a *big job* and I, for one, don’t feel up to the task. Is there an organization that’s not tied to an individual manufacturer that would be interested in organizing such an event? Perhaps the CSIA?

  7. Ryan Maw

    Maybe conference is the wrong word. It could be much more casual: A meet-up for of PLC programmers. Two days at a nice hotel or lodge. A chance to meet people who do the same stuff and talk about personal work experiences and lessons learned. No real organization of the event would be necessary other than everyone comes prepared to share something and we all agree on a location and date. It could be small; even with just a few people I think it could be really interesting, even more interesting than a big conference.

  8. Pingback: Why good ladder logic looks like it was written by an 8 year old | Contact and Coil – BrentHumphreys.net

  9. Victor Martinez

    Hi PLC guys!

    I have been worked many years on the Automation Industry at Michigan. When I started Siemens has the major PowerTrain Jobs in the Area. I loved to do STL software for Siemens controllers. The logic executed faster than any ladder diagram but later on I understood that the PLC program is not made for me.

    The PLC program is built for the plant and usually the first person to respond to an factory issue is going to be an electrician. Usually electricians are guys or ladies without advance programming knowledge.

    After couple of years I got a opportunity to do a project using Mitsubishi Classic Ladder without symbols, write a line using it cost a lot of hours because it was unable to use common logic due every single bit of memory most to be different using that system but the plant people love it because is easy to debug.

    Currently I am working on a project which the lead programmer before me use loop cycles to process common information the big problem with that is that is not way to find which common equipment got the fault on the logic. Which it will translate of tons of hours in debug purpose and make the system very hard to change it if any of the common components changes.

    I agree with the idea of use AOI/FB for common equipment the rest of the equipment Cycle Modes, Power, Motion commands and Safety should be classic ladder using labels.

    Also code repetition is good when you can afford it. I worked on a job which we have a machine which can have up to 4 nut-runners, scanners, garcons and feeders. It was enable with options bits on the screen. so in this way you can balance the line if required in any other of the spare equipment per station.

    Thanks

  10. Joshua

    I work in a company producing systems with a fixed set of different components acting in a fixed set of changing scenario’s. Using ST allows to fully parameterize the code and produce quickly a new program for a new system. I guess using ladder would be much more cumbersome to do so.

  11. Scott Whitlock Post author

    @Joshua – I can only discuss general “rules of thumb” here. Over many, many machines, certain patterns tend to arise. But each situation might be unique, and you always need to take your own circumstances into account when programming.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.