Documentation Home Page RT-LAB Home Page
Pour la documentation en FRANÇAIS, utilisez l'outil de traduction de votre navigateur Chrome, Edge ou Safari. Voir un exemple.

Ethercat Slave

Description

This document explains how to use the Data Interchange Layer (DIL) system to instantiate an EtherCAT slave communication interface that can be used to send data to an EtherCAT master or receive data from it.

The EtherCAT slave driver is controlling a CIFX 50E-RE PC card designed by Hilscher. This card family is the unified standard supporting all Real-Time Ethernet and Fieldbus systems for PC based automation. In order to use the EtherCAT slave communication interface, this card must be connected to the target through the PCI express link. The complete protocol stack is executed on the CIFX card and data exchange with the target is done via Dual-Port-Memory or DMA.

Then, the EtherCAT slave driver is responsible with initializing the CIFX card and loading the appropriate kernel module to achieve typical EtherCAT slave device operations, according to the user requirements.

As this driver takes advantage of the DIL system, a connection file must be used to bind the model signals to the driver variables. This file is a text file named'connections.opal' (graphical editor will be available in a later release of RT-LAB).Another configuration file must be used to configure each EtherCAT slave communication interface with the number of incoming and outgoing data. Both files are described in the configuration section below.

As shown in the picture above, the CIFX card has two Ethernet ports. It is possible to connect it directly to the master and to use the other port to connect another EtherCAT slave device to create a daisy-chained topology. The last device of the chain can be connected back to the master to create a ring topology thus taking advantage of cable redundancy.

For more information about the EtherCAT protocol itself, please refer to the EtherCAT group technology website.

Driver Configuration

Each EtherCAT slave CIFX card must be configured with a specific file. If the simulation model is using more than one CIFX cards, then the different EtherCAT slave configuration  and connection files have to be provided to the driver. Ensure that the cards all have unique board ids. This can be set by adjusting the rotary switch on the side of the card. Each configuration file has two parts. The first part contains generic configuration information about the driver. The second part defines the number of data that will be exchanged between the master and the slave, with their respective types. The supported types are given in the following table:


NOTE: In the case where there are multiple boards and the data displayed in Simulink is inverted (data for for board x is received on board y), swap the PCIe slots for both cards. If this can not be done, swap the board IDs for the cards accordingly.


Supported data typesType field in the configuration fileSize field in the configuration file
Booleanbool1
Unsigned integer 8uint8
Unsigned integer 16uint16
Unsigned integer 32uint32
Unsigned integer 64uint64
Signed integer 8int8
Signed integer 16int16
Signed integer 32int32
Signed integer 64int64
Single precision floating pointfloat32
Double precision floating pointdouble64

In the configuration file, the size of each input or output must match with its type. This file is essential therefore please note that if it is missing or it has the wrong format, the model will reset during the load operation. In this case, use one of the configuration files offered with the example models as a reference. A typical configuration file looks like this:

