DiagnosisDataReader (FB)

FUNCTION_BLOCK DiagnosisDataReader

This function block is be used for reading the diagnosis data which is received from a profinet device.

The diagnosis data that is read out by an acyclic read-service (see CommFB.RDREC) or received as an profinet alarm (see CommFB.RALARM) has the form of a byte-stream.

The function block is parsing the byte-stream and transfers the protocol specific data into a user-friendly data format.

First step is to initialize the FB with the received data, see methods InitAlarm() or InitData().

Next the method Read() is executed repeately in order to read the next diagnosis item.

After a successful execution of Read() (return value TRUE), the FB's outputs contain valid data

For more information on Profinet Diagnosis, see:

PI Specification, Diagnosis for PROFINET IO, Guideline for PROFINET, Version 1.2 – Date June 2016, Order No.: 7.142

Example 1: Diagnosis-Alarm

PROGRAM PLC_PRG
VAR
    ralarm : CommFB.RALARM;
    alarm : CommFB.AINFO_TYPE;
    alarmCounter : DINT;

    diagReader : ProfinetCommon.DiagnosisDataReader;
    messages : ProfinetCommon.DiagMessageFactory;
    channelDiag : ProfinetCommon.ChannelDiagnosisData;
    sMessage : STRING;
    sDetailsMessage : STRING;
END_VAR


ralarm.EN := TRUE;
ralarm.MODE := CommFB.RALARM_MODE.ALL_ALARMS;       // receive all alarms from all devices connected to the controller
ralarm.F_ID := PN_Controller.MasterID;              // Filter ID, if MODE = ALL_ALARMS use MasterID here, else the ID of subslot

ralarm(ainfo := alarm);
WHILE(ralarm.NEW) DO
    alarmCounter := alarmCounter + 1;

    diagReader.InitAlarm(alarm.PN);
    WHILE(diagReader.Read()) DO                     // not all types of alarm have diganosis data ! (e.g. PULL does not)
        IF(diagReader.IsStandardFormat) THEN        // only standard format can be evaluated in a generic way
            channelDiag := diagReader.Diagnosis;
            IF(messages.TryGetDiagMessage(channelDiag, sDiagMessage => sMessage, sExtDiagMessage => sDetailsMessage)) THEN
                // we have a valid message...
            END_IF
        END_IF
    END_WHILE

    ralarm(ainfo := alarm);     // exec-again
END_WHILE

Example 2: use RDREC to read the diagnosis

PROGRAM PLC_PRG
VAR
    rdrec : CommFB.RDREC;
    buffer : ARRAY[0..255] OF BYTE;
    readError : DWORD;

    diagReader : ProfinetCommon.DiagnosisDataReader;
    messages : ProfinetCommon.DiagMessageFactory;
    channelDiag : ProfinetCommon.ChannelDiagnosisData;
    sMessage : STRING;
    sDetailsMessage : STRING;
END_VAR


// Read Diagosis-Data:
rdrec.ID := pnDevice.ID;                // "pnDevice" is a Profinet slave in the device tree
rdrec.INDEX := TO_INT(ProfinetCommon.DiagnosisRecordIndex.Device);      // = 16#F80C --> get all diagnosis for this device
rdrec.MLEN := TO_INT(SIZEOF(buffer));
rdrec.RECORD := ADR(buffer);
rdrec();

IF(rdrec.VALID AND rdrec.REQ) THEN
    //here we have valid data
    diagReader.InitData(rdrec.RECORD, TO_UINT(rdrec.LEN));
    WHILE(diagReader.Read()) DO
        IF(diagReader.IsStandardFormat) THEN        // only standard format can be evaluated in a generic way
            channelDiag := diagReader.Diagnosis;
            IF(messages.TryGetDiagMessage(channelDiag, sDiagMessage => sMessage, sExtDiagMessage => sDetailsMessage)) THEN
                // we have a valid message...
            END_IF
        END_IF
    END_WHILE
ELSIF(rdrec.ERROR) THEN
    readError := rdrec.STATUS;      // read service failed
END_IF
rdrec.REQ := rdrec.BUSY;
InOut:

Scope

Name

Type

Comment

Output

Source

DiagnosisSource

The diagnosis source is the information where the diagnosis is located on the device.

IsStandardFormat

BOOL

The diagnosis information is in standard format, use the data in output Diagnosis.

IsUSIFormat

BOOL

The diagnosis information is in USI format, use the data in output DiagnosisUSI.

Diagnosis

ChannelDiagnosisData

The diagnosis information in standard format.

DiagnosisUSI

DiagnosisInformationUSI

The diagnosis information in USI format.