Generic EtherCAT Slave

This library of EtherCAT Slaves can never contain all available slaves on the market. To enable custom slaves, this generic EtherCAT slave is provided. A mask configuration parameter, EtherCAT Slave Configuration, is used to setup the slave. It is a Matlab struct. Behind the scenes, the other preconfigured slaves use the same SFunction as the generic slave, but with the comfort of not having to specify a structure.

Apart from the common slave options, the configuration structure has to be specified. At the top level, the structure has the fields

In the following sections, these two fields are described.

SlaveConfig

SlaveConfig describes the slave as required by the EtherCAT Master communication process to configure the slave in the network. This information is available in the EtherCATInfo xml description file supplied by the manufacturor. SlaveConfig by itself is a structure with the fields:
slave.SlaveConfig.vendor = 2;
slave.SlaveConfig.product = hex2dec('bb93052')
slave.SlaveConfig.description = 'EL3001'  % optional

SyncManager Configuration

SyncManager configuration specifies PDO's that are mapped into a SyncManager and the Entries it contains. Once a PDO Entry is specified, it can be assigned to a block input or output port.

The SyncManager is specified by assigning slave.SlaveConfig.sm a cell array with as many elements as the slave has SyncManagers that need to be configured.

The elements of the cell array are cell arrays themselves that have three elements: {SmIndex, SmDirection, SmPDO} where:

  1. SmIndex: Zero based index number of the <Sm> xml element in the EtherCATInfo xml file
  2. SmDirection: SyncManager direction as seen by the master: 0 = Output (for RxPdo); 1 = Input (for TxPdo);
  3. SmPDO: Cell array of PDO's that are mapped to the SyncManager
for example:
slave.SlaveConfig.sm = {Sm2, Sm3};
Sm2 = {2, 0, Sm2PDO}  % SyncManager Index 2, Output
Sm3 = {3, 1, Sm3PDO}  % SyncManager Index 3, Input
The third element of a SyncManager cell array is another cell array with one element for every PDO that will be included in it. This array has two elements: {PdoIndex, PdoEntries} where:
  1. PdoIndex: PDO index number
  2. PdoEntries: PDO index number
for example:
Sm3PDO = {TxPDO1, TxPDO2}
TxPDO1 = {hex2dec('1a00') Entries_1a00}
TxPDO2 = {hex2dec('1a01') Entries_1a01}
The second element of a PDO specification lists the Entries of a PDO. This is a Nx3 numeric array with one row for every Entry. The columns of this array specify
  1. Entry Index
  2. Entry SubIndex
  3. BitLen
The values are obtained directly from the EtherCATInfo xml file.
Entries_1a00 = [hex2dec('6000')  1  1;
                hex2dec('6000')  2  1;
                hex2dec('6000')  3  2;
                hex2dec('6000')  5  2;
                hex2dec('6000')  7  1;
                0                0  7;  % 7 space bits
                hex2dec('1800')  7  1;
                hex2dec('1800')  9  1;
                hex2dec('1800') 17 16]
Note how a space Entry is specified with an Entry Index of 0. In this case only the BitLen is required, the SubIndex is ignored and can have any value.

CAN over EtherCAT configuration

CAN over EtherCAT is a protocol which is used to configure slaves. The required configuration options are set using the synchronous data objects cell array slave.SlaveConfig.sdo.

This cell or numeric array has 4 columns and as many rows as there are options to be configured. The rows can be specified to configure either a single value or the whole SDO at once.

Specify a single SDO value: This mode directly configures a single SDO. The column elements specify:

  1. SDO Index
  2. SDO SubIndex
  3. Data type: 8, 16, 32, 64: uintX_t
    -8, -16, -32, -64: intX_t
    0.32: single
    0.64: double
  4. Value
To specify a value array of uint8, DataType must be 0 and value is a numeric array or a string.
  1. SDO Index
  2. SDO SubIndex
  3. 0
  4. Either a string, or an array of values interpreted as uint8
Complete SDO access: This is the same as value array above, except that SubIndex is -1 as well:
  1. SDO Index
  2. -1
  3. 0
  4. Either a string, or an array of values interpreted as uint8
For example:
slave.SlaveConfig.sdo = { hex2dec('8000'),6,8,1;
                          hex2dec('8001'),0,0,'save';
                          hex2dec('8002'),-1,0,[64,65,66,67];
                          hex2dec('8003'),3,0,[64,65,66,67] };
When there are no special values (like arrays, string, compete access, etc), the cell array can be replace by a Nx4 numeric array.

Distributed Clocks configuration

Distributed Clocks allows the slaves to be synchronized in the range of nanoseconds. Distributed clocks is specified by assigning slave.SlaveConfig.dc either a single value or a vector with 10 elements.

Vector specification: the elements specify:

  1. Assign Activate
  2. Cycle Time Sync0
  3. Cycle Time Sync0 Factor
  4. Shift Time Sync0
  5. Shift Time Sync0 Factor
  6. Shift Time Sync0 Input
  7. Cycle Time Sync1
  8. Cycle Time Sync1 Factor
  9. Shift Time Sync1
  10. Shift Time Sync1 Factor

