5.5. Process Data Access

The process data that is exchanged between an EtherCAT master and the slaves in each cycle is stored in the process data image. There are two separate memory areas, one for the input data and one for the output data. The base addresses of these areas are provided by calling the functions emGetProcessImageInputPtr() and emGetProcessImageOutputPtr(). The size of the process data input image is defined in the ENI file under EtherCATConfig/Config/ProcessImage/Inputs/ByteSize and EtherCATConfig/Config/ProcessImage/Outputs/ByteSize and is returned by emRegisterClient() at EC_T_REGISTERRESULTS::dwPDOutSize and EC_T_REGISTERRESULTS::dwPDInSize.

5.5.1. Process Data Access Functions

Process data variables that are packed as array of bits are bit aligned and not byte aligned in process data. Accessing bits that are bit aligned and not byte aligned should be done using EC_GETBITS. See EC_COPYBITS for how to copy data areas with bit offsets that are not byte aligned. Access to corresponding aligned variables, e.g. of the types EC_T_BYTE, EC_T_WORD, EC_T_DWORD, EC_T_UINT64, can be accessed more efficiently using the appropriate macros according to the following table.

Note

Process data is typically transmitted as little endian and must therefore be swapped on big endian systems in order to be correctly interpreted.

Variable type

Bit size

Macro

Hint

Bit

1

EC_GETBITS

Contains swap for big endian systems

EC_T_BYTE

8

N/A

Bytes can be directly addressed at pbyBuffer[BitOffset/8]

EC_T_WORD

16

EC_GET_FRM_WORD

Contains swap for big endian systems

EC_T_DWORD

32

EC_GET_FRM_DWORD

Contains swap for big endian systems

EC_T_UINT64

64

EC_GET_FRM_QWORD

Contains swap for big endian systems

5.5.2. Process variables’ offset and size

The following screenshot shows variables’ offset and size within the Process Data Image:

Accessing the process data of a specific slave always works by adding an offset to the base address. All offsets are given as bit offsets!

There are different ways possible to get this offset. The offset values will not change until a new configuration is provided, therefore it is sufficient to load them once right after emConfigureNetwork(), it is not needed every cycle.

5.5.3. Process variable access via hard coded offsets

The offset value can be determined from an EtherCAT configuration tool. It is not recommended to use fixed values as the offsets will change as slaves are added/removed from the configuration.

As shown in the screenshot above, Slave_1004 [EL2004].Channel 3.Output is at offset 1.2 with size 0.1 in the example.

The numbering is Byte.Bit so the offset in the example is Byte 1, Bit 2, Bit offset:

8*1+2 = 10

Bit size

0*8+1 = 1

EC_T_BYTE* pbyPdOut = emGetProcessImageInputPtr(dwInstanceId);
EC_T_BYTE  byValue = 0x00;
EC_T_DWORD dwBitOffset = 10;
EC_T_DWORD dwBitSize = 1;

/* get variable in process data */
EC_GETBITS(pbyPdOut, &byValue, dwBitOffset, dwBitSize);

5.5.4. Process variable access via generated PD Layout

The EC-Engineer / EC-Inspector can export the process variables to a PD-Layout C-Header via the menu item Network ‣ Export Process Variables as shown in the following screenshot:

This will generate a header file containing the slaves’ variables as follows:

#include EC_PACKED_INCLUDESTART(1)
#define PDLAYOUT_OUT_OFFSET_SLAVE_2002 22
    typedef struct _T_PDLAYOUT_OUT_SLAVE_2002
    {
        EC_T_SWORD  swChannel_1_Output; // Slave_2002 [EL4132].Channel 1.Output ...
        EC_T_SWORD  swChannel_2_Output; // Slave_2002 [EL4132].Channel 2.Output ...
    } EC_PACKED(1) T_PDLAYOUT_OUT_SLAVE_2002;
#include EC_PACKED_INCLUDESTOP

Example how a value can be accessed:

EC_T_BYTE* pbyPdOut = emGetProcessImageOutputPtr(dwInstanceId);
T_PDLAYOUT_OUT_SLAVE_2002* pPdOutSlave2002 = (T_PDLAYOUT_OUT_SLAVE_2002*)(pbyPdOut + PDLAYOUT_OUT_OFFSET_SLAVE_2002);

EC_T_WORD wChannel1Out = EC_GET_FRM_WORD(&pPdOutSlave2002->swChannel_1_Output);

5.5.5. Process variable access dynamically from ENI

5.5.5.1. emGetCfgSlaveInfo

