The PNIO Master emulates a PROFINET RT master in a network. It can be used to 

The PNIO Master consists of four different tabs which can be selected at the bottom.

The Device Commands tab allows to run basic DCP commands such as the identification of the device, setting the station name aso.

The I/O tab allows to setup and start a PROFINET RT I/O data connection.

The I&M tab allows to read and write the I&M records 1-4 of the device.

Device Commands

The Device Commands tab allows to work with the iRJ45 device using the PROFINET DCP protocol.

To work with an iRJ45 device using PROFINET, scan the network in the Network Navigator, select the required device and then click “Scan device”. The PROFINET Master then sends DCP Ident Req packets to the network and will report how many PROFINET devices in the network replied.

The dialog will automatically close when the device reported back via PROFINET and show the reported data (Station Name, Station Type, IP settings aso) in the Device Commands section.

If no reply from the device is received, an error dialog is shown as depicted in the figure below

The device is now identified as a PROFINET capable device and can now be used with the other functionalities of the PROFINET Master.

As a next step, the symbolic name of the device within the PROFINET network (the station name) can be set by clicking on “Set station name”. A dialog allows to define the new station name.

Per default, the station name is not stored in a non-volatile memory and is reset to an empty string after reboot. To persistently store the station name, check “Permanent” before clicking on “OK”.

After clicking “OK”, the new station is send to the device and the PROFINET Master will report whether the action was successful.

To set the IP configuration (IP address, netmask, gateway) via PROFINET, click on “Set IP settings”. A dialog allows to define the IP settings.

Per default, the IP settings are not stored in a non-volatile memory and are reset to 0.0.0.0 after reboot. To persistently store the IP settings, check “Permanent” before clicking on “OK”.

To visually identify devices in a PROFINET network the PROFINET DCP specification provides the Signal command. An PROFINET device that receives a signal command will show a visual indication which is device dependent and may rang from a blinking LED to a flash LCD display. For example, the iRJ45 Arduino Development board will blink with LED2 upon the reception of such a command.

To trigger the Signal command, click on the “Wink” button. The PROFINET Master will send the appropriate DCP command to the device and report the result.

I/O

The I/O tab allows to establish a PROFINET RT connection with one device to exchange I/O data.

Before working with I/O tab, identify the device via PROFINET by clicking “Scan” in the Device Commands tab.

The PROFINET Master requires information about the configuration of the target device. This information is read from the GSD file that is provided by the device vendor. To read this information, click on “Load GSDML file” and choose the GSD file in the file select dialog.

The I/O configuration consists of the following elements:

To configure the I/O connection, the required modules need be plugged into the slots. To plug a module, select the module in the Modules list and drag it to the required slot. Not all modules may be plugged into all slots. To remove a module from a slot, right click on the module in the Slot list and select “Remove module”.

The GSD may define modules which are automatically plugged into slots. These modules will be plugged by the PROFINET Master when loading the GSD and cannot be removed.

The cycle time of the communication is selected via the Device Interval. It specifies the interval between two data frames in ms. The allowed values are specified in the GSD file.

The valid cycle times start at 32ms up to 128ms depending on the device. However, due to the limitations of a non-real-time operating system such as Windows, the performance may vary based on the PC and the Ethernet interface.

To start the I/O connection, click on “Connect”. After successful establishment, the I/O Data can be seen in the I/O data section of the I/O tab.

The figure above shows the I/O data section for a 64 bytes input module in slot 1 and a 64 bytes output module in slot 2. Input/output data values are always shown as hex data.

The I/O data sections is split into the following columns:

The producer/consumer state shows the PS/CS values as transmitted to/from the device. By hovering of the column with the mouse, a tooltip shows the decoded values.

To edit the PS/CS value, click on the column and select “Edit”. A dialog allows the setting of the new value which is then applied by clicking on “OK”. The consumer state can be edited for input modules, the producer state can be edited for output modules.

Output data can be edited by clicking on the value in the Output Data column. After editing hit the “Enter” key to apply. By hitting the “Esc” key or clicking onto another column, the editing is aborted.

By default, the CS and PS values are set to Good by the PROFINET Master. This value can be configured via File → Preferences → PROFINET RT → IOCS default state / IOPS default state.