OPAL-1.0 Object
EtherCATSlave::EtherCATSlaveConfig {
	board_name=cifx0
	board_id=0
	cifx_path=/Hilscher/EtherCATSlave
	pdo {
		item {
			name=RxPDO
			type=RX
			index=0x1600
		}
		item {
			name=TxPDO
			type=TX
			index=0x1A00
		}
	}
	userObjDict {
		item {
			name=DataIn0
			pdoMapping=RxPDO
			initialValue=1
			size=1
			type=bool
			index=0x6000
		}
		item {
			name=DataIn1
			pdoMapping=RxPDO
			initialValue=0
			size=1
			type=bool
			index=0x6001
		}
		item {
			name=DataIn2
			pdoMapping=RxPDO
			initialValue=0
			size=1
			type=bool
			index=0x6002
		}
		item {
			name=DataIn3
			pdoMapping=RxPDO
			initialValue=0
			size=1
			type=bool
			index=0x6003
		}
		item {
			name=DataIn4
			pdoMapping=RxPDO
			initialValue=0
			size=1
			type=bool
			index=0x6004
		}
		item {
			name=DataIn5
			pdoMapping=RxPDO
			initialValue=1
			size=1
			type=bool
			index=0x6005
		}
		item {
			name=DataIn6
			pdoMapping=RxPDO
			initialValue=0
			size=1
			type=bool
			index=0x6006
		}
		item {
			name=DataIn7
			pdoMapping=RxPDO
			initialValue=1
			size=1
			type=bool
			index=0x6007
		}
		item {
			name=DataIn8
			pdoMapping=RxPDO
			initialValue=-2
			size=8
			type=int
			index=0x6008
		}
		item {
			name=DataIn9
			pdoMapping=RxPDO
			initialValue=22
			size=16
			type=uint
			index=0x6009
		}
		item {
			name=DataIn10
			pdoMapping=RxPDO
			initialValue=0
			size=32
			type=float
			index=0x600A
		}
		item {
			name=DataOut0
			pdoMapping=TxPDO
			size=1
			type=bool
			index=0x600B
		}
		item {
			name=DataOut1
			pdoMapping=TxPDO
			size=1
			type=bool
			index=0x600C
		}
		item {
			name=DataOut2
			pdoMapping=TxPDO
			size=1
			type=bool
			index=0x600D
		}
		item {
			name=DataOut3
			pdoMapping=TxPDO
			size=1
			type=bool
			index=0x600E
		}
		item {
			name=DataOut4
			pdoMapping=TxPDO
			size=1
			type=bool
			index=0x600F
		}
		item {
			name=DataOut5
			pdoMapping=TxPDO
			size=1
			type=bool
			index=0x6010
		}
		item {
			name=DataOut6
			pdoMapping=TxPDO
			size=1
			type=bool
			index=0x6011
		}
		item {
			name=DataOut7
			pdoMapping=TxPDO
			size=1
			type=bool
			index=0x6012
		}
		item {
			name=DataOut8
			pdoMapping=TxPDO
			size=8
			type=uint
			index=0x6013
		}
		item {
			name=DataOut9
			pdoMapping=TxPDO
			size=16
			type=uint
			index=0x6014
		}
		item {
			name=DataOut10
			pdoMapping=TxPDO
			size=64
			type=double
			index=0x6015
		}
		item {
			name=Acyclic0
			pdoMapping=DO_NOT_MAP_AS_PDO
			accessRights=READ_ONLY
			size=1
			type=bool
			initialValue=1
			index=0x6016
		}
		item {
			name=Acyclic1
			pdoMapping=DO_NOT_MAP_AS_PDO
			accessRights=WRITE_ONLY
			size=8
			type=uint
			initialValue=253
			index=0x6017
		}
		item {
			name=Acyclic2
			pdoMapping=DO_NOT_MAP_AS_PDO
			accessRights=READ_WRITE
			size=16
			type=uint
			initialValue=3258
			index=0x6018
		}
		item {
			name=Acyclic3
			pdoMapping=DO_NOT_MAP_AS_PDO
			accessRights=READ_WRITE
			size=32
			type=uint
			initialValue=231464652
			index=0x6019
		}
		item {
			name=Acyclic4
			pdoMapping=DO_NOT_MAP_AS_PDO
			accessRights=READ_WRITE
			size=8
			type=int
			initialValue=-120
			index=0x601A
		}
		item {
			name=Acyclic5
			pdoMapping=DO_NOT_MAP_AS_PDO
			accessRights=READ_WRITE
			size=16
			type=int
			initialValue=-3531
			index=0x601B
		}
		item {
			name=Acyclic6
			pdoMapping=DO_NOT_MAP_AS_PDO
			accessRights=READ_WRITE
			size=32
			type=int
			initialValue=-268435455
			index=0x601C
		}
		item {
			name=Acyclic7
			pdoMapping=DO_NOT_MAP_AS_PDO
			accessRights=READ_WRITE
			size=32
			type=float
			initialValue=0.78362382
			index=0x601D
		}
		item {
			name=Acyclic8
			pdoMapping=DO_NOT_MAP_AS_PDO
			accessRights=READ_WRITE
			size=64
			type=double
			initialValue=34.7836
			index=0x601E
		}
	}
}

