SQF Cancel not working

Hello, I’m back with another Sequential Function Chart problem,

I am now running 7.7.3 rc1 and while my problem with action blocks running more than once is resolved, I now have a problem when I cancel a chart, it keeps running.

I have a very simple chart to test…

B --> Initialize Globals --> Label --> Log chart and parent chart information --> wait until runningTime % 60 is 0 --> set delay to runningTime + 15 --> Wait until past that delay --> Jump to Label

I’ve been cancelling the chart usually when it’s on the MOD 60 step. The chart disappears from the Chart Control window, but if I watch the logs, it is still running, and will keep running until I stop and start the gateway.

What lead to this, I’m attempting to put together a master chart starter chart that uses a parallel block and several enclosing blocks to start my suite of charts. I’ve started small with only one chart, and have been testing the administration control over the charts. I’ve been finding that when I cancel my control chart, the child charts are restarting quickly enough to eventually crash the gateway.

BTW: your scripting documentation indicates a couple of chart variables that don’t exist for me:
chart.running, and chart.state

Thank you,
Bill S.

Hi,

We’ve been working quite a bit in the last two weeks on improving chart lifecycle control. I’ve attached the latest build here (beta 15), please try it, and let me know how that changes what you’re observing. I think it should be much more reliable now.

Yes, chart.state and chart.running have been removed. This was done first due to some technical changes, but we’re not sure they’re really very useful. Any element will only be active if the chart is active… and this includes Enclosed charts. These were never accessible outside of the chart, as far as I know. That said, if you have a particular example of why you need them, please let me know. Otherwise, we’ll update the documentation to remove them.

This particular build includes a number of new features as well:

  1. step scope now includes ‘name’ and ‘id’ for the step.

  2. There is now a version of system.sfc.setVariable(s) that can take a step id as well and will set the variables on the step scope, if the step is active.

  3. Much more flexibility with using things in scopes:
    i) In scripting, you can use “context.resolve(scopeid)” to resolve a scope
    ii) In expressions (transitions), you can bind to scopes with references like “{scopeid.key}”
    iii) The following scope ids are now available:
    chart - the chart scope
    step - the step scope
    previous - in a transition, refers to the previous (active) step’s scope
    parent - the enclosing chart scope
    root - goes all the way up to the top level enclosing chart’s scope
    iv) You can bind into dictionaries in a scope in a transition. In other words, if in your onStart you had:

step['data'] = {'trig' : 0, 'completed' : 0}

In your following transition, you could use:

{previous.data.trig}>0

Please feel free to provide any feedback here on this version.

Regards,
SFC-module.modl (366 KB)

Thank you for allowing me to test the modules.

It does seem to cancel the chart I tell it to cancel now. Which I tested by setting up a parallel execution that besides doing the enclosing action, also is looping doing a logging step after a delay. The logs do stop now, where they didn’t before.

Regarding the missing chart variables:

I agree with you that the chart.state and chart.running entries don’t help much for the current chart, but I would like to use them in the child chart to see the parent chart’s status. This would require that the values get pushed to the child before the parent finishes terminating/pausing or whatever.

What I’d like to accomplish, is a following of state from the parent charts all the way down to the lowest child chart. I do not however feel that this should be a default, I believe that this type of thing should be doable using the chart.parent.running and/or chart.parent.state variables and transitions in the child chart. Of the two the chart.state variable is more critical.

Example:
Parent Starts Child, Parent is paused, then Child pauses,
or Parent stops for any reason, then Child stops.

The above example should flow down the tree of charts. The tree I’m working on looks like this:

  1. Master Control (Only RunAlways Chart)
  2. Zone Control ( 1 started by the master for each zone, presently 4 zones.)
  3. Application Control ( 1 started by the zone for each application, about 6 of these )
    For a total of about 29 charts running, 24 Application Charts, and 5 Control Charts.

