Long running subroutines

I’m using Groov Epic. My strategy initially had the Startup, which polls for a StartRequest for each Node, starts the applicable Node n chart, which runs the process approx 2 hours, and then each chart exits.
I was starting to duplicate/rename these and join them up, but it seems like subroutines, would be more effective (and read manual section and watched the making subroutine (averaging inputs) video). I have converted the working Node1 chart to a subroutine, taking:
2x analog Ins(Temp, Pressure), 1x digital Out (Relay), and some variables to control start/abort and show temperature targets.
I’ve implemented these within the Startup chart using:
ActionBlock: subroutine with Node1 params
ActionBlock: subroutine with Node2 params.
… etc and will do so for Nodes 3 through 24 once I get it working.

Trying to use the debugger breakpoint and step into:
Startup → Node1 subroutine > Check for Start var, Delay, Check for StartRequest var, then seems to goto Startup (Delay1) > Node2 subroutine > check for StartRequest var etc, and then onto 3.
It looks like it does this just once for each subroutine, and that the processing seems to completely finish, i.e. the subroutines don’t continue running.

Can I use subroutines in this way ?
What do I need to do for this use case ?
The goal is that all subroutines initialize and are checking for the StartReq variable (and when received start the process control loop).

I read a little about multitasking: the processor yields at a delay to let other code operate, but once yielded, where does the processor resume within the first subroutine ?
Or is the sub just called again and again, and would I then need to create a flow chart loop on Startup from last Node back to first Node actionblock ?

my subroutine:

Welcome to the Opto Forums David.

I have never used or seen subroutines used like this before.
@philip Have you?

Usually a subroutine ‘falls through’ pretty quickly, like converts a temperature and is done.
Looping a sub for 2 hours… hmmm, just not sure.

The time slice question I can answer. The subroutine takes the time slice of the calling chart.
I think that is part of the issue with your method. The Powerup chart calls the first sub and so gives up its CPU time slice to that first sub, which then loops for 2 hours. (If I understand your description correctly).

I have one (and only one) project where I am using a subroutine that does not exit until the batch process is complete. I am not using it like @david.timms is though, but he may be able to do something similar as this, but I don’t completely follow what he is trying to accomplish.

The reason I used a long-running subroutine was to update an inherited project where there were four identical manufacturing lines with each running in its own chart. Normally I would use a single looping chart with tables and pointers, but I didn’t want to do a major rewrite for this project. So to minimize the labor expense of writing the same code four times, I moved the logic into a subroutine and then call the subroutine from each of the four charts. It all works without issue.

I am not seeing any benefit for @david.timms using subroutines in the manner he is using it though, as he has discovered the subroutines are synchronous - meaning when you call the subroutine, the calling chart is blocked until the subroutine finishes. And it doesn’t look like his sub ever exits (unless I am missing it), so Node 2 and Node 3 will never run. I’m also concerned with that the “Initialise Subroutine” block also doesn’t seem to be included in the flow.

If his “nodes” are all the same, he may benefit from structuring them like the project I mentioned, otherwise just putting the logic into separate charts and not using subs may be best.

1 Like

I think I understand what @david.timms is going for here, but he’s going to have to make some code changes.

I like the idea of a subroutine, because you’re re-using the same code for a bunch of different inputs and outputs. However, you would essentially need 24 separate charts, each of which starts your subroutine with different inputs and outputs, to have the subroutines running at the same time.

Because your subroutine never ends, your Powerup chart should never execute past the first block (Node 1 subroutine) because the execution is stuck inside the subroutine. Instead, create 24 charts (Node1, Node2, etc.). Start each of those charts in Powerup. In each of those charts, the only command could be starting the subroutine.

1 Like

Also, I think I know why your subroutine is ending. Your line from start skips “Initialize Subroutine” and “Delay 250 msec” and goes straight down the condition block “User started?”, going behind the other two blocks. If that condition is false, you go to the “toggle _heater” block, then to the delay block, and then your subroutine exits because there’s no connection from the delay block.


Whoa! @varland Nice spot!
I totally missed it.

I highlighted it since its easy to miss…

EDIT: there might be a connection from the delay block the ‘User started’ condition block, it might just be doubled up with the Start block connection.
Hint, never overlay connections and thus arrows, offset them so you can see what joins what.

1 Like

With 24 of these, if they are all the same, I would recommend using tables and pointers and building it in one looping chart. It’s a bit more advanced and will require some learning time, but then when you go to fix a bug or add a feature, you only have to do it once for all of them.

Old post on using pointers (and tables) that may give an idea or two: PAC Control 101: Why/when/how would I use POINTERS?

1 Like

@Beno: I assumed there was not a doubled-up connection because the subroutine wouldn’t end if there was, as far as I can tell.

I agree with @philip about using pointers for this task instead of subroutines. Using pointers would allow this task to be accomplished with a single chart, and there are definitely reasons to not run 24 charts at the same time if you can avoid it.

Thanks opto22’ers for noting that connection problem, I’m not sure if it’s just in the screen_capture/printing problem. I’m away from my PC for a few days, so can’t check.

From the answers, I take it that to have simultaneous threads of execution, I would need that number of charts (+ startup chart) ?

Yes, that’s correct. A total of 25 charts.

Thanks for noting that, indeed it was the fault; as I’m driving the Start variable via the C# managed SDK. There was the need to “use” the Input values, so that the fresh value would be read from the EPIC.

I looked at the tables & pointers info and demos, but it seemed more complicated and harder for long term support reasons. Given the subroutine can be used in this way, I have been able to move forward using a single subroutine in each of 24 charts, with the Powerup chart starting all of them.

Initially implementing the subroutines use an Action block, I changed this to Script block, as it made it easier to: adjust the subroutine parameters (comment the subroutine out, add/delete params), which was difficult using the Action block as I had to clear all users of the variables/values before I could change the subroutine parameter block, and then change them back after changing the subroutine params.

Cheers all for your fast responses and sharing your experiences / usages of the product.