Best practise for unit instances

Subjective question, but still…

The task layout under Physical view is designed for adding programs. This makes it possible to get an easy overview of whats happening.
But when a complete program for a machine with code, control modules, alarms.. becomes a re-usable unit, what is the typical way to go in AS? Duplicating code is not an option.
In Siemens there would be a unit FB or FC and the overview of programs would be inside. This could be done the same way in AS. But instead of a complete overview under Physical it would just call Units or possible Unit_0, 1, 2.
In AS an option is also to index all instances and call unit[n] in each program. The Physical overview could then contain seemingly duplications of all programs in a task but index n would be increased at the start of each unit. This duplicates however the program calls which should be identical for all units.

I would choose the Siemens organisation unless there is a better pattern in AS:

Hi @emedan ,
there is room for improvements in AS that’s why R&D daily review our product requests so I recommend to contact our B&R office in your area and present your product request.

Ciao
Valerio

it’s a best practice request

I’m not sure I fully understand what you’re trying to solve here, but if I had e.g. multiple conveyors of exactly the same type in an application (logic, alarms,etc) I always handled it by having a structure_type and then creating an array of variables of that type, where N was the number of conveyors.

The logic was called from a single task in a FOR loop. The nice thing about this approach was that the code existed only once, so any change was immediately applied to all conveyors. And if I added more conveyors to the application, I only had to change the N constant.

So, for me, this is basically the same principle as FB + instances, just using an array of structures instead of separate instances.

You can deploy the same task multiple times in .sw file.

That’s how I converted my program in question. What still nags me are re-usable functions. The program for one unit is organized in folders for readability; 00_inputs, 10_ various process parts, 20_communication and so on. But the quick and dirty conversion now has FOR loops for the programs in each one. Ideally one unit is processed as a whole. It seems then, that to keep one main FB calling each instance (built from many programs under our understandable structure) like I would organize it Siemens, in AS I need to place all the other code up in Libraries instead, including datatypes. This seems to be the main difference I see currently. But I’m really only after a best practise template organisation of a program running identical units.

Maybe you can share with us printscreen(s) from TIA portal to see what excatly you are looking for?

Do you mean run a task multiple times or a program?

I haven’t figured out how to instance or re-run the complete task.

What I do with this idea is to duplicate all the unit programs in the same task. Each unit program operates (for easy access in other programs) on a global variable unit[x] and the x is updated in the task between instances. So for a low number of units this is easy and managable.

Hopefully an image is worth 1000 words.

Almost. Thanks! Instancing is nicely built-in it seems. And .st actions for internal “funcitons”.

Hello,

as far as I know there is no “good practice” for this, since there are several ways of doing it, like using instances of the task or using arrays and FOR loops which was already mentioned. I am not entirely sure I understand what you would like to achieve. But I am using a different approach, it is somewhat complex, but here is an example how I handle and structure my axes which are always identical:

I create one task called Axis, I put it inside a new user library. Internally the task is using a local variable (structure) called “Internal”.

Internal contains three structure members: Command, Parameter and Status. The code can look like this:

IF (Internal.Command.MoveAbsolute) THEN

   Internal.Status.AxisMoving := TRUE;

END_IF;

However, since my axis must be unique, I also create a global structure variable called gConveyor. Then I create 3 PV mappings:

gConveyor.Command → Internal.Command

gConveyor.Parameter → Internal.Parameter

Internal.Status → gConveyor.Status

Outside of the task I am calling the axis by using gConveyor.Command.MoveAbsolute.

gConveyor.Command.MoveAbsolute := TRUE;

IF (gConveyor.Status.AxisMoving) THEN
...

The task itself is more or less just a shell, with referenced files from the library task, and if you want you can have some axis specific files which are not referenced.

What are the benefits of this? I am always working with the generic local structure “Internal” in my tasks. I am not forced to use massive arrays, which are difficult to debug. And since I am doing this PV mapping for every task, I can be sure that the data is only written once to all tasks, at the beginning of the task cycle. This ensures consistency across tasks and cycles - if a higher priority task would interrupt the task and change the global variable, the local values will not change mid-task. It also makes sure that only the task itself can write the statuses.

This library is then a submodule in git, which means I can use the submodule across all my projects, and if I update the code in the submodule, this of course means the axis code will be updated in all projects using it. This comes at the cost of some overhead, because all structure members are copied cyclically through “Variable mapping”.