Jump to content

advice on "main routine" structure


Recommended Posts

Hello all,

 

I am a beginning plc programmer and I have to program a small machine.  Since the machine is a prototype, it is not needed to have a perfect program with good fault messages or the ability to run slow or anything like that. I just like to have a simple yet safe program to prove that our prototype will do what it's supposed to do.

The machine has a start and stop button and it needs to home before it can run in automatic mode. I would also like to split up the automatic cycle in some subroutines.

I made some example code that I would use for the main routine. Would this be good code to start from? Or am I missing something rather important?

Thanks for anyone who can offer some advice!

 

main routine structure.JPG

Link to comment
Share on other sites

  • MVP 2023

If ladder rung #1 is supposed to be a standard latch circuit, it's wrong - MB 2 should be MB 4.

I think conditional subroutine calls are very poor programming practice. You have to be extremely careful not to leave coils hanging in limbo when the subroutine stops being called.

With PLC ladder logic, the next subroutine is normally called when the previous subroutine is finished - and not before. You don't need a bunch of code to create that situation, as you seem to be doing here.

 

Link to comment
Share on other sites

6 hours ago, Flex727 said:

If ladder rung #1 is supposed to be a standard latch circuit, it's wrong - MB 2 should be MB 4.

Ofcourse! I should have seen that ..

6 hours ago, Flex727 said:

I think conditional subroutine calls are very poor programming practice. You have to be extremely careful not to leave coils hanging in limbo when the subroutine stops being called.

With PLC ladder logic, the next subroutine is normally called when the previous subroutine is finished - and not before. You don't need a bunch of code to create that situation, as you seem to be doing here.

Well, the problem is that each subroutine will take numerous scans before it is finished. This is because each subroutine will contain rungs where I am waiting for a motor to be in position. So I cannot just let subroutine 2 start if something in subroutine 1 is not finished...

edit:

I should probably have mentioned that I am using a counter and compares at the start of each rung in the subroutines to see if I can execute that rung (sequential program). Now that I think about it, I could use values for that counter from 0 to 100 for subroutine 1, from 100 to 200 for subroutine 2, and so on, and then I would no longer need the "sub 1 done" bits to trigger the start of sub 2. Just need to make sure that the counter at the end of sub1 is 100 so sub 2 will continue after that...

Link to comment
Share on other sites

  • MVP 2023
5 hours ago, acisre said:

Well, the problem is that each subroutine will take numerous scans before it is finished. This is because each subroutine will contain rungs where I am waiting for a motor to be in position. So I cannot just let subroutine 2 start if something in subroutine 1 is not finished...

edit:

I should probably have mentioned that I am using a counter and compares at the start of each rung in the subroutines to see if I can execute that rung (sequential program). Now that I think about it, I could use values for that counter from 0 to 100 for subroutine 1, from 100 to 200 for subroutine 2, and so on, and then I would no longer need the "sub 1 done" bits to trigger the start of sub 2. Just need to make sure that the counter at the end of sub1 is 100 so sub 2 will continue after that...

You are trying to program like you would a computer with some other language, not program a PLC with ladder logic. PLC ladder logic should be organized completely differently. Every rung of every subroutine should be evaluated on every scan.

You probably should be using a State Machine instead of what you're trying to do. Our resident genius, @Joe Tauser, has written an example program to help educate us on this terrific technique to handle the type of situation you are trying to deal with.

Looking at your edit, it appears you might be headed in the direction of a State Machine, which is great. Look at Joe's example program and see if it helps you.

 

Link to comment
Share on other sites

Hi Joe,

 

I think I did something similar to jour state machine code. I hope my code will be finished in one week from now...  will post it then.

 

It is getting quite complex. I think i need to find a trade off between readability of the code vs not making things to difficult...

for example: i have a subroutine called « MoterToPosition » , so in my main routine I just store speed, acceleration and position into some bytes and then call that subroutine. That way, the code gets shorter and more readable.

