
EtherCAT PDO Mapping Explained: RxPDO, TxPDO, and Process Data
EtherCAT is one of the fastest fieldbuses in industrial motion control โ but raw speed means nothing unless the master and slaves agree on exactly which data travels in each cycle.
That agreement is PDO mapping.
Getting PDO configuration wrong is one of the most common causes of EtherCAT commissioning failures: drives that never leave the SAFE-OP state, IOmap reads that return garbage, or position commands that silently do nothing. This post explains the full mechanism from object dictionary indices down to byte-level IOmap access in C.
What Is a PDO?
PDO stands for Process Data Object.
In EtherCAT's CoE (CANopen over EtherCAT) layer, a PDO is the mechanism for exchanging real-time, cyclic process data โ the fast path that carries control words, target positions, actual velocities, and status words every single network cycle.
Every variable a slave exposes for real-time exchange lives inside the PDO. The master reads and writes these variables by directly accessing a shared memory region called the IOmap โ no protocol overhead, no handshake, just a memory copy stamped onto each Ethernet frame.
SDO vs PDO: The Critical Distinction
EtherCAT slaves expose two communication mechanisms:
| | SDO | PDO | |---|---|---| | Full name | Service Data Object | Process Data Object | | Timing | Acyclic โ on demand | Cyclic โ every EtherCAT cycle | | Latency | Milliseconds | Microseconds | | Use case | Configuration, parameter reads | Real-time control data | | Addressing | Index + subindex | Mapped into IOmap offset |
SDOs are used during startup to configure drives โ setting motion profiles, current limits, homing modes, and PDO assignment itself. Once the drive enters OP state, SDO transactions stop and the PDO data stream takes over.
PDOs are what your servo loop reads every 1 ms (or 250 ยตs, or 500 ยตs) to close the position or velocity loop. There is no acknowledgement, no retry โ just deterministic data exchange at network cycle rate.
Trying to use SDOs at full cycle rate will overflow the mailbox and destabilize the network. Everything time-critical must go through PDOs.
RxPDO and TxPDO: From the Slave's Perspective
The naming convention trips up most engineers the first time.
RxPDO โ data the slave receives from the master. This is the master's output: target position, target velocity, controlword, torque feedforward.
TxPDO โ data the slave transmits to the master. This is the master's input: actual position, actual velocity, statusword, following error.
From the master's code you write into RxPDO memory and read from TxPDO memory. The slave's documentation uses the opposite frame of reference โ always check which end is speaking before interpreting an index.
Master Slave (Servo Drive)
โ โ
โ โโ RxPDO (master output) โโโโโโโโโโโบ โ controlword, target pos
โ โ
โ โโโ TxPDO (slave output) โโโโโโโโโโ โ statusword, actual pos
โ โ
The CANopen Object Dictionary
Every CoE slave has an object dictionary โ a structured table of parameters addressed by a 16-bit index and an 8-bit subindex.
PDO mapping occupies two specific index ranges:
- 0x1600โ0x17FF โ RxPDO Mapping Objects (what the slave receives)
- 0x1A00โ0x1BFF โ TxPDO Mapping Objects (what the slave transmits)
Each mapping object is itself a sub-indexed list. Subindex 0 holds the count of mapped objects. Subindex 1 onward holds 32-bit descriptors, each encoding the target object index (16 bits), subindex (8 bits), and bit length (8 bits):
Descriptor (32-bit):
[31:16] = Object Index e.g. 0x6040
[15:8] = Subindex e.g. 0x00
[7:0] = Bit length e.g. 0x10 (16 bits)
For example, object 0x1600 subindex 1 holding 0x60400010 means: map object 0x6040 (controlword), subindex 0, 16-bit wide โ into this RxPDO.
PDO Assignment Objects: 0x1C12 and 0x1C13
Defining which objects appear in a PDO is only half the work. The slave also needs to know which PDO mapping objects are active for a given sync manager.
This is controlled by the PDO assignment objects:
- 0x1C12 โ Sync Manager 2 PDO Assignment (RxPDO, master output)
- 0x1C13 โ Sync Manager 3 PDO Assignment (TxPDO, slave output)
Subindex 0 is again the count. Subindex 1, 2, โฆ list the active mapping object indices. A typical single-PDO drive has:
0x1C12 subindex 0 = 1 (one RxPDO active)
0x1C12 subindex 1 = 0x1600 (use mapping object 0x1600)
0x1C13 subindex 0 = 1 (one TxPDO active)
0x1C13 subindex 1 = 0x1A00 (use mapping object 0x1A00)
Multi-axis modules or drives with extended diagnostics may activate multiple mapping objects and stack them end-to-end in the sync manager buffer.
Default CiA 402 PDO Mappings
The CiA 402 profile standardises servo drive object indices. Most servo drives ship with a default PDO mapping that covers the four essential variables for position mode:
| Object | Name | Size | Direction | |---|---|---|---| | 0x6040 | Controlword | 16-bit | RxPDO | | 0x607A | Target Position | 32-bit | RxPDO | | 0x6041 | Statusword | 16-bit | TxPDO | | 0x6064 | Position Actual Value | 32-bit | TxPDO |
The default RxPDO (0x1600) therefore maps 6 bytes: 2 bytes controlword + 4 bytes target position. The default TxPDO (0x1A00) maps 6 bytes: 2 bytes statusword + 4 bytes actual position.
Velocity mode adds 0x60FF (target velocity, 32-bit) to the RxPDO and 0x606C (velocity actual value, 32-bit) to the TxPDO. Torque mode swaps in 0x6071 and 0x6077.
Always verify the exact mapping against the drive's ESI file โ vendors frequently deviate from the CiA 402 defaults and add proprietary objects.
How SOEM Auto-Configures PDO Mapping from ESI Files
SOEM (Simple Open EtherCAT Master) is the most widely used open-source EtherCAT master library. It reads slave configuration from ESI files (EtherCAT Slave Information, XML format) that vendors ship with their drives.
The ESI file declares the exact PDO mapping โ which sync managers are used, which mapping objects are active, and the bit layout of each variable. SOEM parses this during ec_config() and builds the IOmap automatically.
# Build SOEM from source
git clone https://github.com/OpenEtherCATsociety/SOEM.git
cd SOEM && mkdir build && cd build
cmake .. && make -j$(nproc)
The key SOEM call that wires everything together is ec_config_map():
#include "ethercat.h"
#define IOmap_SIZE 4096
char IOmap[IOmap_SIZE];
int main(void)
{
if (ec_init("eth0") <= 0) {
printf("No socket connection on eth0\n");
return -1;
}
if (ec_config_find_and_autoconfig() > 0) {
ec_config_map(&IOmap); /* builds IOmap from ESI data */
ec_configdc(); /* configure distributed clocks */
ec_statecheck(0, EC_STATE_SAFE_OP, EC_TIMEOUTSTATE * 4);
ec_slave[0].state = EC_STATE_OPERATIONAL;
ec_writestate(0);
ec_statecheck(0, EC_STATE_OPERATIONAL, EC_TIMEOUTSTATE * 5);
}
return 0;
}
After ec_config_map() returns, each slave's inputs and outputs pointers inside ec_slave[] point into the IOmap at the correct byte offsets. SOEM has done the PDO-to-byte-offset arithmetic for you.
Reading a TxPDO Value from IOmap in C
Once the network is in OP state and ec_receive_processdata() has been called, the TxPDO data sits in the IOmap at the slave's input offset.
The byte offset for slave n is ec_slave[n].inputs - (uint8_t *)IOmap.
For the default CiA 402 TxPDO layout (statusword at byte 0, actual position at byte 2):
#include <stdint.h>
#include "ethercat.h"
/* Call after ec_receive_processdata() each cycle */
void read_slave_feedback(int slave_idx)
{
uint8_t *base = ec_slave[slave_idx].inputs;
/* statusword: 16-bit at byte offset 0 */
uint16_t statusword = *(uint16_t *)(base + 0);
/* actual position: 32-bit at byte offset 2 */
int32_t actual_pos = *(int32_t *)(base + 2);
printf("Slave %d status=0x%04X pos=%d counts\n",
slave_idx, statusword, actual_pos);
}
EtherCAT frames use little-endian byte order. On x86 Linux this is transparent; on big-endian targets use le16toh() / le32toh() from <endian.h>.
Never compute the byte offset manually from scratch โ always derive it from ec_slave[n].inputs after ec_config_map() has run. Hard-coded offsets break the moment the ESI-defined PDO layout differs from your assumption.
Writing to an RxPDO: Setting Target Velocity
Writing follows the same pattern but targets the outputs pointer. Call ec_send_processdata() after updating.
/* Cyclic motion loop โ runs every 1 ms */
void cyclic_task(int slave_idx, int32_t target_vel, uint16_t ctrl_word)
{
uint8_t *base = ec_slave[slave_idx].outputs;
/* controlword: 16-bit at byte offset 0 */
*(uint16_t *)(base + 0) = ctrl_word;
/* target velocity: 32-bit at byte offset 2 (velocity mode PDO) */
*(int32_t *)(base + 2) = target_vel;
ec_send_processdata();
ec_receive_processdata(EC_TIMEOUTRET);
}
The drive only acts on the written values when its state machine is in OP and the controlword enables the power stage โ writing a non-zero target velocity while the drive is in SWITCH ON DISABLED does nothing and is not an error.
Common PDO Configuration Mistakes
Wrong byte order. EtherCAT uses little-endian. If you cast a 32-bit pointer on a big-endian host without byte-swapping, position values will read as large garbage numbers. Always use le32toh() on non-x86 targets.
IOmap offset errors. Computing byte offsets from the PDO mapping XML by hand is error-prone. Trust ec_slave[n].inputs / ec_slave[n].outputs โ they are set correctly by ec_config_map(). If they point to NULL, the slave failed to reach SAFE-OP and the ESI file was never parsed.
PDO size mismatch. When the drive has a non-default PDO assignment (e.g., two mapping objects active instead of one), the actual byte layout differs from the simple 6-byte CiA 402 default. The slave will refuse to enter OP, or ec_slave[n].Obits / ec_slave[n].Ibits will not match your expected values. Cross-check both against ec_readPDOmap() output.
Forgetting subindex 0. When reconfiguring PDO mapping via SDO at runtime (rather than relying on ESI defaults), you must write 0x00 to subindex 0 of the mapping object before writing the descriptors, then write the correct count back last. Skipping this leaves the drive in an inconsistent state.
Modifying PDO assignment while in OP. PDO assignment objects (0x1C12, 0x1C13) are only writable in PRE-OP state. Attempting an SDO write to these objects in SAFE-OP will return an abort code and the mapping will not change.
Need PDO Configuration for Your Servo Drive?
Lichi Robotics handles complete EtherCAT PDO mapping and slave configuration for any servo drive brand โ Yaskawa, Siemens, Panasonic, Delta, Beckhoff, and more.
๐ Explore EtherCAT Solutions โ
WhatsApp Us โ free demo with setup support included.
