CANopen PDO Mapping with Anybus CompactCom ADI Setup

Daniel Price9 min read
Industrial NetworkingOther ManufacturerTechnical Reference
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

Overview: How ADIs Become PDOs

The Anybus CompactCom (ABCC) presents application data to any supported fieldbus through a single abstraction: the ADI (Application Data Instance). The host application declares ADIs, then declares which ADIs are exposed cyclically by filling a process-data map. On a CANopen host interface, that cyclic map is what the ABCC turns into PDOs and into the CANopen mapping objects visible to the master.

The host-side map structure used by the ABCC driver is:

typedef struct ABCC_PdMapType
{
   UINT16               iNbrMaps;  /* Number of ADI Write/Read mappings
                                      present in asMaps[] array. */
   ABCC_PdAdiMapType*   psMaps;    /* Pointer to array of ADI mappings */
} ABCC_PdMapType;

Each element of the psMaps array is one ADI mapping entry. The practical consequence reported from integration work on this interface is that the CompactCom generates one PDO per entry in psMaps rather than packing several ADI entries into one PDO frame. If that behavior holds for your firmware revision, you cannot aggregate multiple ADIs into a single 8-byte CAN frame by adding more entries to the array.

Ambiguity to resolve before you design around it: the one-ADI-per-PDO behavior described here is an observed characteristic of the ABCC host driver's process-data mapping, not a documented guarantee of the CANopen specification. Confirm it against the CANopen network guide and the ABCC driver release notes for your exact module and firmware before committing a PDO budget. The decision path is in the verification section below.

The CANopen Objects Involved

Whatever the host driver does internally, the master sees a standard CiA 301 object dictionary. These are the objects to inspect when you want to know what the CompactCom actually produced:

Object range Function Direction (device view)
0x1400-0x15FF RPDO communication parameters (COB-ID, transmission type, inhibit/event timer) Received by device
0x1600-0x17FF RPDO mapping parameters (sub-index 0 = number of mapped objects, sub 1..n = mapping entries) Received by device
0x1800-0x19FF TPDO communication parameters Transmitted by device
0x1A00-0x1BFF TPDO mapping parameters Transmitted by device

A mapping entry in 0x16xx/0x1Axx is a 32-bit value:

bits 31..16 : index of mapped object
bits 15..8  : sub-index of mapped object
bits 7..0   : object length in BITS

Example: mapping a 16-bit process value at index 0x2001, sub-index 0x01 gives the entry 0x20010110 (0x10 = 16 bits).

The hard physical constraint is the CAN data field: 8 bytes = 64 bits maximum per PDO. The sum of the length fields of all sub-entries in one 0x16xx/0x1Axx record must not exceed 64. This limit applies regardless of whether the CompactCom packs one ADI or several into that PDO.

Consequences of One ADI per PDO

If each ADI mapping entry produces its own PDO, three design consequences follow directly:

  1. PDO count scales with ADI count, not with byte count. Sixteen 2-byte ADIs consume sixteen TPDOs instead of the four PDOs they would need if packed 4 x 2 bytes per frame.
  2. Bus load rises sharply. Each PDO is a full CAN frame with arbitration field, CRC and inter-frame space regardless of payload. Eight separate 1-byte PDOs cost roughly eight times the bus time of one 8-byte PDO carrying the same data.
  3. COB-ID budget. The CiA 301 predefined connection set gives a node only four default TPDOs and four default RPDOs. Beyond that you must assign COB-IDs manually through 0x1800+n:01 / 0x1400+n:01 and check for collisions with other nodes' default ranges, SYNC (0x080), EMCY (0x080 + Node-ID), SDO (0x580/0x600 + Node-ID) and NMT error control (0x700 + Node-ID).

Work-arounds when you need packed frames

Approach How it works Trade-off
Composite ADI Declare one ADI as an array or structured element containing all the values that must travel together; map that single ADI. Host application must pack/unpack manually; total ADI size must stay within 64 bits for a single PDO.
Master-side remap If the device permits dynamic PDO mapping, the master writes 0x16xx/0x1Axx sub-index 0 = 0, writes the desired sub-entries, then restores sub-index 0 to the entry count. Only works if the CompactCom advertises variable mapping; otherwise SDO abort. Check before designing.
Reduce cyclic set Move low-rate or configuration values out of the process-data map and read them acyclically via SDO. Higher latency for those values; SDO traffic must be scheduled.
Transmission type tuning Leave the PDO count high but throttle with event timers (0x1800+n:05) and inhibit times (0x1800+n:03). Data freshness drops; not a fix for COB-ID exhaustion.

Configuration Sequence on the Host Side

Build the process-data map before the ABCC leaves the setup state. Order of operations in the host application:

  1. Define ADIs. Populate the ADI entry list with index, name, data type, element count and access descriptor. Every ADI you intend to map cyclically must exist here first.
  2. Build the map arrays. Create one ABCC_PdAdiMapType array for write direction (device to network) and one for read direction, then wrap each in an ABCC_PdMapType with iNbrMaps set to the array length. A mismatch between iNbrMaps and the real array length is the classic cause of garbage in the last PDO or a startup fault.
  3. Register the map with the driver during the ABCC setup/mapping phase, before the module transitions to the state where process data is exchanged.
  4. Set the CANopen node parameters — Node-ID and baud rate — through the network-specific host object, or through hardware switches if the carrier board provides them. These must be settled before NMT startup.
  5. Handle the process-data callbacks. Copy fresh values into the write buffer and consume the read buffer on every cyclic update event; do not block inside the callback.
Sizing check: before you build, sum the mapped ADI sizes in bytes for each direction and compare with the maximum process-data size of your CompactCom module and with the number of PDOs you can afford on the bus. A map that the host driver accepts can still be rejected by the module if it exceeds the module's process-data limit.

