Break out of a subroutine?

I am building a subroutine called subLeachLine hat will run a leach line for an up timer amount of time. The sub is called by an OptoScript block that is running a while loop. The while loop runs as long as the leach field (1 or 2) is enabled. I want the current leach line being called to stop running immediately if the current leach field is disabled or if the line is disabled. I know that I can watch for the line itself to be disabled within the sub, but I’m not sure where or how many times I want to check… but if the leach field is disabled, the original while loop that calls the sub will not quit and shut down the sub because the processing of that chart has suspended while the subroutine subLeachLine that it called is running. Am I correct?

So, if I want to shut down the current leach line in either instance I would have to check if both the current line or the current leach field get disabled somewhere during the subroutine…correct?

In my SCADA program I used to write ‘watchdog’ blocks to do this. They would simply run and say if disabled, then shut down subroutine and leach line and reset. Is that the best way to do it in this instance (as in a chart that just watches anything I want to disable) or would it be better to pass the ‘leach field enabled’ variable into the sub as well as the ‘current line enabled’ variable and shut it down from the sub?

Right now I’m wondering if instead of doing all of this code with the flow chart, maybe I should have just encapsulated all this code in OptoScript between some ‘while’ loops within my subroutine instead? No way to build that with the flow chart programming is there?

It’s hard to decide because with limited programmers (me) where I work, I don’t know if the person doing this after me would do better with OptoScript code or if they would do better with the flow chart… Thanks to the OptoForums for being my fellow programmers to collaborate with since I have no one here to bounce ideas off!

For your first question, yes, when a subroutine is called from a chart, it’s just like any other command (e.g. Delay) where it takes however long to run, and in the meantime, the next command just waits until that call to the subroutine finishes/returns. So if you want the subroutine to finish sooner based on some flag, you would have to pass that flag to the subroutine.

Re: OptoScript vs. flow charts, everything you can do in OptoScript blocks can also be done in action/condition blocks and vice versa. OptoScript just makes some stuff easier, like math/formulas, while loops, building strings. Also, you typically need fewer blocks (and sometimes fewer temporary variables) if you do things in OptoScript blocks. I like a combo for the visual debugging part and to help make it clear what the chart is doing, generally.

Also keep in mind that a subroutine is good for re-using code, and you can have as many as you want. So if you find the subroutine you’ve built is getting big and needs more parameters passed to it, consider breaking it into smaller pieces (where you can check that flag you mentioned in between calls to the different subs, or each time through your while loop in the calling chart).

I hope that helps/makes sense!

Thanks for the great input I have been getting!

Here is the chart in question:

Would you think based on this it would be better to do this in OptoScript with a while statement to to handle the “watchdog” issue I mentioned? The option I show here is the extra two condition blocks taking care of it. They would shut the lines down pretty quick at that point in the program, but not if I needed them shut down immediately at any point during the program.

Thanks!! I love figuring out how to do things, but I’m glad to have others to gain insight from since I’m still an intermediate…

This would be my concern with the approach you have taken here. I would try to avoid using delay commands for process control and use timers instead, so instead of waiting and having no control during that time, you can simply check if the timer is expired and move on.

See if you can keep track of the state of your process and use conditional blocks that check the current state and run the appropriate actions. This will allow your code to run once through and exit. This will allow you to use this code for multiple processes at the same time.

I like to handle all safety and alarm checks at the beginning of my control program as well so it is clear that appropriate action will be taken.

Is there a better way to do this than the delays? There is a reason why I’m delaying. I open the line valve, but then it takes a little while before the flow sensor to actually show flow after the valve is opened so I have to wait before I check for flow. This is the same on the shut down end of the program and it actually takes longer for the flow valve to show no flow rather than when it first shows flow.

That’s part of the reason why I thought that it might be better to use OptoScript with a while loop. That way I could just do ‘while leach field enabled and leach line enabled’ run the program.

When you said you handle all safety and alarm checks at the beginning how does that work if you cant make that check until after the condition?

Timers are better than delays. You setup a timer for 30 seconds, and if you don’t detect flow and the timer expires, then you alarm. During that 30 seconds, your chart can be doing other things - controlling other leach fields, etc. If for some reason the high float tripped during the 30 seconds or some other safety, you can immediately begin the shutdown.

Thanks for your reply phillip. I have been out of town so I’m just getting back into this. I removed my ‘Line Enabled?’ condition as I realized that I already covered that in my OptoScript block that called this subroutine.
The mode = startup? confused me. Is that to replace the ‘Current Line Still Enabled?’ Condition I had? It looks like there isn’t a timer started in this before the flow sensor is checked? The reason I had the 30 second delay is because it takes a little bit for the flow sensor to register after the valve is opened. So, I would have to start the timer when I open the valve and then have two conditions in the ‘flow?’ block that say if ‘timer > 30 seconds and flow is on’ then set to running correct?

Another question I have is by putting the ‘high float trip?’ condition before everything it’s not checked after the flow starts, so it wouldn’t disable the line if the float goes high while the line is flowing right?

Welcome back! The chart I posted was kind of a general way to utilize timers and “state” for controlling a process. This would all be wrapped in a loop - that is the part that probably caused some misunderstanding.

This code will need to be called in a loop over and over again - say every 500ms or so. Since we are calling it over and over, we need to remember the state of our process, so I keep that in a mode variable.

Now my flow chart is not complete in anyway - just wanted to get a quick example out to show you how I would utilize timers to control a process.

I’ll try to explain more with each of your questions.

The way I was thinking about this is I would have mode normally set to “shut down”. If I want the process to start, then I would set this to “startup” - this would be somewhere else in my strategy. The code I posted would continue to run over and over, checking the mode.

On startup it will keep checking for flow, and if there is no flow, it checks if the timer expired or not - if not, then we know we are okay and just have to wait a little while to detect flow, so we exit. This happens over and over until we either detect flow or the timer expires. If the timer expires, then we know the startup failed for some reason and we can report that and shutdown or do whatever your process needs.

No, it will check the flow immediately after it commands the valve to open - we don’t care, the code will move on, start the timer on the first time through and exit. Some time later (in 500ms if that’s what we choose), the code will need called again and the flow will be checked again, and over and over again.

The safeties will be checked as often as the code is called. Since we are keeping track of the “state” and are using timers, we can start from the top of the code and know where we are in our process. So the safeties will get checked as often as we go through our loop - so 500ms in our example.

To build on to what I wrote above (the chart) - say for shutdown, I would have two modes - “Shutting Down” and “Shut Down”. So when I am done with the process, I would set the mode to “Shutting Down” - this could be somewhere else in the strategy outside our loop, or in response to a safety in this logic. Shutting down could then command the valve closed, and start a timer and stay in that mode until we detect flow has stopped. Once we detect flow has stopped, then we change our mode to “Shut down”. We then would add a condition for “Shut Down” that will exit - it can still be called over and over, but since we are in mode “shut down”, we simply exit.

I could write more - ha ha. Hopefully I haven’t caused you too much confusion, let me know if I need to explain any of this better.