The slave offsets can be determined dynamically with the function emGetCfgSlaveInfo(). The offsets are stored in EC_T_CFG_SLAVE_INFO::dwPdOffsIn and EC_T_CFG_SLAVE_INFO::dwPdOffsOut.

Example of how Slave_1004 [EL2004].Channel 3.Output can be accessed:

EC_T_CFG_SLAVE_INFO SlaveInfo;
dwRes = emGetCfgSlaveInfo(dwInstanceId, EC_TRUE, 1004, &SlaveInfo);

EC_T_BYTE* pbyPdOut = emGetProcessImageOutputPtr(dwInstanceId);
EC_T_BYTE  byValue = 0x00;
EC_T_DWORD dwBitOffset = SlaveInfo.dwPdOffsOut + 2;
EC_T_DWORD dwBitSize = 1;

/* get variable in process data */
EC_GETBITS(pbyPdOut, &byValue, dwBitOffset, dwBitSize);

5.5.5.2. emGetSlaveOutpVarInfo

All variables of a specific slave can be determined dynamically with the functions emGetSlaveInpVarInfoEx() or emGetSlaveOutpVarInfoEx(). The offset is stored in EC_T_PROCESS_VAR_INFO_EX::nBitOffs.

Example of how Slave_1004 [EL2004].Channel 3.Output can be accessed:

EC_T_WORD wNumSlaveVars = 0;
EC_T_WORD wNumVarsRead = 0;
EC_T_PROCESS_VAR_INFO_EX* aProcVarInfo = EC_NULL;

/* get number of output variables */
dwRes = emGetSlaveOutpVarInfoNumOf(dwInstanceId, EC_TRUE, 1004, &wNumSlaveVars);

/* allocate buffer for the variable info structs */
aProcVarInfo = (EC_T_PROCESS_VAR_INFO_EX*)OsMalloc(sizeof(EC_T_PROCESS_VAR_INFO_EX) * wNumSlaveVars);
OsMemset(aProcVarInfo, 0, sizeof(EC_T_PROCESS_VAR_INFO_EX) * wNumSlaveVars);

/* read all variables of the slave at once */
dwRes = emGetSlaveOutpVarInfoEx(dwInstanceId, EC_TRUE, 1004, wNumSlaveVars, aProcVarInfo, &wNumVarsRead);

EC_T_BYTE* pbyPdOut = emGetProcessImageOutputPtr(dwInstanceId);
EC_T_BYTE  byValue = 0x00;

/* get variable in process data */
EC_GETBITS(pbyPdOut, &byValue, aProcVarInfo[0].nBitOffs, aProcVarInfo[0].nBitSize);

5.5.5.3. emFindOutpVarByName

The variable offsets can be determined dynamically using the names with the functions emFindInpVarByNameEx() or emFindOutpVarByNameEx(). Each input or output has a unique variable name, all variables names are stored in the ENI file under EtherCATConfig/Config/ProcessImage/[Inputs|Outputs]/Variable. The offset is stored in EC_T_PROCESS_VAR_INFO_EX::nBitOffs.

Example of how Slave_1004 [EL2004].Channel 3.Output can be accessed:

EC_T_PROCESS_VAR_INFO_EX ProcVarInfo;
dwRes = emFindOutpVarByNameEx(dwInstanceId, "Slave_1004 [EL2004].Channel 3.Output", &ProcVarInfo);

EC_T_BYTE* pbyPdOut = emGetProcessImageOutputPtr(dwInstanceId);
EC_T_BYTE  byValue = 0x00;

/* get variable in process data */
EC_GETBITS(pbyPdOut, &byValue, ProcVarInfo.nBitOffs, ProcVarInfo.nBitSize);

5.5.5.4. emGetSlaveOutpVarByObjectEx

The variable offsets can be determined dynamically using the object index and subindex with the functions emGetSlaveInpVarByObjectEx() or emGetSlaveOutpVarByObjectEx().

The object index and subindex can be get with the EC-Engineer:

Example of how Slave_1004 [EL2004].Channel 3.Output can be accessed:

EC_T_PROCESS_VAR_INFO_EX ProcVarInfo;
dwRes = emGetSlaveOutpVarByObjectEx(dwInstanceId, EC_TRUE, 1004, 0x7010, 0x01, &ProcVarInfo);

EC_T_BYTE* pbyPdOut = emGetProcessImageOutputPtr(dwInstanceId);
EC_T_BYTE  byValue = 0x00;

/* get variable in process data */
EC_GETBITS(pbyPdOut, &byValue, ProcVarInfo.nBitOffs, ProcVarInfo.nBitSize);