Verification on the Live Network

Do not trust the intent of your source code. Read back what the device published.

  1. Enumerate the mapping objects by SDO. From the master or a CANopen configuration tool, upload 0x1A00:00, 0x1A01:00, ... and 0x1600:00, 0x1601:00, ... Sub-index 0 is the count of mapped objects. If every populated mapping object shows a count of 1, the one-ADI-per-PDO behavior is confirmed on your firmware.
  2. Decode each sub-entry. Upload sub-index 1..n and split the 32-bit value into index / sub-index / bit length. Verify the bit length matches the declared ADI data type (8, 16, 32, 64).
  3. Test for variable mapping. Attempt an SDO download of 0x00 to 0x1A00:00. Success means the device supports dynamic remapping and you may be able to pack multiple entries. An SDO abort (typical codes: 0x06010002 write-to-read-only, 0x06090030 value range, 0x08000022 wrong device state) means the mapping is static or the device is in the wrong NMT state — remapping generally requires the device to be out of operational PDO exchange.
  4. Capture the bus. With a CAN analyzer, put the node in Operational (NMT command 0x01 with node-ID, or 0x00 for all nodes) and count distinct COB-IDs and their DLC. One 2-byte frame per value confirms unpacked PDOs; an 8-byte frame carrying four values confirms packing.
  5. Measure bus load. Multiply frame count per cycle by the frame time at your bit rate and compare with the cycle period. Keep steady-state load with margin for SDO, EMCY and heartbeat traffic.

Bus-load reference

An 11-bit-identifier CAN data frame is approximately 47 + 8 x N bits before stuffing, where N is the payload byte count. At 500 kbit/s, one bit time is 2 us. Use this to compare packed and unpacked layouts:

Layout for 8 bytes of process data Frames Approx. raw bits Approx. time @ 500 kbit/s
1 PDO x 8 bytes 1 111 ~222 us
4 PDOs x 2 bytes 4 252 ~504 us
8 PDOs x 1 byte 8 440 ~880 us

Bit stuffing adds up to roughly 20% in worst case; treat these figures as lower bounds and add margin plus inter-frame space (minimum 3 bit times).

Common Failure Modes

Symptom Likely cause Action
Module refuses to leave setup state Mapped process-data size exceeds module limit, or iNbrMaps does not match the array Recount the array; sum mapped bytes per direction
Last mapped value is stale or garbage iNbrMaps larger than the real array; reading past the end Fix the count constant; derive it with sizeof(arr)/sizeof(arr[0])
Master reports missing PDO / no data COB-ID collision or PDO disabled (bit 31 of 0x1400+n:01 / 0x1800+n:01 set) Read back COB-ID entries; clear the valid bit correctly
SDO abort when remapping Static mapping, or device in Operational state Set NMT Pre-Operational, retry; if still aborted, mapping is fixed
TPDO never transmits Transmission type is synchronous (0-240) but no SYNC producer on the bus Enable a SYNC producer, or set transmission type 254/255 with an event timer
Intermittent frame loss under load Bus load too high from unpacked PDOs Pack into composite ADIs, raise bit rate, or add inhibit times

Design Checklist

  1. Count the ADIs you intend to map cyclically in each direction and assume, until proven otherwise, one PDO each.
  2. Confirm the PDO count fits the default connection set (4 TPDO + 4 RPDO); plan explicit COB-ID assignment if it does not.
  3. Confirm no mapped ADI exceeds 64 bits.
  4. Compute bus load at the target cycle time and bit rate; leave headroom for SDO, heartbeat and EMCY.
  5. Read back 0x16xx/0x1Axx from the live device and archive the decoded map with the project files.
  6. Test whether dynamic remapping is accepted; if it is, keep it as a packing option, but note that master configuration then becomes part of the commissioning procedure.

Can I map multiple ADIs into a single CANopen PDO on an Anybus CompactCom?

Integration experience with the ABCC host driver indicates each entry in the psMaps array of ABCC_PdMapType becomes its own PDO, so several ADIs are not packed into one frame. The practical work-around is to declare one composite ADI (array or structure) that carries all the values, keeping it within the 64-bit CAN payload limit.

How do I read back the actual PDO mapping a CompactCom created?

SDO-upload 0x1A00:00 onward for TPDOs and 0x1600:00 onward for RPDOs. Sub-index 0 gives the number of mapped objects; each sub-entry 1..n is a 32-bit value of index (bits 31-16), sub-index (bits 15-8) and bit length (bits 7-0).

What is the maximum data a single CANopen PDO can carry?

8 bytes, i.e. 64 bits, set by the CAN data field. The sum of the bit-length fields of all sub-entries in one 0x16xx or 0x1Axx mapping record must not exceed 64.

Why does my SDO write to 0x1A00 sub-index 0 abort?

Either the device uses static mapping, or it is in the Operational state. Send NMT Enter Pre-Operational (command 0x80) and retry; a persistent abort such as 0x06010002 means the mapping object is read-only and cannot be repacked from the master.

How much extra bus load do unpacked PDOs cost?

A standard-ID CAN data frame is roughly 47 + 8 x N bits before stuffing. Splitting 8 bytes into four 2-byte PDOs raises raw frame bits from about 111 to about 252 — roughly 2.3x the bus time for the same payload.

My TPDO never transmits even though the mapping looks correct. What is wrong?

Check the transmission type in 0x1800+n:02. Values 0-240 are synchronous and require a SYNC producer on the bus; with no SYNC, nothing is sent. Set 254 or 255 with an event timer in sub-index 5 for asynchronous cyclic transmission.

Back to blog