Subroutine philosophy

Doug-P

Member
Join Date
Jun 2003
Location
Pa
Posts
1,248
A situation has arisen which will probably require some logic to be rewritten. There is a philosophical (so far :)) disagreement between myself and two of the other programmers.

They are of the opinion that when multiple actions are needed to get something done that each routine be called in its turn from the main line program until the result is achieved. (nesting bad!)

My position is: make one call from the main program and let the subroutines call whatever other subroutines are necessary.

What does the forum say?
 
elevmike said:
You've got my vote!
Thanks! Maybe I should have posted this thread as a poll.

Actually, I'm thinking that the way to go might be to just start in doing it 'my way'. I've already got one functioning example so there's a precedent, right?
 
Just be aware that there may be restrictions on how deep you can nest the subroutines. If you exceed the limit, the program may crash. It can be a bear to troubleshoot if your subroutine calls are conditional. In fact, any time you make subroutine calls conditional, you increase the difficulty in debugging the program.

I'm of the opinion that you shouldn't be afraid have one subroutine call another one, but you should design your program so that you keep the degree to which the subroutines are nested manageable.

Which means that the answer to your question is our favorite: "It depends..."
 
Steve Bailey said:
Just be aware that there may be restrictions on how deep you can nest the subroutines. If you exceed the limit, the program may crash. It can be a bear to troubleshoot if your subroutine calls are conditional. In fact, any time you make subroutine calls conditional, you increase the difficulty in debugging the program.
I won't have a problem there, I'm only going two levels in. On the other hand, conditionality is almost unavoidable. As in:

{If new data,
call LOOKUP srtn}

/LOOKUP
{Call SEARCH
if data exists
Call REMOVE srtn
if data exists
set actuation latch
}


It's simplified but it's generally this way.
 
"Nesting " of sub-routines is not required at all.

You might set yourself up to run against "nesting-limits" but this need not happen at all.

Now, there are "timing-advantages" in using "Sub-Routines". However, ALL of those "advantages" can be realized in Ladder alone.

Before there were "Sub-Routines" there was only Ladder. Ladder was alone. Ladder could, and can, handle all "sub-routine"-like functions without using ANY "Sub-Routines".

Granted, there is a large degree of "modularity" involved in sub-routines. However, Ladder can maintain the same degree of "modularity" and, yet, produce more time saving than a "Sub-Routine" can!

That is,... if you are not afraid.

(80)
 
I am agreement with Steve Bailey and I add.
The approach that myself,
Recommends:
  • It ascertain quantity of datas, records; Defined a streak of variables from the same one pagines (Variables in low address Some CPU, the time of access for low/high address does difference)
Restraints:(avoid)
  • Normally, the sub-routines they not enable the utilization of determined instructions; Exactly, can occur sporadic, unexpected errors.. But should have caution to the hardware "free" restritions.
  • Avoid indirect instructions and manipulation data
Verify limits: Quantity of records; Noose of repetition; gross Time from the routine;
Disable in the called, routines of hardware (prioritary), avoiding interroper during the execution.
It mount a table of decision, classifying the kinds of routines, actions and purpose. Like this that said as do.
-----------------[portuguese]------------------
Sou de acordo com Steve e adiciono. O método que aplico,
Recomenda:
Evitar adicionar o flag de interlock da chamada da routina no final dela. Utilizar flag auxiliar.
Averiguar quantidade de dados, registros;
Definir uma faixa de variables da mesma pagina (Variables em registro baixos; Algumas CPU, o tempo de acesso para registro baixo alto faz diferença) Restrições: (evitar)
Normalmente, as subroutinas impedem a utilização de determinadas instruções; Exatamente, pode ocorrer erros imprevistos, esporádicos ... Mas deve ter cautela aos hardware "liberais"
Evitar instruções indiretas e deslocamento de dados.
Verificar limites: Quantidade de registros; Laço de repetição; Tempo total da rotina; Desabilitar na chamada, routinas de hardware (prioritaria), evitando interroper durante a execução.
Montar uma tabela de decisão, classificando os tipos de routinas, ações e finalidade. Assim que decido como fazer.
 
Terry,

Speed is not an issue for this Softlogix engine application.

