Skip to content

create slaves json

iqrok-lenovo edited this page Dec 30, 2021 · 1 revision

Writing slave.json

To write slaves.json, the easiest way is to look at the output of ethercat cstruct. Unfortunately, this only works if only the ethercat slaves have already had PDOs mapped. If the ethercat slaves' PDOs are dynamically mapped (i.e. Festo CPX-E-EC, Festo CPX-E-EC), you still need to refer to the slave's datasheet and the output of ethercat sdos.

Below is the explanation on how I write slaves.json for my hardware setup.

Hardware Setup

The connected ethercat slaves are Beckhoff EK1100, Beckhoff EL4004, and Beckhoff EK1004.

$ ethercat slaves
0  0:0  PREOP  +  EK1100 EtherCAT-Koppler (2A E-Bus)
1  0:1  PREOP  +  EL4004 4Ch. Ana. Output 0-10V, 12bit

PDOs

ethercat pdos is a command to output List Sync managers, PDO assignment and mapping of connected ethercat slaves.

$ ethercat pdos
=== Master 0, Slave 1 ===
SM0: PhysAddr 0x1000, DefaultSize  128, ControlRegister 0x26, Enable 1
SM1: PhysAddr 0x1080, DefaultSize  128, ControlRegister 0x22, Enable 1
SM2: PhysAddr 0x1100, DefaultSize    8, ControlRegister 0x24, Enable 1
  RxPDO 0x1600 "AO RxPDO-Map Outputs Ch.1"
    PDO entry 0x7000:01, 16 bit, "Analog output"
  RxPDO 0x1601 "AO RxPDO-Map Outputs Ch.2"
    PDO entry 0x7010:01, 16 bit, "Analog output"
  RxPDO 0x1602 "AO RxPDO-Map Outputs Ch.3"
    PDO entry 0x7020:01, 16 bit, "Analog output"
  RxPDO 0x1603 "AO RxPDO-Map Outputs Ch.4"
    PDO entry 0x7030:01, 16 bit, "Analog output"
SM3: PhysAddr 0x1180, DefaultSize    0, ControlRegister 0x00, Enable 0

cstruct

ethercat cstruct is a command to generate slaves PDO information in C Language.

$ ethercat cstruct
/* Master 0, Slave 1, "EL4004"
 * Vendor ID:       0x00000002
 * Product code:    0x0fa43052
 * Revision number: 0x00140000
 */

ec_pdo_entry_info_t slave_1_pdo_entries[] = {
    {0x7000, 0x01, 16}, /* Analog output */
    {0x7010, 0x01, 16}, /* Analog output */
    {0x7020, 0x01, 16}, /* Analog output */
    {0x7030, 0x01, 16}, /* Analog output */
};

ec_pdo_info_t slave_1_pdos[] = {
    {0x1600, 1, slave_1_pdo_entries + 0}, /* AO RxPDO-Map Outputs Ch.1 */
    {0x1601, 1, slave_1_pdo_entries + 1}, /* AO RxPDO-Map Outputs Ch.2 */
    {0x1602, 1, slave_1_pdo_entries + 2}, /* AO RxPDO-Map Outputs Ch.3 */
    {0x1603, 1, slave_1_pdo_entries + 3}, /* AO RxPDO-Map Outputs Ch.4 */
};

ec_sync_info_t slave_1_syncs[] = {
    {0, EC_DIR_OUTPUT, 0, NULL, EC_WD_DISABLE},
    {1, EC_DIR_INPUT, 0, NULL, EC_WD_DISABLE},
    {2, EC_DIR_OUTPUT, 4, slave_1_pdos + 0, EC_WD_DISABLE},
    {3, EC_DIR_INPUT, 0, NULL, EC_WD_DISABLE},
    {0xff}
};

Configuration for each slave

Slave Position 0

In the hardware setup, the slave in position 0 is EK1100. This ethercat slave is a bus coupler. It doesn't have any PDO or SDO. If we look at the output of ethercat pdos and ethercat cstruct, Slave 0 is not listed. But this slave still need to be included in the configuration. We can gather more information by executing ethercat slaves -p0 -v

$ ethercat slaves -p0 -v
=== Master 0, Slave 0 ===
Device: Main
State: PREOP
Flag: +
Identity:
  Vendor Id:       0x00000002
  Product code:    0x044c2c52
  Revision number: 0x00120000
  Serial number:   0x00000000
DL information:
  FMMU bit operation: no
  Distributed clocks: yes, 64 bit
  DC system time transmission delay: 0 ns
Port  Type  Link  Loop    Signal  NextSlave  RxTime [ns]  Diff [ns]   NextDc [ns]
   0  MII   up    open    yes             -   3095858314           0           0
   1  EBUS  up    open    yes             1   3095858914         600         145
   2  MII   down  closed  no              -            -           -           -
   3  N/A   down  closed  no              -            -           -           -
