# EtherCAT read task

> Read the input PDOs of EtherCAT modules into channels.

An EtherCAT read task reads the input PDOs of one or more modules on one network into channels. For example, it can record the two analog inputs of an EL3102 module at 1 kHz.

Before you start, you need [configured modules](https://docs.synnaxlabs.com/reference/hardware/ethercat/configure-device).

## PDO channels

Each channel reads one entry of an input PDO, such as the value of one analog input. The channel selects the entry by its CoE address: an index and a sub-index, such as `0x3101:02`. The Console lists the entries of a module with their addresses. The entries come from the scan and depend on the revision of the module. For example, an EL3102 can show a `Value` entry at `0x3101:02` and another at `0x3102:02`, one for each input.

The data type of a channel must be a number type of the same size as its entry, in whole bytes. For example, a 16-bit entry takes `int16` or `uint16`.

All modules in a task must be on the same port. The **Sample rate** sets how often the task takes a sample from the network. The network on a port cycles at a multiple of the sample rate of each read task, from 100 Hz to 10 kHz. If no such rate exists, for example for read tasks at 3 kHz and 4 kHz, the task does not start. See [how the Driver runs a network](https://docs.synnaxlabs.com/reference/hardware/ethercat/configure-device#how-the-driver-runs-a-network).

Each sample has the time of the network cycle that read it. Without IgH, if a module on the network has a distributed clock, the Driver measures that time with the distributed clock. The timestamps then show when the EtherCAT frame passed the modules, without the jitter of the computer clock, and they stay in line with the computer clock. When the computer is busy, a cycle can still run late, and its timestamp shows the delay. See [timing](https://docs.synnaxlabs.com/reference/hardware/tasks#timing).

## Create an EtherCAT read task

[Enterprise](https://docs.synnaxlabs.com/reference/get-started/editions "Needs Synnax Enterprise")

**Console**

1. In the devices toolbar, right-click a module and select **Create read task**.
2. Set **Sample rate** and **Stream rate**.
3. Click **Add channel**, then select the module in **Slave device**. A new channel starts with the module of the last channel.
4. Select an entry in **Entry**. **Data type** then shows the type of the entry.
5. Click (**Start**).

The Console creates the channels and names them after the identifier of the module and the name of the entry, such as `ai1_Value` for a module with the identifier `ai1`. If the module has more than one entry with that name, the Console adds the PDO name, or the address when the module gives no PDO name, such as `ai1_Value_3101_02`. The index channel is `ai1_time`.

Starting or stopping a task does not restart the network. The other tasks on the port keep running.

[](https://synnax.nyc3.cdn.digitaloceanspaces.com/docs/hardware/ethercat/read-task-dark.mp4#t=0.001)

**Python**

Python does not create channels. Create them first.

```python
import synnax as sy
from synnax import ethercat

module = client.devices.retrieve(key="<module key>")
time = client.channels.create(
    name="ai1_time", is_index=True, data_type=sy.DataType.TIMESTAMP
)
ch1 = client.channels.create(
    name="ai1_ch1", index=time.key, data_type=sy.DataType.INT16
)
ch2 = client.channels.create(
    name="ai1_ch2", index=time.key, data_type=sy.DataType.INT16
)

task = ethercat.ReadTask(
    name="Analog inputs",
    sample_rate=1000,
    stream_rate=25,
    channels=[
        ethercat.EntryReadChannel(
            device=module.key,
            index=0x3101,
            sub_index=0x02,
            data_type=sy.DataType.INT16,
            channel=ch1.key,
        ),
        ethercat.EntryReadChannel(
            device=module.key,
            index=0x3102,
            sub_index=0x02,
            data_type=sy.DataType.INT16,
            channel=ch2.key,
        ),
    ],
)
client.tasks.configure(task)
task.start()
```

To find an entry by its name, use `ethercat.find_entry(module, "<name>")`. It returns the `index`, `sub_index`, and `data_type` of the entry. It raises `sy.NotFoundError` if no entry has the name, and `sy.MultipleFoundError` if entries at more than one address have it. To select one of them, also pass `pdo_name`, the name of the PDO that holds the entry, such as `"Channel 1"`.

**TypeScript**

TypeScript does not create channels. Create them first.

```typescript
import { ethercat } from "@synnaxlabs/client";

const module = await client.devices.retrieve({ key: "<module key>" });
const time = await client.channels.create({
  name: "ai1_time",
  isIndex: true,
  dataType: "timestamp",
});
const ch1 = await client.channels.create({
  name: "ai1_ch1",
  index: time.key,
  dataType: "int16",
});

const task = await client.tasks.create({
  name: "Analog inputs",
  rack: module.rack,
  type: "ethercat_read",
  config: ethercat.readConfigZ.parse({
    sampleRate: 1000,
    streamRate: 25,
    channels: [
      {
        type: "entry",
        device: module.key,
        index: 0x3101,
        subIndex: 0x02,
        dataType: "int16",
        channel: ch1.key,
      },
    ],
  }),
});
await task.start();
```

To find an entry by its name, use `ethercat.findEntry(inputs, "<name>")`, where `inputs` is `pdos.inputs` of the device properties. It throws `NotFoundError` if no entry has the name, and `MultipleFoundError` if entries at more than one address have it. To select one of them, pass the name of the PDO that holds the entry as the third argument.

## Task options

| Console label | Python field           | Default | Notes                                                                                |
| ------------- | ---------------------- | ------- | ------------------------------------------------------------------------------------ |
| Sample rate   | `sample_rate`          | 10 Hz   | Up to 10 kHz. A whole multiple of the stream rate.                                   |
| Stream rate   | `stream_rate`          | 5 Hz    | See [read tasks](https://docs.synnaxlabs.com/reference/hardware/tasks#read-tasks).   |
| Data saving   | `data_saving_disabled` | On      | See [data saving](https://docs.synnaxlabs.com/reference/hardware/tasks#data-saving). |
| Auto start    | `auto_start`           | Off     | Starts the task each time the Driver starts.                                         |

## Channel reference

Each channel has a `device`, the key of the module (**Slave device**), and a `channel`, the Synnax channel that records the value. Each table shows the Console label of a setting, with its Python field under it.

**Entry**

#### [Entry](https://docs.synnaxlabs.com/reference/hardware/ethercat/read-task#entry)

Python `EntryReadChannel`TypeScript `entry`

Reads one input entry at its CoE address.

| Setting                    | Default | Notes                                        |
| -------------------------- | ------- | -------------------------------------------- |
| Entry `index`, `sub_index` |         | The CoE address, such as `0x3101:02`.        |
| Data type `data_type`      |         | A number type of the same size as the entry. |

A task from an earlier release can also hold an `unresolved` channel (`UnresolvedReadChannel`). It has the name of an entry, but no address. See [troubleshooting](https://docs.synnaxlabs.com/reference/hardware/ethercat/read-task#a-channel-from-an-earlier-release-has-no-entry).

## Troubleshooting

### A channel from an earlier release has no entry

Earlier releases could select an entry by its name. If the module has more than one entry with that name, or none, the upgrade cannot find the address of the entry. The Console marks the channel with an error, and the task does not start. The error reads “… matches more than one input entry …” or “… matches no input entry …”.

Select an entry for the channel in **Entry**. The first entry in the list with that name is the one that the task read before, and it keeps the old channel.

### “All slaves must be on the same network”

The task uses modules on two ports. Create one task for each port.

### “sample_rate must be divisible by stream_rate”

Set a sample rate that is a whole multiple of the stream rate, such as 1000 Hz and 25 Hz.

### “no bus rate at or below 10000 Hz …”

The sample rates of the read tasks on the port have no common multiple at or below 10 kHz. Use sample rates with a small common multiple, such as 250 Hz and 1 kHz.

### “Failed to read data”

A module on the port stopped responding, so every network cycle fails. Every read task on the port shows this warning and pauses. The [module status](https://docs.synnaxlabs.com/reference/hardware/ethercat/configure-device#module-status) shows which module is lost. Check its power and its cable.

The task keeps trying, at most 5 seconds apart, and its data starts again when the module responds. You do not need to restart the task.

### “Slave … has no input entry at …”

The module has no input entry at the address of the channel. Select an entry from the list again. In code, use an address that the Console lists, or find the entry by its name.

### “Data type … does not fit entry …”

The data type of the channel has a different size from the entry. Select a number type of the same size, such as `int16` for a 16-bit entry. From code, the Driver reports “data type … is … but entry … holds …”.

### “More than one channel uses entry …”

Two channels of the task use the same entry. Select a different entry for one of them. From code, the Driver reports “another channel already uses entry …”.

For other problems, see [Configure an EtherCAT device](https://docs.synnaxlabs.com/reference/hardware/ethercat/configure-device#troubleshooting) and [Troubleshoot hardware](https://docs.synnaxlabs.com/reference/hardware/troubleshooting).
