This not going to persuade anyone to quit using, or undo, existing unconditional sub-routines that they might already have... however, it might persuade novices from following that path.
My primary objection is to the idea of using unconditional sub-routines.
So... let's say you have a main section of code that is perhaps 100 rungs long. Then, let's say that you have... oh, 50 sub-routines. And let's say they all just happen to be 100 rungs each. And all of the sub-routines are called, unconditionally, every scan.
50 sub-routines x 100 rungs = 5000 total sub-routine rungs
The main has 100 rungs.
5000 + 100 = a grand-total of 5100 rungs... every single scan...
In terms of the processor, what is the difference between a single-body program, consisting of 5100 rungs, and a multiple-body program, again, consisting of a total of 5100 rungs?
Generally nothing, except that, from the processor's point of view, the sub-routine version has a bit of extra over-head, what with all that jumping and returning.
Gee... do ya think that might affect the scan time... just a little? Maybe?
Do you have any sorta-high-speed Input ON/OFF situations? Situations where, if the scan-time was just a little bit better you wouldn't need to install a high-speed counter?
Except in the case where certain inputs are monitored on an interrupt-basis, the "read-inputs" portion of the scan is essentially... non-existent. While you are "sleeping", the world keeps turning on it's axis... things happen, sometimes slowly... sometimes quickly... sometimes too quickly to notice.
We "Computers" (as in "Be the Computer") need to notice everything! As quickly as possible! Un-neccessarily long scan-times cause un-necessary problems. Don't forget... PLCs are NOT REAL TIME! Not even with interrupts.
Changing tack a bit...
I have absolutely no objection to the idea of using a sub-routine to support a "Class", as in "C", or "C++". In this case, if fully utilized, the particular sub-routine can be notified as to which inputs/conditions are pertinent as well as which outputs are affected. That would be a case of a truely "general-purpose" sub-routine... very much in line with the original intent of sub-routines.
A valve-class was suggested. All of the valves, in that particular class (there might be any number of classes... Valve-Type-A, Valve-Type-B, etc), are handled in exactly the same way. In this case, the sub-routine is absolutely unprejudiced... it treats all valves, in the particular class, exactly the same. (OK, yeah... it's absolutely unprejudiced, however, only within the particular class - I guess that, over-all, that makes it inherently prejudiced)
Be that as it may... all the sub-routine needs to know is... which conditions to pay attention to, and which output(s) to affect.
That is a TRUE general-purpose sub-routine! There's no way in the world that I can argue against the value of such a tool!
Then there is the argument that using sub-routines makes it easier to get right to the area of interest while troubleshooting. This is the general solution for not having at least a minimum set of reasonable documentation.
When I started in my current situation, the first thing I did was produce a document identifying all of the Inputs and Outputs by number and name... on a functional-module basis. I had to change a lot of those names into something reasonable. I distributed that document to all of the electricians. They have been updated ever since.
I did NOT include Timer and Counter numbers.
In general, any process that has been working well for any length of time represents pretty stable code. If a problem occurs in stable code... you can bet your house that it is an input issue, or a mechanical issue... not a code issue.
And so, that document gives those electricians (and perhaps the brighter mechanics and production people) the primary tool that they need to figure out what's wrong. Of course, they need to know how to read the idiot-lights on the PLC modules... a "map" is always beneficial!
If an HMI is available, access to Timers and Counters should ALWAYS be restricted as much as possible, except through the HMI.
If a situation occurs, in an HMI-less system, where the Timers and/or Counters need to be modified, in the program, by maintenance folks... that "wanna-be-a-programmer" guy should be fired. That "so-called programmer" simply ain't doin' what needs to be done!
Darren asked...
"What happens to the outputs in this section while it is being skipped??"
You have to realize how a computer really works with memory. You also need to realize that there is a FRIGGIN' HUGE difference between a Sub-Routine and an MCR (Master Control Relay).
In a computer, once a bit is told to turn on, it STAYS ON... until TOLD to turn OFF! Otherwise, how could you possible expect to call-up a document and have all of the 0s and 1s as they should be?
The thing about a PLC is that... upon "SCANNING" a rung, if it doesn't have "cause" to turn on, or keep on, the particular output-bit, then the PLC will drive that bit OFF!
The key here is that the rung has to be SCANNED! If the rung is not scanned, then the associated output-bit is not changed... at least, not by that rung.
If a sub-routine is not running, then that sub-routine is not scanned, and so, the rung associated with a particular bit can not cause the last written state to be changed. The bit remains as it was after the last scan across the rung controlling that bit.
In an MCR the PLC is designed to turn OFF all bits within the MCR range if the MCR is not active.
HOWEVER... what you need to know is that ALL rungs in an MCR area are ALWAYS scanned! If the MCR is OFF, then ALL Output-bits are turned OFF. If the MCR is ON, then all Output-bits respond to the conditions within each rung.
A PLC is nothing more, or less, than a COMPUTER! It is a PC! (or mac). It follows the same rules that a PC follows!
I'm goin' for a serious MGD-break now... later.