However, things also get more complex now:

  • For one, it is possible to call the subroutine but only one rung in that subroutine gets executed. This is because all the rungs check the SB242 (SDO in progress). So now i need to make sure that in the next scan, the remaining rungs in the subroutine get executed. So i need to remember where I stopped using again a counter etc....
  • I also need to make sure that my main routine keeps calling that subroutine untill it is finished. So now i need a « I am finished » bit that the subroutine sets high when the last rung is executed. In the main routine I can then check that bit to see if I can go into the next state
  • Also, it is possible that in my main program i will call subroutine « <MoterToPosition » twice in one scan, so now i need to implement a « I am busy » bit to indicate that the second call should not start if the first call is not yet finished...

I am starting to think that it might be better to just throw this subroutine away and place all the rungs in the main routine again, at the cost of having a much longer and less readable program.

 

Thx for all the help

 

sven

Link to comment
Share on other sites

  • MVP 2023
5 hours ago, acisre said:

So now i need to make sure that in the next scan, the remaining rungs in the subroutine get executed.

 

5 hours ago, acisre said:

I also need to make sure that my main routine keeps calling that subroutine untill it is finished.

 

Please allow me to repeat what I said above:

23 hours ago, Flex727 said:

Every rung of every subroutine should be evaluated on every scan.

Write your code with this in mind and you'll have much more success with PLC ladder logic, now and in the future.

Link to comment
Share on other sites

16 minutes ago, Flex727 said:

Please allow me to repeat what I said above:

Write your code with this in mind and you'll have much more success with PLC ladder logic, now and in the future.

But then you are basically telling me that, if I can't find a way to make that subroutine evaluate everything in every scan, it should not be a subroutine at all? I just don't see a way around the SB242 without skipping motor messages

I added the subroutine to provide more clarity.

 

 

 

MotorToPosition.vlx

Link to comment
Share on other sites

  • MVP 2023
1 hour ago, acisre said:

if I can't find a way to make that subroutine evaluate everything in every scan, it should not be a subroutine at all?

I'm offering advice based on my experience. You're free to accept or ignore it as you choose. My way of doing things is my way, not the only way. My philosophy is to never use GoTos or conditional triggers for subroutines. I find that it's a better way, but it's not the only way.

In my opinion, subroutines in ladder logic should be used differently than subroutines in normal computer programming. A normal computer program has a beginning and an end with subroutines for specialized tasks. In ladder logic, you have continuous execution of all code in a never-ending loop. Going off to execute a subroutine for a specialized task, or using GoTos, risks triggering the Watchdog Timer, which is a major fail for the programmer. I use the Main Routine only for Power-Ups and subroutine calls. Then all the code is broken up in logical chunks for easy understanding and readability into subroutines.

Link to comment
Share on other sites

2 hours ago, Flex727 said:

I'm offering advice based on my experience. You're free to accept or ignore it as you choose. My way of doing things is my way, not the only way. My philosophy is to never use GoTos or conditional triggers for subroutines. I find that it's a better way, but it's not the only way.

In my opinion, subroutines in ladder logic should be used differently than subroutines in normal computer programming. A normal computer program has a beginning and an end with subroutines for specialized tasks. In ladder logic, you have continuous execution of all code in a never-ending loop. Going off to execute a subroutine for a specialized task, or using GoTos, risks triggering the Watchdog Timer, which is a major fail for the programmer. I use the Main Routine only for Power-Ups and subroutine calls. Then all the code is broken up in logical chunks for easy understanding and readability into subroutines.

Thanks Flex727 for all the advice so far. I am here to follow the advice of professionals, not to ignore it :-)

I think I do know what I have to do now. Im going to create more subroutines to keep everything more readable, but all of the subroutines will be read one after another and they will all share the same state counter. That way I don't need the conditional triggers you are referring to.

