Tutorial 1: Create a component

In this first tutorial we will introduce some key koncepts of VIGO6 which will help you build your first control component. The tutorial alternates between information and "hands on" exercises using the information just presented and supported by "how-to"-live demonstrations. These demonstrations are identified by this icon:

Now - let us get started.

The VIGO6 Active editor

Programming in VIGO6 is done in the Active Editor. As we move along the tutorial, the relevant parts/functionalities of the editor will be described.

COPP types are expressed within the VIGO6 Active Editor in a tree structure, similar to the navigation pane in Windows Explorer.  A component type is identified within the VIGO6 navigation tree with a C icon. 

Data types, constants and variables are defined directly in the VIGO6 navigation tree . Changes of names of elements in the navigation structure automatically update the program code.

Navigation in the VIGO6 navigation tree is done with the 4 arrow keys or the mouse.

It is possible to have multiple types open at the same time. These are represented as separate tabs in the editor.


The Virtual Tour of VIGO6

COPP Component

A COPP component is one of the COPP types in VIGO6.

A COPP component is a combination of program code, data and configurations defining a specific functionality. A COPP component has memory containing variables and constants, using various memory categories.

It also contains methods with program code. The method has access to the memory in the component and can call other methods in the component and methods in other components (through connectors).



All COPP types are identified by a GUID (Global Unique Identifier) which is automatically assigned by VIGO6.
VIGO6 GUIDs follow this format:

<company identifier>_<ID number>-<version number>.

So e.g. GUID “PD_2886-01” is version one of type 2886 from company PD. and GUID “PD_2886-02” is the second version of type 2886 from company PD.


New component types can be created by inheriting from an existing component type
The existing type is called an Ancestor. The new types are called Descendents. The decendents receive a new ID-number and hence also a new GUID.
Additional methods and facilities can be added in descendents.
The editor ensures that the descendent retains all its ancestor’s properties in order to remain compatible.
The parameter type for the ancestor’s methods cannot be changed. 

Versioning and archive

An Archive system is an integrated part of VIGO6. All COPP types are stored in the COPP archive, identified by the GUID. Each type contains COPP information and related documentation.
Any change of an archived type is given a new version by the editor and server.


When you have defined a type, you can use it over and over again. When you use your component in a project, you are actually using an instance of the component type. You can add as many instances of a type as you need.

When a new version of a component type is available, the programmer can decide whether or not to update his instances of the type. No reprogramming is needed.


Now let us start working in VIGO6.

What you need to build - control logic:

The task of the component (shown in light green in the illustration) is to regulate a temperature to a temperature specified in a Setpoint, by controlling an output connected to a heating element. The temperature is measured by a 4-20 mA temperature transmitter. The regulating principle is a simple on/off with a temperature hysteresis. The regulating interval is controlled by a pre-built timer-function.

What you need to build: Visualisation/HMI

It must be possible to view and change the set-point and to view the current temperature.

Important note on naming. Whenever you need to name a new type, the tutorial will indicate the name like this "XX_Temperature_regulator_simple". Please select two letters that make sense to you like your initials (JD for John Doe) and put instead of the XX -i.e. "JD_Temperature_regulator_simple".



