Merging Strategies

Is there a way of merging two strategies together in PAC Control Basic 9? I know that you can import/export charts but I’m looking for a faster solution that would just dump all variables, I/O units, charts, etc. together into one strategy.

I realized this may be a bit of an obscure request but for those of us who have template strategies they like to work off of to develop customized solutions for individual clients, this could be a real timesaver!

Hello Arlin,

Wow, I’m guessing you must have some really huge strategies you want to combine… since the process of exporting charts is pretty quick, ditto for importing those charts into the other strategy you’d like to “merge.” How many charts do you have in your strategies? Are you using subroutines at all?

Also, I’m guessing that you’re “real” charts (those that end up as your “customized solutions”) are much smaller than this monster-merged strategy you seek. Is that correct? You want to merge them as a way of keeping them organized?

Speaking of keeping things organized, since we don’t currently have a way to do version control or some kind of “configuration management” on your strategies and projects, I’d be interested in hearing how you keep track of different versions of these charts, strategy, and any PAC Display projects you have in the mix.

Thanks for the question!

I wouldn’t say the strategies are massive (at least not by my standards!). Here’s where that question came out of…

We do a lot of work for processing facilities where the product flow, points monitored, HMI, etc. is quite similar from job to job. However, every facility has it’s own little quirks or different ways of doing things we have to take into account. Sometimes it’s different pieces of equipment that the customer wants monitored in a different manner. Sometimes it’s a different number of storage/supply bins or surge hoppers along the way.

Basically how we currently approach programming a new job is to set-up a new strategy with that customer’s specific I/O layout. Sometimes the I/O is somewhat similar between jobs, other times it can be very different. How we handle monitoring the various points in the facility however, is very similar. So once we setup the new I/O, we go back to our “template strategy”, import the charts from there into the new strategy and modify the programming to point to the appropriate I/O points and variables.

Usually there are variables that wind up unused or duplicated I/O points that one has to go back and weed out (I guess I’m a minimalist that way… try to keep things as efficient as possible). So going the route of exporting/importing charts understandably takes time.

I guess maybe what I’m looking for is a command that would let you export an entire strategy and import it into a new one. I hope this maybe clears up what I’m asking.

I’m not looking to merge existing charts together to organize them… I’ve been pretty careful with keeping the number of charts in a strategy fairly low to keep things simple within reason.

To answer your question about organization, it’s really nothing spectacular. As each unique strategy is developed, it is saved in a folder specifically relating to that customer. The “template” I speak of is stored in it’s own folder. Everytime I update my template, I make sure the previous one is archived and then just right overtop the template strategy. That way if something doesn’t work in my update, I just restore the previous archive. If a specific customer decides they want changes or expansions done, we handle it much the same way in their own specific folder.

You are right though, organization is very key to eliminating confusion when programming!

Hi Arlin,

A few things you mention above jump out at me:

[B]First[/B]: “… I make sure the previous one is archived.” Excellent. Archive often–hard drive space is cheap, your time is not!

[B]Second[/B]: “… product flow… similar from job to job.” That makes me think you might benefit from using Subroutines or at least pointers. You could pass values to your subroutines, or have your pointers loop through different sets of points, depending on the customer, with different flags to indicate things like “number of storage/supply bins” and perhaps save yourself some time when it comes to the per-customer customization.

For a good example of how you might do that, I’d recommend taking a look at the “I/O Enabler” strategy (which is also helpful if you might ever lose communication to your I/O units for any reason). This strategy is installed with PAC Control, typically in a folder that looks something like:
C:\Program Files (x86)\Opto22\PAC Project 9.0\Control Basic Examples[B]IO_Enabler for Enet & PAC Brains[/B]

Or can be downloaded from the Opto 22 website here.

Pay special attention to the pink “User Initialization” OptoScript block in the chart called IO_Enabler_Chart. That’s where the pointers that get used throughout the code are pointed at the actual hardware.

[B] Third[/B]: “export an entire strategy and import it into a new one.” Why not just copy the whole strategy and delete the parts you don’t need? Because you’re right: exporting/importing charts takes time, but deleting stuff out of your strategy tree can be extremely zippy! Here’s another Forum entry on clean up.

Of course, you can’t delete something if it’s being used in the strategy somewhere and therefore has a non-zero “Ref Count.” So, you can just remove all references to specific tags and replace them with a pointer to that tag (like I/O Units in the case of that “I/O Enabler” strategy). In that strategy, you’ll notice if you right-click on any of the I/O Units in the strategy tree, then do a Find, the only place those tags show up is in that pink “User Initialization” block I mentioned above.