You are right that I try to program it to much like a computer (it's the only other programming experience that I have)

Link to comment
Share on other sites

  • MVP 2023
3 hours ago, acisre said:

You are right that I try to program it to much like a computer (it's the only other programming experience that I have)

I came from a computer programming background as well and I think that was probably the hardest thing for me - unlearning ingrained habits from that world. PLC ladder logic is fundamentally different and failing to wrap one's head around that is probably the most common  problem I see with new PLC programmers.

Joe Tauser's State Machine example shows the proper way to handle situations where you are stepping through a process sequentially and want to avoid code until it's time for it. It definitely opened my eyes some years ago when he first posted it here.

Link to comment
Share on other sites

  • MVP 2023

The fundamental idea of the State Machine is that it is based on the value of a numeric pointer and Equal blocks.  There's nothing to say that you can't have multiple pointers in different subroutines that rely on each other.  

Get the idea of how many times you call the subroutine and the enable bits out of your head.  Call all the subroutines all the time, and use state values that do nothing but wait for something else to finish to move on.

Take a look at the attached program.

Joe T.

MotorToPosition JT.vlp

Link to comment
Share on other sites

13 hours ago, Joe Tauser said:

The fundamental idea of the State Machine is that it is based on the value of a numeric pointer and Equal blocks.  There's nothing to say that you can't have multiple pointers in different subroutines that rely on each other.  

Get the idea of how many times you call the subroutine and the enable bits out of your head.  Call all the subroutines all the time, and use state values that do nothing but wait for something else to finish to move on.

Take a look at the attached program.

Joe T.

MotorToPosition JT.vlp

Hi Joe,

 

Thank you for the time you took to create that program.

I don't think that the timers you added are of much added value. If the timers or to long I will loose a lot of time (my program is more then 100 rungs and almost all of them send SDO instructions or read info from the motors via SDO upload). The machine needs to go as fast as possible (current cycle time is 7.5 seconds, I want it to be 6.5 seconds or less. And in that time approximately 30 actions are done. That gives me an average of 0.2 s for each movement. Having timers of 100ms will make it impossible to achieve that.

However If I make the timers very short like 10ms then basically you can then just leave them out and simply check for the bit SB242. If not ok it will probably be ok in the next scan or the scan after that.

About the "call all the subroutines all the time".  Isn't it an advantage to just call the subroutine only when you need it, to make the PLC just read the rungs that if needs to read at that time an not slow it down unnecessarily? Just asking, not planning on adding conditional subroutines at the moment but that seemed like an advantage of having conditional subroutines.

 

Sven

Link to comment
Share on other sites

  • MVP 2023
6 hours ago, acisre said:

I don't think that the timers you added are of much added value. 

 

6 hours ago, acisre said:

However If I make the timers very short like 10ms then basically you can then just leave them out and simply check for the bit SB242

Unitronics has an underlying feature of advanced function blocks taking a scan or two to update their busy bits.  I added the timers because I have no idea what the response time of the SDO block is.  You may be able to turn them down to 0.01 seconds or eliminate them completely.  You'll have to load the program to find out.

6 hours ago, acisre said:

About the "call all the subroutines all the time".  Isn't it an advantage to just call the subroutine only when you need it, to make the PLC just read the rungs that if needs to read at that time an not slow it down unnecessarily?

100 rungs is a not a large program size.  Look at your scan time - it will probably be on the order of 5 ms.

 

Many of the statements you have made in this post sound like guesses and considerations.  Have you loaded a program and tested it yet?

Joe T.

 

 

Link to comment
Share on other sites

4 hours ago, Joe Tauser said:

Unitronics has an underlying feature of advanced function blocks taking a scan or two to update their busy bits.  I added the timers because I have no idea what the response time of the SDO block is.  You may be able to turn them down to 0.01 seconds or eliminate them completely.  You'll have to load the program to find out.

Aha ok, now I understand.

4 hours ago, Joe Tauser said:

100 rungs is a not a large program size.  Look at your scan time - it will probably be on the order of 5 ms.

 

Many of the statements you have made in this post sound like guesses and considerations.  Have you loaded a program and tested it yet?

Joe T.

Yes I have tested a code without timers, and it worked fine. I have added a little program with some subroutines from the complete program. This is all tested and works.

I don't know If I will keep the subroutines like this. Here they were intended as reusable code but they are not called all the time.  Probably will change that as Flex727 recommended.

Sven

example_for_forum.vlp

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

This site uses cookies. By clicking I accept, you agree to their use.