According to the configuration file presented above, the EtherCAT slave CIFX card is programmed to have one RxPDO and one TxPDO. The card can have up to 32 TxPDOs and 32 RxPDOs. (see TwinCAT's help for more information). This way the cyclical data can be mapped to custom TxPDOs or RxPDOs.

In the "Cyclical IO-Mailboxes" example model, the board is configured to cyclically receive 8 booleans, one 8-bit integer, one unsigned 16-bit integer, and one 32-bit floating point value from the EtherCAT master. The receiving points are all mapped to the RxPDO described above. On the other end, it expects to cyclically send 8 booleans, one 8-bit unsigned integer, one 16-bit unsigned integer, and one double floating point value. These objects are all mapped to the TxPDO. At the same time, it is programmed to have 9 dictionary objects through which the slave and the master can exchange data acyclically.

The cyclical and acyclical data are fully configurable in terms of their location in the object dictionary, their names, data sizes, and types. Furthermore, acyclical objects can offer different types of access rights for the master.

The location in the object dictionary is defined in terms on an index. The master will use this index to access a dictionary object.

The following table explains each driver parameter:


ParameterDescription
board_nameName of the board used by the driver to open the board. In the current implementation, this parameter must be set to 'cifx0' but it will be changed when multiple boards support will be added.
board_idIndex of the board. In the current implementation, this parameter must be set to 0 but it will be changed when multiple boards support will be added.
cifx_pathPath where the firmware files of the CIFX board are located. By default, they are installed in '/Hilscher/EtherCATSlave'.
pdoThis a list that details all the cyclical object structures. Cyclically exchanged objects all belong to one of the structures defined in this list. Each element of this list has a name, a type (either RX or TX) and an index as its address.
userObjDictThis is where the objects in the object dictionary are defined. Each item of this list can represent a TxPDO mappable object, an RxPDO mappable object, or a generic dictionary object. Depending on the type of the object, different fields are needed within the item, as seen in the above configuration file.


Note: If there are multiple PDOs of type RX, please make sure to enter the cyclical dictionary objects of the first RxPDO defined in the PDO section of the configuration file before the objects of the second RxPDO defined in the configuration file, and so on. The same comment applies for PDOs of type TX.


Example: TxPDO1 is defined before TxPDO2 in the PDO list of the configuration file. If obj1 is mapped to TxPDO1 and obj2 is mapped to TxPDO2, obj1 has to appear before obj2 in the userObjDict list

Each item in the userObjDict list requires a connection in the connections.opal file. The TxPDO mappable objects have to be mapped to outputs, the RxPDO mappable objects have to be mapped to the inputs. For the acyclical data, if the object has READ_WRITE access rights then it has to be mapped in both inputs and outputs. If, on the other hand, it has READ_ONLY access rights, it has to be added only to the outputs (since the object cannot be written by the master, there is no point in giving it an input connection as well). Finally, for the WRITE_ONLY access rights, the object has to be added only to the inputs section of the connections file.

RT-LAB Usage

In RT-LAB, two configuration files must be transferred to the simulator in ASCII mode before the model loads. The first file is the EtherCAT slave configuration file described above and the second is the 'connections.opal' file. If the project where the EtherCAT slave communication interface has to be integrated already contains a 'connections.opal' file, the main 'item {}' information of the file must be simply copied and added to the existing 'connections.opal' file. In other words, all 'connections.opal' files must be merged into a single file for a given simulation to use many drivers simultaneously.

The 'connections.opal' file is required to bind model signals to driver variables. This is how all drivers implemented within the Data Interchange Layer work. In RT-LAB, model signals that need to reach the driver have to be connected to 'OpOutput' blocks. It is the case for the data sent by the EtherCAT slave to the EtherCAT master; this data are defined by the object dictionary items of the configuration file described above that are mapped to TxPDO, acyclic data having READ_ONLY and READ_WRITE permissions and data pertaining to CoE emergencies.

Signals travelling from the driver to the simulation model have to be connected to 'OpInput' blocks. It is the case for the data sent by the EtherCAT master to the slave, defined by the object dictionary items of the configuration file described above that are mapped to RxPDO, acyclic data having WRITE_ONLY and READ_WRITE permissions and the transmission status connections.

Here is what the typical connections file looks like for the EtherCAT slave:

OPAL-1.0 Object
List {
  item {
    configFile=ethercat_slave_cfg.opal
    id {
      EtherCATSlave
    }
    outputs {
      item {
        dataInProcess=OpOutput:emergency_data[0]
        dataInExchanger=cifx0_0_emergency.trigger
      }
      item {
        dataInProcess=OpOutput:emergency_data[1]
        dataInExchanger=cifx0_0_emergency.priority
      }	  
      item {
        dataInProcess=OpOutput:emergency_data[2]
        dataInExchanger=cifx0_0_emergency.err_code
      }
      item {
        dataInProcess=OpOutput:emergency_data[3]
        dataInExchanger=cifx0_0_emergency.err_reg
      }	  
      item {
        dataInProcess=OpOutput:emergency_data[4:8]
        dataInExchanger=cifx0_0_emergency.diag_data
      }
      item {
        dataInProcess=OpOutput:slave_outputs[0]
        dataInExchanger=cifx0_0.DataOut0
      }
      item {
        dataInProcess=OpOutput:slave_outputs[1]
        dataInExchanger=cifx0_0.DataOut1
      } 
      item {
        dataInProcess=OpOutput:slave_outputs[2]
        dataInExchanger=cifx0_0.DataOut2
      }
      item {
        dataInProcess=OpOutput:slave_outputs[3]
        dataInExchanger=cifx0_0.DataOut3
      }
      item {
        dataInProcess=OpOutput:slave_outputs[4]
        dataInExchanger=cifx0_0.DataOut4
      }
      item {
        dataInProcess=OpOutput:slave_outputs[5]
        dataInExchanger=cifx0_0.DataOut5
      }
      item {
        dataInProcess=OpOutput:slave_outputs[6]
        dataInExchanger=cifx0_0.DataOut6
      }
      item {
        dataInProcess=OpOutput:slave_outputs[7]
        dataInExchanger=cifx0_0.DataOut7
      }
      item {
        dataInProcess=OpOutput:slave_outputs[8]
        dataInExchanger=cifx0_0.DataOut8
      }
      item {
        dataInProcess=OpOutput:slave_outputs[9]
        dataInExchanger=cifx0_0.DataOut9
      }
      item {
        dataInProcess=OpOutput:slave_outputs[10]
        dataInExchanger=cifx0_0.DataOut10
      }
      item {
        dataInProcess=OpOutput:slave_outputs[11]
        dataInExchanger=cifx0_0.Acyclic0
      }
      item {
        dataInProcess=OpOutput:slave_outputs[12]
        dataInExchanger=cifx0_0.Acyclic2
      }
      item {
        dataInProcess=OpOutput:slave_outputs[13]
        dataInExchanger=cifx0_0.Acyclic3
      }
      item {
        dataInProcess=OpOutput:slave_outputs[14]
        dataInExchanger=cifx0_0.Acyclic4
      }
      item {
        dataInProcess=OpOutput:slave_outputs[15]
        dataInExchanger=cifx0_0.Acyclic5
      }
      item {
        dataInProcess=OpOutput:slave_outputs[16]
        dataInExchanger=cifx0_0.Acyclic6
      }
      item {
        dataInProcess=OpOutput:slave_outputs[17]
        dataInExchanger=cifx0_0.Acyclic7
      }
      item {
        dataInProcess=OpOutput:slave_outputs[18]
        dataInExchanger=cifx0_0.Acyclic8
      }	  
    }
    inputs {  
      item {
        dataInExchanger=cifx0_0_status.tx
        dataInProcess=OpInput:tx_status
      }
      item {
        dataInExchanger=cifx0_0_status.rx
        dataInProcess=OpInput:rx_status
      }                       
      item {
        dataInExchanger=cifx0_0.DataIn0
        dataInProcess=OpInput:slave_inputs[0]
      }
      item {
        dataInExchanger=cifx0_0.DataIn1
        dataInProcess=OpInput:slave_inputs[1]
      }
      item {
        dataInExchanger=cifx0_0.DataIn2
        dataInProcess=OpInput:slave_inputs[2]
      }
      item {
        dataInExchanger=cifx0_0.DataIn3
        dataInProcess=OpInput:slave_inputs[3]
      }
      item {
        dataInExchanger=cifx0_0.DataIn4
        dataInProcess=OpInput:slave_inputs[4]
      }
      item {
        dataInExchanger=cifx0_0.DataIn5
        dataInProcess=OpInput:slave_inputs[5]
      }
      item {
        dataInExchanger=cifx0_0.DataIn6
        dataInProcess=OpInput:slave_inputs[6]
      }
      item {
        dataInExchanger=cifx0_0.DataIn7
        dataInProcess=OpInput:slave_inputs[7]
      }
      item {
        dataInExchanger=cifx0_0.DataIn8
        dataInProcess=OpInput:slave_inputs[8]
      }
      item {
        dataInExchanger=cifx0_0.DataIn9
        dataInProcess=OpInput:slave_inputs[9]
      }
      item {
        dataInExchanger=cifx0_0.DataIn10
        dataInProcess=OpInput:slave_inputs[10]
      }
      item {
        dataInExchanger=cifx0_0.Acyclic1
        dataInProcess=OpInput:slave_inputs[11]
      }
      item {
        dataInExchanger=cifx0_0.Acyclic2
        dataInProcess=OpInput:slave_inputs[12]
      }
      item {
        dataInExchanger=cifx0_0.Acyclic3
        dataInProcess=OpInput:slave_inputs[13]
      }
      item {
        dataInExchanger=cifx0_0.Acyclic4
        dataInProcess=OpInput:slave_inputs[14]
      }
      item {
        dataInExchanger=cifx0_0.Acyclic5
        dataInProcess=OpInput:slave_inputs[15]
      }
      item {
        dataInExchanger=cifx0_0.Acyclic6
        dataInProcess=OpInput:slave_inputs[16]
      }
      item {
        dataInExchanger=cifx0_0.Acyclic7
        dataInProcess=OpInput:slave_inputs[17]
      }
      item {
        dataInExchanger=cifx0_0.Acyclic8
        dataInProcess=OpInput:slave_inputs[18]
      }	  
    }
  } 
}



It is important that the name of the driver configuration file is provided. Also, each string used as a 'dataInExchanger' tag must have the same prefix defined by the name of the board 'cifx0' concatenated with '_', concatenated with the board index '0'. Next, if the point is a dictionary object, the tag continues with a dot '.' followed by the name of the element in the model. However, if the point is used for emergencies, the tag continues with '_emergency', followed by '.' and the name of the model element. Finally, in the case of status connections, the tag continues with '_status' concatenated with a dot '.' and the name of the model element. The board name and index of the prefix have to be the same as those in the configuration file referenced by the 'connections.opal' item. In the case of this example, the prefix for each input signals is cifx0_0.

To receive the data from the EtherCAT master in the model, three 'OpInput' blocks are required. In the case of the example above, the first block must be named 'slave_inputs' because this is the name given in the connections file for the 'dataInProcess' fields. The two next blocks must be named 'tx_status' and 'rx_status', as seen in the above connections file. To send data to the EtherCAT master through the connection points, two 'OpOutput' blocks must be used. In the case of the example above, they must be named 'slave_outputs' and 'emergency_data'.

As shown in the connections file example, two connections points can be used in the inputs section to receive status information from the CIFX card (status.tx and statux.rx).
The table below describes each transmission status value that might be returned by the driver.


status.txDescription
0No error. The EtherCAT slave is successfully transmitting the configured data to the connected EtherCAT master.
-1No EtherCAT master is connected (or not yet connected) to the EtherCAT slave
otherAny other transmission status is returned directly from the CIFX card driver API. The hexadecimal value of this status must be used to find the corresponding description in the CIFX API documentation or in the CIFX error codes documentation.


The table below describes each reception status value that might be returned by the driver.


status.rxDescription
0No error. The EtherCAT slave is successfully receiving the configured data from the connected EtherCAT master.
-1No EtherCAT master is connected (or not yet connected) to the EtherCAT slave
otherAny other reception status is returned directly from the CIFX card driver API. The hexadecimal value of this status must be used to find the corresponding description in the CIFX API documentation or in the CIFX error codes documentation.

The emergency messages should be constructed according to the EtherCAT definitions. Information related to the error codes can be found on page 163 of the mentioned document. For the error register, refer to page 107. The priority of an emergency message ranges from 0 to 3, with 3 being the highest. Finally, the diagnostic data is data specific to the emergency being sent. It is recommended that the above-mentioned document is used for the creation and transmission of emergency messages. However, an emergency message will be sent whenever the trigger is switched from 0 to 1. It is the user's responsibility to enter valid data in the model.

The EtherCAT slave example models show how to perform the connections using 'OpInput' and 'OpOutput' block. Two example models are provided. The first one, 'Cyclical IO' focuses strictly on the exchange of cyclical data between the master and the slave. The second one, 'Cyclical IO-Mailboxes' includes the cyclical communication and also the acyclical communication and use of emergency messages. They are located in the following directories:

YOUR_RT_LAB_INSTALLATION_FOLDER/Examples/IO/EtherCAT/Hilscher/EtherCAT_Slave/Cyclical IO/simulink

YOUR_RT_LAB_INSTALLATION_FOLDER/Examples/IO/EtherCAT/Hilscher/EtherCAT_Slave/Cyclical IO-Mailboxes/simulink

The example models are also accessible from the New Project wizard in RT-Lab. Select one of the two EtherCAT_Slave templates under IO/EtherCAT/Hilscher/EtherCAT_Slave/. Here is a screenshot of the master subsystem:

The Beckhoff TwinCAT software can be used to connect with the EtherCAT slave and test the example model.

HYPERSIM Usage

The driver is not yet available in Hypersim but can be ported upon request.

Limitations

The current version of the EtherCAT slave communication interface has the following limitations:

  • On 64bit platforms, enabling the XHP mode is not possible; if the driver is part of a model that requires XHP enabled, it is advised to group the OpInputs/OpOutputs used by EtherCAT slave in a separate subsystem that will operate with XHP = off.
  • Number of boards: Only supports one EtherCAT slave board per target.
  • Memory alignment: Data can be only aligned on 8-bit boundary in the CIFX Dual Port Memory. If only one 'bool' value is configured, it will be stored as one byte. However, 8 'bool' values configured one after each other will be stored in one byte (not in 8 bytes).
  • Offline mode: Driver does not work offline.
  • Platform: Driver can only be used on Linux (OPAL-RTLinux x86-based 32bit and OPAL-RTLinux x64-based 64bit platforms).
  • Data types: bool, uint8, int8, uint16, int16, uint32, int32, uint64, int64, float, double.
  • Maximum cyclical transmission size: The driver can only send cyclically 256 bytes at once.
  • Maximum cyclical reception size: The driver can only receive cyclically 256 bytes at once.


OPAL-RT TECHNOLOGIES, Inc. | 1751, rue Richardson, bureau 1060 | Montréal, Québec Canada H3K 1G6 | opal-rt.com | +1 514-935-2323
Follow OPAL-RT: LinkedIn | Facebook | YouTube | X/Twitter