Once you’ve replaced all the customer-specific tags with a pointer, you’ll be able to delete those tags that now should all have Ref Counts of 0.

Of course, you’ll need to initialize all those pointers to your strategy/customer-specific tags, preferably in one place – like that “User Initialization” OptoScript block. That way, when you go to customize your copied strategy, you can do it all in one place. You’ll also be able remove (or /* comment out */) all that initialization code temporarily and easily delete the customer-specific stuff for the next version of your strategy.

Sounds like you’re already in this habit, but I’ll mention it a few more times because it’s so important: during this whole process you’re doing lots of archives (for our newbies, in PAC Control config mode, go to: File > Archive Strategy). This is in case you want to go back to a previous version for any reason.

I hope that helps or at least gives y’all something to ponder and comment on.

Write on!


P.S. - If you ever go to delete a tag that is not found in the strategy anywhere, yet has a non-zero Ref Count, use this process to make PAC Control re-calculate all Ref Counts:

  1. Click in the Strategy Tree to make it the active window.
  2. Press CTRL+R.
  3. Choose Compile > Compile All.
  4. Choose File > Save All.
    The strategy database is rebuilt and the reference counts should be correct.

Thanks for the tips Mary. We do use pointers to a certain extent within our strategies. Sometimes the level of customization required means there’s no real time savings there but for the most part, that is an important point.

I’ve stayed away from subroutines somewhat because of lack of experience/knowledge in them and sometimes it just seems easier to do without. I program mostly in script blocks… I find it more efficient to debug a chart containing a few well-organized script blocks than a large chart filled with lots of action blocks, etc. Often it seems faster to just write a script block containing direct links to I/O points rather than go to the effort of passing values or I/O points in and out of a subroutine. A lot of our programming revolves around outputs changing states depending on the states of certain inputs. Subroutines is something I will admit I should explore further especially if it’s a task I’m using heavily from strategy to strategy.

One important point I want to raise regarding deleting variables with a reference count of “0”… Make sure (before deleting them!) that those variables aren’t referenced anywhere in your HMI. I on occasion will use a variable that is not touched by my strategy but does change state or value based upon input from my HMI (which in turn would be used to control visibility of another object in my HMI for example).

Hi Arlin,

Glad to hear you’re using pointers, and thinking about subroutines. I was just putting together some training content on the joys (or at least the when/why/how) of subroutines, using and example of some OptoScript code I recently converted to a sub for easier re-use. I’ll share that when I get it all polished.

Also, I’m glad you mentioned the caution about deleting Ref Count zero tag (I did mention this in that earlier post on clean up, but, like archiving, I think it can’t hurt to re-emphases to help prevent future frustration for other folks).

You got me thinking, though, perhaps we could reduce the odds of such and accidental removal by [B]purposely making the strategy’s Ref Count non-zero[/B] for such a variable. For example, perhaps in the Powerup chart somewhere (with lots of comments explaining why), you could have an OptoScript statement like:

// This line of code is included here to reduce the odds of an accidental “clean up”
// by causing a non-zero Ref Count since this variable is not currently used in this strategy
nHMIflag = nHMIflag; // This variable IS used by the PAC Display project such-and-such.

(A regular action block could do the same with with just a Move command where the variable is moved to itself.)

You don’t even need to have your logic flow through the code–it could be in an unattached block floating off to the side, with plenty of comments of course–that’s another one of those things we can’t emphasize enough! Would be good to at least mention the non-strategy entity that needs it, in case that changes later.

What do you think?

I think that’s a good idea. I would absolutely make sure in the comments to describe what specific purpose that variable has in PAC Display (or elsewhere). Nothing is worse than going back to a project a few years down the road and trying to remember why you programmed things in the manner you did!

Do not fear the subroutine. I have only recently started using them and with 20+ controllers, using subs has been pretty easy way to update strategies with common functions. example: there is a sub routine that i have written to dump data into a sql database. this runs on every controller in the installation (these are a mix of pac and factoryfloor controllers so therefore 2 subroutines) and if i need to add a change in the subroutine logic, it gets altered in the sub and then a download will see the changes take effect.
there is no importing of charts, renaming, copying and pasting of blocks etc… its very very seamless (unless you change the parameters sent/returned from the sub). This may benefit you with your ‘master template’ as any changes aren’t directly applied to the strategy but the subs of that strategy. and if the directory structure is in place, this would mean that the subroutine changes will roll on automatically to your existing strategies (as the subroutine reference will be static).

Also, we have a string variable in the installation here that is updated directly from the HMI and not utilized in the control strategy at all. it has been deleted once or twice so i ended up putting a description for the variable as ‘DO NOT DELETE!!!’. haven’t had the problem since.