I have attempted to use the chart level onCancel, onAbort, or onStop routines to set a chart variable or a tag memory variable to indicate this for me, but none of the attempts have been successful. The tag variable does not get changed, and the variable in the chart.parent element in the child doesn’t get updated either.

I am able to cobble something using the runningTime variable in the parent chart, which stops changing, but that seems rather fragile. I’d prefer to have at least the documented state variable that should get updated in all the charts that have a copy of the parent chart even while the chart is stopping/aborting/cancelling.

Hi,

I think my main point of misunderstanding revolves around this:

Currently, an enclosed chart is started, and its state is directly controlled by the parent chart. If the parent chart is paused or cancelled, the child chart is paused or cancelled. The parent chart's EnclosingStep is watching the child chart, and on deactivate, will either wait until it's finished, or cancel it, based on the settings.

Are you looking for a way to simply start a child chart and then move on? The child chart would run independently, but could theoretically watch the state of its parent chart?

In my mind, I see the Master Control, with a parallel with 4 Enclosing Steps for zones. Then, each zone has a parallel with 6 Enclosing Steps for the Application. In this case, the sub charts states will all naturally follow the parent charts' states. Is this not what you have in mind? Are you thinking of some sort of a loop that consults something and launches sub chart until completion?

Thanks,

Yes, I believe we are on the same page…

The Zone Chart is as follows. I have no great trust in the automatic pausing and stopping of the child charts, And I wish to be able to easily disable a zone, so I enhanced the watchdog chart to keep track of it’s parent chart as well as the PLC heartbeat.

[code]<?xml version="1.0" ?>

Chart Name: ZoneProcessing

This chart is the master chart for a zone. All the other charts will be started and restarted by this chart.


def onStart(chart, step):
“”"
This will run when the step starts, before any
other action.

Arguments:
	chart: A reference to the chart's scope.
	step: A reference to this step's scope.
"""
shared.WWD_MOM_Chart.ZoneProcessing.defineGlobals(chart, step)
{cancelRequested} = true || tag('[default]'+{zoneId}+'/Flags/ZoneRunning') = 0 {cancelRequested} = false && tag('[default]'+{zoneId}+'/Flags/ZoneRunning') = 1 zoneId{zoneId} runMode{runMode} zoneId{zoneId} runMode{runMode} zoneId{zoneId} runMode{runMode} zoneId{zoneId} runMode{runMode} zoneId{zoneId} runMode{runMode} zoneId{zoneId} runMode{runMode} zoneId{zoneId} runMode{runMode} zoneId{zoneId} runMode{runMode} tag('[default]'+{zoneId}+'/Flags/ZoneRunning') = 1 tag('[default]'+{zoneId}+'/Flags/ZoneRunning') = 0 tag('[default]'+{zoneId}+'/Flags/ZoneRunning') = 1 tag('[default]'+{zoneId}+'/Flags/ZoneRunning') = 0 tag('[default]'+{zoneId}+'/Flags/ZoneRunning') = 1 tag('[default]'+{zoneId}+'/Flags/ZoneRunning') = 0 tag('[default]'+{zoneId}+'/Flags/ZoneRunning') = 1 tag('[default]'+{zoneId}+'/Flags/ZoneRunning') = 0 tag('[default]'+{zoneId}+'/Flags/ZoneRunning') = 1 tag('[default]'+{zoneId}+'/Flags/ZoneRunning') = 0 tag('[default]'+{zoneId}+'/Flags/ZoneRunning') = 1 tag('[default]'+{zoneId}+'/Flags/ZoneRunning') = 0 tag('[default]'+{zoneId}+'/Flags/ZoneRunning') = 1 tag('[default]'+{zoneId}+'/Flags/ZoneRunning') = 0 tag('[default]'+{zoneId}+'/Flags/ZoneRunning') = 1 tag('[default]'+{zoneId}+'/Flags/ZoneRunning') = 0 A B C D E F G H A B C D E F G H L L [/code]