A single value just sets Assign Activate.

For example:

slave.SlaveConfig.dc = hex2dec('320');
slave.SlaveConfig.dc = [hex2dec('320'), 0, 1, 0, 0, 1, 0, 0, 0, 15000];

Sercos over EtherCAT

This obsolete configuration sends Sercos messages over EtherCAT. The required configuration options are set using the cell array slave.SlaveConfig.soe.

This cell array has 2 columns and as many rows as there are options to be configured:

  1. SDO Index
  2. Either a string, or an array of values interpreted as uint8
For example:
slave.SlaveConfig.soe = { hex2dec('8001'),'save';
                          hex2dec('8002'),[64,65,66,67] };

PortConfig

PortConfig describes the input and output ports of a block. PortConfig is a struct with the fields input and output.

Output Port specification

slave.PortConfig.output is a structure vector with the fields: The number of elements of slave.SlaveConfig.output determines how many output ports a block has. For example: the block with
slave.PortConfig.output(1).pdo = [ 0 0 0 0 ];
slave.PortConfig.output(2).pdo = [ 0 1 0 0;
                                   0 1 1 0;
                                   0 1 1 1 ];
will have 2 scalar output ports. Port 2 is a vector with 3 elements.

The PDO specification is a zero-based Nx4 array of index address of a PDO Entry. The columns specify:

  1. SyncManager Index. This index addresses the SyncManager element of the slave.SlaveConfig.sm cell vector. Only input SyncManagers (element 2 of the SyncManager field is 1) should be addressed. Addressing a SyncManager with direction output (0) will result in a warning.
  2. PDO Index. This index addresses the PDO element of the third element of the SyncManager cell vector.
  3. Entry Index. This index addresses the Entry row of the second element of the PDO cell vector.
  4. Element Index. This index addresses the data type element of the PDO Entry. (eg. if a Entry has BitLen=8 and it is interpreted as a boolean, Element Index can be [0..7])
The indices are zero-based.

The port will have as many elements as pdo has rows (N).

pdo_data_type is a value that specifies which data type to interpret the PDO Entry as. Valid values are:

ValueData Type
uint(1)Boolean
uint(2)Bit2
uint(3)Bit3
uint(4)Bit4
uint(5)Bit5
uint(6)Bit6
uint(7)Bit7
uint(8)Unsigned8
uint(16)Unsigned16
uint(24)Unsigned24
uint(32)Unsigned32
uint(40)Unsigned40
uint(48)Unsigned48
uint(56)Unsigned56
uint(64)Unsigned64
sint(08)Integer8
sint(16)Integer16
sint(32)Integer32
sint(64)Integer64
float('single')Real32
float('double')Real64

The data type must match the PDO Entry's BitLen. The remainder of division BitLen / mantissa_bits must be zero. Specifying a data type with fewer bits than BitLen will create a vector. For example, if BitLen=64 and pdo_data_type=1001 (boolean), the PDO Entry will have 64 elements. Placing all booleans on one output will have:

slave.PortConfig.output(3).pdo_data_type = 1001;
slave.PortConfig.output(3).pdo = [ 0,0,0,0;
                                   0,0,0,1;
                                   ...
                                   0,0,0,63 ];
Output port 3 will have 64 boolean elements;

full_scale is intended to normalize the PDO Entry value to unity so that scaling can be performed naturally. For example, full_scale has the value 2^15 for int16.

Gain, offset, filter and full_scale apply the following operation:

output = filter((PDO_Entry / full_scale) * gain + offset);

Gain, offset and filter can be spedified using either:

Parameters can either be a scalar or a vector, where the vector size must match the port width.

Specifying any of gain, offset, full_scale or filter causes the output's data type to be set to double.

gain, offset, full_scale or filter may assigned a 2 element cell array {'NameString', ValueArray}. The variable will be available as a parameter, allowing values to be changed at run-time.

Not specifying any of gain, offset, full_scale or filter will set the data type to the PDO Entries raw data type, possibly promoting the value to the next superiour type. Unsigned64 and Integer64 are represented as Real64 because they are not available in Simulink Coder.

Input Port specification

This is very similar to Output Port specification with the following exceptions: The signal's data type must either match pdo_data_type or be Real64.

Gain, offset and full_scale apply the following operation:

PDO_Entry = (input * gain + offset) * full_scale;

Block Parameter Config

This is a very difficult feature to use. It creates a block parameter that can be accessed from any port as a parameter during runtime when specifying PortConfig's gain, offset and filter options when specified using struct('parameter', idx, 'element', idx) in PortConfig.

The parameter specification is a name value map as a list of structs using struct('name', ..., 'value, ...).

A much more complex specification references model wide parameters from the "Model Workspace". The difficulty lies in the way it is specified. You need to edit the generic slave (option "Look under mask") and append the "Model Workspace" names after the sixth "S-Function parameters". They are then referenced using:
struct('name', ..., 'mask_index', 6+x)

For further instructions see the mex file itself or examples from the installation ;)