I understand that ladder can do it all and that subroutines add a level of complexity. However, I gravitate toward the clarity (to me anyway) and compactness that they provide. Besides, if, down the road something needs to be tweaked the subroutine allows said tweaking to happen in one place for all rather than sifting through the program to find every instance to be changed.
 
Terry Woods said:
Now, there are "timing-advantages" in using "Sub-Routines". However, ALL of those "advantages" can be realized in Ladder alone.

Before there were "Sub-Routines" there was only Ladder. Ladder was alone. Ladder could, and can, handle all "sub-routine"-like functions without using ANY "Sub-Routines".

Granted, there is a large degree of "modularity" involved in sub-routines. However, Ladder can maintain the same degree of "modularity" and, yet, produce more time saving than a "Sub-Routine" can!

I guess there still are people that think the world is flat!
 
programmer...

I guess that shows how little you understand about "cause & effect" as in... why exercise a particular stretch of code when you don't need to.

Run code "flat" at the top and dip in whenever and to whatever extent is necessary only when that is required.

In this manner, average scan time is as low as it can be. This makes for faster responses when those responses are needed.

Granted, sometimes the scan time is longer. But very rarely, if ever, will the scan time be too long. This is because large portions of the process are idle.

So...?
 
Terry,

In most machines, (no.. make that ALL) machines (CPUs) I know of, only the instructions in the main body of the program, and called subrutines will be scanned. My "master" program has 4 subs. If I tried to elimiate all the subs, the program execution time would be well above 50ms. The one sub that is only run on the 1st scan for configuration purposes alone takes 20+ms to execute. If these instructions were executed on all scans/cycles my program would be a dog (and were not talking about a Greyhound), and I would be dealing with a large number of trip and fall lawsuits, burning up motors and brake coils and so on. I know this because I first tried to do with out subs.

The reality is that it all depends on your application. If not using subs works for you then great. Personally I'm not going to sit here and tell anybody they should or should not use subs without knowing anything about the application. The only obivious point would be if the sub were to be called on every scan then it would be pointless and slowdown execution time. If the sub were to be called infrequently, and it places the machine in a totally different mode, then the use of subs will likely increase proformance.

With all that in mind, proper flowcharting of your program should reveal the need to use subs or not.

Happy fathers day!!!

Mike.
 
I use subroutines simply to 'organize' my ladder. The 'main' program has very little actual code. The majority of it is consists of the subroutine calls, and nearly all of the calls are unconditional. I don't think I have ever nested subroutines, but that's only because I've yet to find a need for it.

I prefer AB's GUI over others when it comes to subroutines. I'm surpised that others don't lay it out this way. I like the fact that each subroutine is shown as a separate file, instead of 'tacking on' all the subroutines after the END statement, making just one LONG file. You do a lot less scrolling... :nodi:

beerchug

-Eric
 
Mike...

You said...
"...only the instructions in the main body of the program, and called subrutines will be scanned."

It would be more accurate to say...
Each rung in the main program and each rung in any called sub-routine is subject to the possibility of scanning.

PROGRAM #1

Rung-1 "Hello World!"
Rung-3000 END


How fast will Program #1 run?
How many rungs in Program #1 will in fact be scanned?


Now, how fast will this program run?

PROGRAM #2

Rung-1 "Hello World!"
Rung-2 Go To Rung-3000
Rung-3000 END


How many rungs in Program #2 are in fact scanned?


If, for whatever reason, we really needed to write and rewrite the phrase "Hello World!" as quickly as possible, which program would do it better?

Obviously, Program #2 will blow Program #1 out of the water. Of course, Program #2 doesn't do anything more than write and rewrite "Hello World!".

But the point is made. Both programs are the same size and yet Program #2 leaves Program #1 standing in the dust as far as scan-rate is concerned. This is because of the difference in logic-flow management.

Obviously, we would like to have programs do a little bit more than running around yelling "Hello World! Hello World! Hello World!..."

So... is there a way to maximize the scan-rate while actually doing something?



PROGRAM #3

Rung-1 If don't need to exercise Module-0 then Go To Rung-1000
  • Module-0 code
  • Module-0 code
  • Module-0 code
Rung-1000 If don't need to exercise Module-1 then Go To Rung-2000
  • Module-1 code
  • Module-1 code
  • Module-1 code
