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: |
|