Scripting

The PROFINET Master provides a scripting interface to manipulate output data and react on received input data using an integrated Python 2.7 interpreter.

A script can be selected prior starting the connection using the scripting section as shown below.

To select a script, push the “Select script file” button and a file selection dialog will appear which allows to choose the appropriate script file. To clear the currently selected script, push the “Clear Script” button.

The basic structure of a script is shown in the listing below.

#########################################################################
# PNIO master script skeleton                                           #
#########################################################################


###
# This function is called every time a frame is received
# from the device.
###
def process_input():
    pass

###
# This function is called every time a frame is about to be sent.
# It contains the complete frame incl. all headers.
###
def process_output():
    pass


###
# This function is called once the PNIO stack reports that
# the connection is established. At this point in time, you can
# retrieve the position of the individual data items.
###
def established():
    pass


###
# This function is called once when the connection was closed.
###
def closed():
    pass


###
# Called once during init of the script
###
if __name__ == "__main__":
    pass

A script contains of the following elements:

The following table describes the different global variables that are available for access in the the scripts.

Name

Description

Type

Available from

station_name

Name of the station the master is connected to

String

main

mac

MAC address of the station the master is connected to

Byte Array

main

config

Configuration of the PNIO connection. See description below

PnioConnectionConfig instance

established

in_data

Data frame received starting behind the header

Byte Array

process_input

out_data

Data frame to sent to the remote station incl. the header

Byte Array

process_output

out_data_offset

The offset of the output data within the frame

int

process_output

A PnioConnectionConfig object encapsulates the configuration of a PNIO connection. It provides the following functions:

Name

Description

Return Value

getModulesToPlug

returns a list of PnioModule instances describing the modules/submodules that shall be plugged into the appropriate slots

a list of PnioModule instances

getWatchdogFactor

returns the watchdog factor

watchdog factor as int

getDataholdFactor

returns the data hold factor

data hold factor as int

getControllerReductionRatio

returns the controller reduction ratio

controller reduction ratio as int

Information of about individual modules is encode in PnioModule and PnioSubmodule instances.

A PnioModule consists of the following functions:

Name

Description

Return value

getSlot

returns the slot where the module shall be plugged into

slot as int

getName

the name of the module

name as string

getInfoText

InfoText of the module

InfoText as string

getAllSubmodules

returns a list of submodules

list of PnioSubmodule instances

A PnioSubmodule provides of the following functions:

Name

Description

Return value

getName

returns the name of the submodule

name as string

getDirection

data direction of the submodule

DIR_IN - input

DIR_OUT - output

DIR_INOUT - input/output

getInputSize

the size of input data in bytes

input data size as int

getOutputSize

the size of output data in bytes

output data size as int

getIoInputDataObject

getIoOutputDataObject

returns an IoDataObject describing the input or the output data of the submodule.

IoDataObject instance

getSubslot

the subslot where the submodule shall be plugged into

subslot as int

getDeviceToControllerIoCsObject

getControllerToDeviceIoCsObject

returns the cs IoDataObject object used for input data (controller to device) or output data (device to controller)

The following script demonstrates how to access configuration data by printing information about all modules and submodules to the console.

###
# This function is called once the PNIO stack reports that
# the connection is established. At this point in time, you can
# retrieve the position of the individual data items.
###
def established():
    print("Connected to " + station_name)
    print("===== Connection params =====")
    
    # show basic connection params
    print("reduction ratio: " + str(config.getControllerReductionRatio()))
    print("wd factor: " + str(config.getWatchdogFactor()))
    print("data hold factor: " + str(config.getDataholdFactor()))

    # show module/submodule configuration
    print("===== Modules =====")
    # ignore module 0 as this is the dap module
    for i in range(1, len(config.getModulesToPlug())):
        module = config.getModulesToPlug().get(i)
        print("----- Module " + module.getName() + "-----")
        print("Description: " + module.getInfoText())
        print("Number of submodules: " + str(len(module.getAllSubmodules())))
        subs = module.getAllSubmodules()
        
        # show all submodules
        for j in range(len(subs)):
            sub = subs.get(j)
            direct = str(sub.getDirection())
            print("\t----- Submodule " + sub.getName() + "-----")
            print("\tData direction: " + direct)
            if ("DIR_IN" == direct):
                print("\tInput size: " + str(sub.getInputSize()))
            if ("DIR_OUT" == direct):
                print("\tOutput size: " + str(sub.getOutputSize()))
            if ("DIR_INOUT" == direct):
                print("\tInput size: " + str(sub.getInputSize()))
                print("\tOutput size: " + str(sub.getOutputSize()))    
        print("")