General:
  Group: SystemBk
  Image name: 
  Order number: EK1100
  Device name: EK1100 EtherCAT-Koppler (2A E-Bus)
  Flags:
    Enable SafeOp: no
    Enable notLRW: no
  Current consumption: -2000 mA

From the output above, we get vendor id and product code. The configuration for slave 0 is like this

{
    "alias": 0,
    "position": 0,
    "vendor_id": "0x00000002",
    "product_code": "0x044c2c52"
}

Slave Position 1

$ ethercat cstruct -p1
/* Master 0, Slave 1, "EL4004"
 * Vendor ID:       0x00000002
 * Product code:    0x0fa43052
 * Revision number: 0x00140000
 */

ec_pdo_entry_info_t slave_1_pdo_entries[] = {
    {0x7000, 0x01, 16}, /* Analog output */
    {0x7010, 0x01, 16}, /* Analog output */
    {0x7020, 0x01, 16}, /* Analog output */
    {0x7030, 0x01, 16}, /* Analog output */
};

ec_pdo_info_t slave_1_pdos[] = {
    {0x1600, 1, slave_1_pdo_entries + 0}, /* AO RxPDO-Map Outputs Ch.1 */
    {0x1601, 1, slave_1_pdo_entries + 1}, /* AO RxPDO-Map Outputs Ch.2 */
    {0x1602, 1, slave_1_pdo_entries + 2}, /* AO RxPDO-Map Outputs Ch.3 */
    {0x1603, 1, slave_1_pdo_entries + 3}, /* AO RxPDO-Map Outputs Ch.4 */
};

ec_sync_info_t slave_1_syncs[] = {
    {0, EC_DIR_OUTPUT, 0, NULL, EC_WD_DISABLE},
    {1, EC_DIR_INPUT, 0, NULL, EC_WD_DISABLE},
    {2, EC_DIR_OUTPUT, 4, slave_1_pdos + 0, EC_WD_DISABLE},
    {3, EC_DIR_INPUT, 0, NULL, EC_WD_DISABLE},
    {0xff}
};

From the output above, we get information about vendor id and product code from this part

/* Master 0, Slave 1, "EL4004"
 * Vendor ID:       0x00000002
 * Product code:    0x0fa43052
 * Revision number: 0x00140000
 */

we're gonna set the configuration based from information above

{
    "alias": 0,
    "position": 1,
    "vendor_id": "0x00000002",
    "product_code": "0x0fa43052",
    "syncs": []
}

For sync manager configuration, we can look at this part

ec_sync_info_t slave_1_syncs[] = {
    {0, EC_DIR_OUTPUT, 0, NULL, EC_WD_DISABLE},
    {1, EC_DIR_INPUT, 0, NULL, EC_WD_DISABLE},
    {2, EC_DIR_OUTPUT, 4, slave_1_pdos + 0, EC_WD_DISABLE},
    {3, EC_DIR_INPUT, 0, NULL, EC_WD_DISABLE},
    {0xff}
};

we can filter the output above by omitted any sync manager which 4th parameter is NULL. After filtering the output, we get this sync manager that need to be configured

{2, EC_DIR_OUTPUT, 4, slave_1_pdos + 0, EC_WD_DISABLE},

it yields this configuration.

{
    "alias": 0,
    "position": 1,
    "vendor_id": "0x00000002",
    "product_code": "0x0fa43052",
    "syncs": [
        {
            "index": 2,
			"watchdog_enabled": false,
            "pdos": []
        }
    ]
}

item watchdog_enabled can be set based on the last parameter value, it's either EC_WD_DISABLE or EC_WD_ENABLE.

For pdos configuration, we can look at 4th and 3rd parameters. Also, we're gonna need this part

ec_pdo_info_t slave_1_pdos[] = {
    {0x1600, 1, slave_1_pdo_entries + 0}, /* AO RxPDO-Map Outputs Ch.1 */
    {0x1601, 1, slave_1_pdo_entries + 1}, /* AO RxPDO-Map Outputs Ch.2 */
    {0x1602, 1, slave_1_pdo_entries + 2}, /* AO RxPDO-Map Outputs Ch.3 */
    {0x1603, 1, slave_1_pdo_entries + 3}, /* AO RxPDO-Map Outputs Ch.4 */
};

The 4th parameter is slave_1_pdos + 0 and the 3rd parameter is 4. So, we're gonna look at slave_1_pdos array items index 0, 1, 2, and 3. From those array items, we look at the 1st paramater. The 1st parameter is the pdo index. We set pdo index based on that information, and the current configuration would be like this

{
    "alias": 0,
    "position": 1,
    "vendor_id": "0x00000002",
    "product_code": "0x0fa43052",
    "syncs": [
        {
            "index": 2,
			"watchdog_enabled": false,
            "pdos": [
                {
                    "index": "0x1600",
                    "entries": []
                },

                {
                    "index": "0x1601",
                    "entries": []
                },

                {
                    "index": "0x1602",
                    "entries": []
                },

                {
                    "index": "0x1603",
                    "entries": []
                }
            ]
        }
    ]
}