Rung-2000 If don't need to exercise Module-2 then Go To Rung-3000
  • Module-2 code
  • Module-2 code
  • Module-2 code
Rung-3000 END



In this arrangement, the smallest scan-rate would be based on the time required to scan Rung-1, Rung-1000, Rung-2000 and Rung-3000.

That is a 3000 rung program being scanned as if it were only 4 rungs long. The scan-rate advantage is obvious.

Now, the actual coding is a little more complicated than what I have shown.

On "Start-Up", the following conditions are FALSE:
  • Don't need to exercise Module-0
  • Don't need to exercise Module-1
  • Don't need to exercise Module-2

While in a particular module, the program might do something that requires follow-up. For instance, if, while in a particular module, the program starts a timer then, if for no other reason, the program will have to revisit the module on the next scan just to check on the timer (there might be reasons other than timers). In that case, the program reasserts the FALSE status of the "Don't need to exercise Module-X" condition.

If the program goes through a module and at the end of the module there is no internal reason to revisit the module then the "Don't need to exercise Module-X" condition is set to TRUE. In that case, the program hasn't done anything inside the module that requires further attention.

Now, like I said, the code above is very much simplified. There is also code that monitors those external activities that apply to the particular module. So, depending on external activities, the program might determine (at the top-most level) that there is a need to visit a particular module.

So, the program might visit a module because of external conditions or because a previous visit to the module requires a follow-up.

Modularity should be extended all the way down to individual output devices. It might be the case that Module-1 contains some sub-modules; Module-1A, Module-1B, Module-1C,...

Each of those sub-modules is subjected to the same control scheme that exists at the top-level. That is, at the upper-level of Module-1 there is a set of conditions similar to the conditions at the top-most level:
  • Don't need to exercise Module-1A
  • Don't need to exercise Module-1B
  • Don't need to exercise Module-1C

As the program goes deeper and deeper within a particular module, the corresponding "Don't need to exercise..." bits are SET or RESET accordingly.

So, if Module-1 contains 50 sub-modules (Module-1 might be several levels deep), and there is a cause to visit or revisit Module-1, then it might be the case that only 2 or 3 of the sub-modules get visited... or maybe all 50 need to be visited.

The concept is to use only those tools (sections of code) that are needed and only when they are needed.

Depending on the particular application, the scan-rate might vary widely, but each scan will be as short as it can be for the particular set of circumstances. Of course, this scheme has no affect on over-head (over-head time is generally fixed). However, this scheme brings the control process as close to real-time as it can be.
 
Doug-P said:
A situation has arisen which will probably require some logic to be rewritten. There is a philosophical (so far :)) disagreement between myself and two of the other programmers.

They are of the opinion that when multiple actions are needed to get something done that each routine be called in its turn from the main line program until the result is achieved. (nesting bad!)

My position is: make one call from the main program and let the subroutines call whatever other subroutines are necessary.

What does the forum say?

I agree with Doug. I could not and would not write 'C' code any other way. An S7 programmer would also agree. The user can write functions or function blocks to effectively extend the instruction set of the S7. I would also use nested subroutines in ladder when it makes sense. However, I think the reluctance to use nested subroutines is due to the difficulty of debugging because a nested subroutine can be called from many places in a program. Ladder does not provide adequate debugging tools for debugging subroutine calls with ease like one can do in C. The only PLCs that I have seen with a single step are the Rockwell onces.

PLCs need to have a real time trace, single stepping, break points and a call stack to make debugging easier. Then the nested subroutines would not be an issue.
 

Similar Topics

I have a bender table that I am automating. I have added a Kinco HMI and PLC, I am also using an Omron encoder sensing the rotation of the table...
Replies
49
Views
9,231
See image below. Look at line 95. I tested all data type, but none of them works. https://ibb.co/H2Csr15 See this. TEMPDATA2 is used only...
Replies
3
Views
2,687
With RS5000 and a Clogix, I would like to know if i can work with same coils adresse on 2 different subroutine and just call one at the time? I...
Replies
13
Views
3,101
When the subroutine is no longer being called, and then called up again, what happens with one-shots in that subroutine? I have some rungs in...
Replies
12
Views
3,011
Hi Friends How can I create/Call in a subroutine in GXWork3/GXworks2?
Replies
4
Views
1,538
Back
Top Bottom