Step 1: Create a temperature regulator component

  • Open PD_7664 Process_component, by clicking on the "open type"-icon (or pressing CTRL-O"). Then select "COMPONENTS>>". You can now type any part of the name; including numbers and you should be able to see the component on the list. Double click to open. 
  • Right click on the component name and select “Create new type”. A new tab will open, showing the new component type and you will be the writer. The component is inherited from PD_7664.
  • Double click on the name of your component and change it to "XX_Temperature_regulator_simple".
    TIP: pressing the space-bar will create an underscore.

Constants  Constants are either type constants or instance constants.

Type constants are defined and set at type level and cannot be modified in instaces of the type.
Instance constants are defined at type level, but set at instance level.


Variables can be volatile or non-volatile. Volatile variables lose their value on power-off. Non-volatile variables keep their value even after power-off, and can have a default value assigned.
Variables are local to the component or method in which they are declared. Should it be necessary to set or view the variable outside of the component, the variable needs to be connected to a Register.


Quantity types

Data instances are normally associated with a "quantity type", to simplify visualisation, and to enable the compiler to prevent program-errors related to quantity and thereby help the programmer to avoid quantity errors.
Examples of Quantity types are:
Density, Pressure, Energy, Volume, Mass, Time
When defining variables of floating point type, the Quantity type must be stated.
The Quantity type for the result of a calculation or expression is deduced by the compiler. For any assignment, the compiler analyzes the Quantity types and indicates when there is an incompatibility such as: Volume: = Density.

Step 2:  Create variables and constants in your component

A constant is added by right clicking  on the section "TYPE CONSTANTS" or "INSTANCE CONSTANTS". 

A variable is added by right clicking og the section "VOLATILE VARIABLES" or "NON-VOLATILE VARIABLES".

Create the following variables and constant and add Quantity:
Non-volatile variables section: Set_point_value [AbsoluteTemperature] (PD_2003 Float32) Used as set-point for the regulator.  Set the default value to 25 [degrees celcius]

Volatile variable section: Actual_temperature_value [AbsoluteTemperature] (PD_2003 Float32). Holds the value of the input from the temperature component 

Instance constants section: Regulating_interval [TimeDifference] (PD_2003 Float32) Defines how often the regulator must run.

Handling local unit definitions

All data in a COPP component is stored in SI-units. Human interfaces as e.g. display and editor converts from the SI units to the unit definition selected via the Local Unit table where a set of units are defined. Eg there is a local unit table for Europe and another for the US. The programmer may prefer to work with gallons while the operator prefer to see litres. This is no problem when using VIGO6

Step 3: Setting the local unit table in the Active Editor

Click on "Change editor setup" (the orange wheel).

Click on the combo box "Default Quantity Local unit relation table".

Select:  PD_5311 Europe_metric_system.


Note: the units that the operator will see is chosen at a later stage in the tutorial series (tutorial 2). For now what we have set is the units used in the editor.


A subcomponent is a special type of component, created and designed by Proces-Data to be integrated into another component (the Parent component). A Subcomponent specifies an interface and a number of data instances. It contains methods with access to its own declared data structures. By Override, the methods in the subcomponent can obtain access to the data in its Parent component. When a component as parent integrates a Subcomponent, the Parent component has direct access to data in the Subcomponent.
Examples of subcomponents are Registers and Timers.

A register gives access to the variable related to it through the Set and Get methods.

Notation for accessing a register is the same as used to access variables. For example "My_register:= 27" will call the registers Set method, which will store the value "27" in the variable related to the register.

Step 4: Add subcomponents - registers and timer
Make the variables: Set_point_value and Actual_temperature_value visible outside of the control component - eg for the visualisation or for other components.

Right-click on the Subcomponent section of your component and select:
Add>>, Register>>  click on PD_4050 Register.
Change the name of the new register to "Set_point". 
Then right click on the register and select: "Assign data field to the register subcomponent" and select "Set_point_value" as register variable. Make sure that "get" and "set" is enabled for all user types (this tells the visualisation that this variable must be editable). Set maximum value to 40 and minimum value to 20 (enter the same values for alarm limit high and alarm limit low).

Then create a register (called Actual_temperature) for the variable Actual_temperature_value in the same way. Make sure that "get" is enabled and "set" is disabled for all user types. This tells the visualisation that this variable must be visible but non-editable. Set maximum value to 100 and minimum value to 0 (enter the same values for alarm limit high and alarm limit low).

Add a timer so you can repeat your regulation at predefined intervals:
Add PD_4404 Timer_subcomponent to the Subcomponent section.
Change the name to Timer.
Then select the timer and read the functionality for a Timer_subcomponent by selecting the methods and reading the documentation shown just to the right of the VIGO6 navigation tree.


A method in (sub) component X is able to call/activate methods in component Y via a connector.

The connector is a "placeholder" for a connection to a component of a given type.  At this point in time we do not specify hardware, we simply specify that we will use hardware compatible with the COPP type that we have chosen to create a connector to.

By establishing the connectors, we can access the methods of the component type(s) that we connect to and can finalise the control code before we move to hardware selection.

The decision on specific hardware modules for the components is not made at this point, which gives us the possibility to use the same control component with many (compatible) types of hardware without need for programming control code or visualisation for each. 

If eg. a specific hardware module for output control  is no longer produced, we simply need to substitute the physical module and our plant will continue to operate with no need for reprogramming or even recompliation.


Step 5 : Add connectors
Your temperature regulator component will need to interface with already made components for reading a temperature (the orange component on the drawing to the left) and for setting a digital output (the blue component on the drawing).

Hence you need to add connectors.

  • Create connection to the output component:
    Under section "Connection to external component": Add connector to instance of type: PD_2824 Digital_output_base, which is a basis for more output types.
    Rename it to Output.
  • Create connection to a temperature component: Under section "Connection to external component": Add connector to instance of type: PD_2854 Temperature_input_base rename it to Temperature.

We are almost ready to start writing our control code, but first a few items about the COPP programming language and how it is supported by the Active Editor.


Methods contain program code that only runs when the method is called. It is similar to a function in PROCESS-PASCAL, with the possibility of having parameters and a result.
Program code in a method has direct access to parameters, local variables, component variables and constants. However, methods differ from functions, as they can be called via P-NET.

A method can be checked as an Internal method(I), External method(E) or both(IE).

Methods marked External can be called from another component in the same device or via P-NET. External methods are not allowed to call methods in other components.
Methods marked Internal (I) cannot be called from another component but are allowed to call methods in other components.

See the overview of method calls below:

A mutex makes sure that calls within a component to the same method are  handled in sequence. Also there is an external mutex handling external calls to a method.

There is no mutex that encompass both internal and external calls, so be very aware when declaring IE methods as conflicts in execution may arise. 

Assignment of a value to a variable
On the left of ’:=’ the name of the variable you want to assign a value is written.

On the right side is the value which can be:
a constant
a variable
a Method

Assigning a constant to a variable with a specific Quantity requires the constant is given the correct local unit (SI unit.)
Example: Weight_Setpoint: = 35 [Kg]

The compiler checks that both sides have compatible data types (GUID match). It also checks that the Quantity type is correct.


 Popup menu

Placing the cursor in the beginning of a code line or just after the last text, a popup menu will show the choice of acceptable program code at that position.  It is thus not necessary to learn the whole syntax up front.







Through the popup menu it is also possible to access code templates that pre-load control structures.

COPP Notation without Begin/End
A block in a COPP program is not bounded by a BEGIN and an END. This has been replaced by:

  • Indentation - representing"BEGIN"
  • Reverse indentation - representing  "END" 

An Indented program is like a tree structure in which the indents indicate the level structure of the coding. The editor inserts the vertical lines and highlights the current block to improve readability.
THEN and ELSE are a sub-structure to IF and are thus indented. THEN and ELSE are alternatives and therefore have the same indentation level. THEN and ELSE sub-structures are indented. The IF, THEN, ELSE block is displayed with”+ / -” used to show/hide the block.
The Program Editor has a built in "code standard" that provides the same indentation style, and look. This means that programmers can easily understand each other's programs.

Step 6: Add a method and write your control code
You now need to write the actual piece of code that will enable your component to make the required regulation. 

Create a new method : right click on the method section and select Add Method. The new method is renamed to Regulate.
Write code for your temperature control:
Read the temperature from the input component into the register "Actual_temperature" in the control component.
if the temperature is lower than the set point, then open the output
in all other cases close the output

What your code should look like:


Method Call

When defining a method’s parameter and result type, the name, data type and Quantity type must be defined (as for a variable).
A method call must contain the individual parameters by name.
X: = Component Name. Method Name (Content: = delivered_amount, Number: = 7)
The Editor contains template functionality, which writes the parameter names, for example: Method Name (Content: =?, Number: =?)
A programmer need not remember the order of method parameters, as this will be clear from the parameter names, and leads to a reduced number of errors. (A pop-up menu will only show the identifiers that represent instances of a permissible data type and Quantity type). This model means that it is much easier for a reviewer to read the program.
Methods may include local variables, which only exist as long as the method runs.
Local Variables are given a name and Quantity type.
When calling a method, local variables are automatically set to "invalid", and must be initialized by the program before they can be used. (Security) .
When a method performs a calculation, the outcome is influenced by the data instance values and their Data Quality indications, which will be included in the result of calculation. In other words, if one or more are marked invalid, the result will also be invalid.

Step 7: Repeating the regulation
You need to make sure that your regulation continuously run at specific intervals, and for this you use the timer subcomponent that you added earlier.

Open the Timer subcomponent and select the method "Timermethod".
Right click to ‘Override’ and open ‘Program’.

In the first line of the program it says INHERITED. This indicates that the method of the ancestor will be executed.  Never delete the INHERITED, unless you specifically understand what you ancestor (and its ancestor-chain) 

Now implement program code to:

Call the Regulate method
Run the Timer again in time defined by your constant Regulating_interval .

What your code should look like:

Task manager

All devices include a TASK manager with a number of TASK components. The TASK manager allocates CPU time for the methods in the different components.
The TASK manager includes a stack for running the program. The stack size is the same for all TASK managers in a device. It will be adapted to the method in the device with the highest memory need.
The COPP system is designed for event-driven methods with short execution periods, and does not use a ’Change Task’, since this would require a stack for each method.

A Task Manager contains two queues.
The TASK manager's job is to take a vacant TASK and start to run the Timermethod in the first component in the timer queue at the specified time.
Otherwise the first component in the Async queue is run with the method specified in the chain.

To ensure that timer methods in the Timer queue do not occupy the CPU 100%, a method from the Timer queue is always followed by a method from the Async queue and vice versa. If the next specified time in the timer queue is later than current time, a Async queue method is executed instead.

Only methods without any parameters and results can be in the Async queue.

Only the Timermethod in timer subcomponents can be inserted in the timer queue.
A method can only be in a queue once.
When calling methods in remote components, the calling TASK is parked while waiting for response.
After a reset, the Init method of all components is called.

Step 8: Handling the startup (init).
You need to be sure that your system is in a well known state before you start your regulation.

Override’ the Init method in your Temperature_regulator_simple component and start writing after ‘Inherited’. Call the Timermethod.

What your code should look like:

note: The editor automatically inserts ‘Call_asynchronously’ when calling a method marked "internal" from a method marked "external". See Task Manager for further information.


In VIGO6 you decide at component level what parts of the component to make available for visualisation. Any data that you want the "outside world" to edit and/or see need to be put in a register (as we did for set point and actual temperature). 

The programmer can create any number of views or he can reuse views that others have made and combine it with visualisation elements from other components.  

Let us make a simple view for our temperature regulator component.


Step 9:  Create view for temperature regulator component.

As stated in the specifications, it must be possible to view and change the set-point and to view the current temperature. 

Open your control component XX_Temperature_regulator_simple

Right click and select “ create new view for this type based on” PD_11813 - Comp_view.

Rename the view to "Window_for_XX-temperature_regulator_simple"

Select type constants, view_region, bottomRight and set y to 50[mm] and x to 100[mm]. 

Save your view.

Open your graphical editor by pressing the sun-icon just above the VIGO6-navigation tree. You now see your visualisation. It is empty for now.

Right click on view list and select "add"- "view for control instance"  Click on the plus sign beside " XX_temperature_regulator_simple". Select register "setpoint". Select view PD_2159 - Number_name_value_unit. 

On your visualisation you now see the element and you can drag  it to a suitable position on the screen. 

Add a similar view for register "Actual temperature".


Your visualisation should look something like this:


CONGRATULATIONS! You have now created your control component with control logic and visualisation and it can be reused over and over.



And to recap, here is what you have built:

Now let us move to the next tutorial where you learn how to create assemblies, main assemblies and projects. And you will set up your test bed and load your components into a hardware module.