To set PDO entries, we look at this part

ec_pdo_entry_info_t slave_1_pdo_entries[] = {
    {0x7000, 0x01, 16}, /* Analog output */
    {0x7010, 0x01, 16}, /* Analog output */
    {0x7020, 0x01, 16}, /* Analog output */
    {0x7030, 0x01, 16}, /* Analog output */
};

We take PDO index 0x1600 as example. From slaves_1_pdo, we get this information for index 0x1600

{0x1600, 1, slave_1_pdo_entries + 0}, /* AO RxPDO-Map Outputs Ch.1 */

we take a look at 3rd and 2nd parameters. The 3rd parameter is slave_1_pdo_entries + 0 and the 2nd parameter is 1 (the 2nd parameter is the length, how many item we should take starting from slave_1_pdo_entries index 0). With that information, we're gonna look at array slave_1_pdo_entries item index 0.

{0x7000, 0x01, 16}, /* Analog output */

The 1st parameter is the entry CoE index, the 2nd parameter is the CoE subindex, and the 3rd parameter is entry size in bits. The entry configuration for PDO index 0x1600 will look like this

{
    "index": "0x1600",
    "entries": [
        {
            "index": "0x7000",
            "subindex": "0x01",
            "size": 16,

            "add_to_domain": true,

            "swap_endian": false,
            "signed": true
        }
    ]
}

The explanation for PDO entry optional items are like these:

  • add_to_domain

    if it's set to true, then the entry will be added to domains which you can read or write the CoE value. Otherwise will be omitted from domains. (default: false)

  • swap_endian

    if it's set to true, then the CoE value endiannes wil be swapped. Otherwise will be omitted from domains. (default: false)

  • signed

    if it's set to true, then the CoE value will be treated as signed, otherwise it's unsigned. (default: false)

We do the same way for the rest of PDO indexes. Then, the configuration will be like this

{
    "alias": 0,
    "position": 1,
    "vendor_id": "0x00000002",
    "product_code": "0x0fa43052",
    "syncs": [
        {
            "index": 2,
			"watchdog_enabled": false,
            "pdos": [
                {
                    "index": "0x1600",
                    "entries": [
                        {
                            "index": "0x7000",
                            "subindex": "0x01",
                            "size": 16,

                            "add_to_domain": true,
                            "swap_endian": false,
                            "signed": true
                        }
                    ]
                },

                {
                    "index": "0x1601",
                    "entries": [
                        {
                            "index": "0x7010",
                            "subindex": "0x01",
                            "size": 16,

                            "add_to_domain": true,
                            "swap_endian": false,
                            "signed": true
                        }
                    ]
                },

                {
                    "index": "0x1602",
                    "entries": [
                        {
                            "index": "0x7020",
                            "subindex": "0x01",
                            "size": 16,

                            "add_to_domain": true,
                            "swap_endian": false,
                            "signed": true
                        }
                    ]
                },

                {
                    "index": "0x1603",
                    "entries": [
                        {
                            "index": "0x7030",
                            "subindex": "0x01",
                            "size": 16,

                            "add_to_domain": true,
                            "swap_endian": false,
                            "signed": true
                        }
                    ]
                }
            ]
        }
    ]
}

Final configuration

By joining Slave Position 0 and Slave Position 1 configurations, we get this final configuration

[
    {
        "alias": 0,
        "position": 0,
        "vendor_id": "0x00000002",
        "product_code": "0x044c2c52"
    },

    {
        "alias": 0,
        "position": 1,
        "vendor_id": "0x00000002",
        "product_code": "0x0fa43052",
        "syncs": [
            {
                "index": 2,
                "watchdog_enabled": false,
                "pdos": [
                    {
                        "index": "0x1600",
                        "entries": [
                            {
                                "index": "0x7000",
                                "subindex": "0x01",
                                "size": 16,

                                "add_to_domain": true,
                                "swap_endian": false,
                                "signed": true
                            }
                        ]
                    },

                    {
                        "index": "0x1601",
                        "entries": [
                            {
                                "index": "0x7010",
                                "subindex": "0x01",
                                "size": 16,

                                "add_to_domain": true,
                                "swap_endian": false,
                                "signed": true
                            }
                        ]
                    },

                    {
                        "index": "0x1602",
                        "entries": [
                            {
                                "index": "0x7020",
                                "subindex": "0x01",
                                "size": 16,

                                "add_to_domain": true,
                                "swap_endian": false,
                                "signed": true
                            }
                        ]
                    },

                    {
                        "index": "0x1603",
                        "entries": [
                            {
                                "index": "0x7030",
                                "subindex": "0x01",
                                "size": 16,

                                "add_to_domain": true,
                                "swap_endian": false,
                                "signed": true
                            }
                        ]
                    }
                ]
            }
        ]
    }
]

Clone this wiki locally