Positional data within the frame is encoded in IoDataObject instances:

Name

Description

Return value

getFrameOffset

the offset of the data within a input frame (DIR_IN or DIR_INOUT) or an output frame (DIR_OUT or DIR_INOUT)

position as int

The following list provides a more complex example for accessing input and output data. It is based on the example project 09_pnio_io_mirror_new_api for the AC/CC. It sets a value to the 8bit output module and measures the time until the value is mirrored back on the first input module.

#########################################################################
# This script demonstrates how to use the scripting engine of the       #
# PNIO master.                                                          #
# It sets a value to the first output module and measures the time      #
# unitl that value is received on the first input module.               #
#########################################################################

from datetime import datetime


# global vars
in_pos = 0
out_pos = 0
lastval = 0xFF
trigger = False
expected_val = 0


###
# This function is called every time a frame is received
# from the device.
###
def process_input():
    global trigger
    global lastval
    global in_pos
    global expected_val
    global begin
    global end

    if trigger:
        if (expected_val == in_data[in_pos]):
            end = datetime.now()
            lastval = in_data[in_pos] & 0xFF

            # calculate round trip time
            roundtrip_time = end - begin

            # here you could do something with the
            # measured value

            # reactivate the trigger for the next value
            trigger = False


###
# This function is called every time a frame is about to be sent.
# It contains the complete frame incl. all headers. The position of the
# first data can be obtained via variable out_data_offset.
###
def process_output():
    global out_pos
    global trigger
    global out_data_offset
    global expected_val
    global begin

    pos = out_pos + out_data_offset
    new_val = out_data[pos]

    # if last value was received, create next value
    if not trigger:
        if (new_val != 0xFF) :
            new_val = new_val + 1
        else:
            new_val = 0
        begin = datetime.now()
        trigger = True

    # we always set the value in the process output
    out_data[pos] = new_val
    expected_val = new_val
    #pass


###
# This function is called once the PNIO stack reports that
# the connection is established. At this point in time, you can
# retrieve the position of the individual data items as shown
# below.
###
def established():
    global in_pos
    global out_pos

    # get the frame position of the first module, first submodule
    sub = config.getModulesToPlug().get(1).getAllSubmodules().get(0)
    in_pos = sub.getIoInputDataObject().getFrameOffset()

    # get the frame position of the second module, first submodule
    sub = config.getModulesToPlug().get(2).getAllSubmodules().get(0)
    out_pos = sub.getIoOutputDataObject().getFrameOffset()


###
# This function is called once when the connection was closed.
###
def closed():
    pass


###
# Called once during init of the script
###
if __name__ == "__main__":
    pass

process_input and process_output are both called in the realtime context of the PROFINET. Keep these functions as short as possible as otherwise the cycle time of the connection cannot be guaranteed.

I&M

The I/M tab allows to read and write the I&M records 1-4.

To read a record, select the required record tab below the Record Commands and click on “Read I&Mx record”. To write a record, click on “Write I&Mx record”.

The I&M0 record is defined as read-only by the PROFINET specification and thus cannot be written.

Alarms

The Alarms tab shows alarms generated by the device during a PROFINET connection. Alarms are shown in the Alarm List providing a timestamp when the alarm was received by the master and an Alarm Type. By clicking on an alarm entry, the details of the alarm are shown.

Per default, alarms are automatically acknowledged by the PROFINET Master. To disable automatic acknowledgement, untick the box “Auto ACK alarms” in the upper area of the Alarms tab.

When disconnecting the PNIO connection, an alarm “ERR-RTA” will be shown. This is the normal behavior of a PNIO device.