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.
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:
- 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.
- 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.
-
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:01and 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:
- 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.
-
Build the map arrays. Create one
ABCC_PdAdiMapTypearray for write direction (device to network) and one for read direction, then wrap each in anABCC_PdMapTypewithiNbrMapsset to the array length. A mismatch betweeniNbrMapsand the real array length is the classic cause of garbage in the last PDO or a startup fault. - Register the map with the driver during the ABCC setup/mapping phase, before the module transitions to the state where process data is exchanged.
- 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.
- 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.
Verification on the Live Network
Do not trust the intent of your source code. Read back what the device published.
-
Enumerate the mapping objects by SDO. From the master or a CANopen configuration tool, upload
0x1A00:00,0x1A01:00, ... and0x1600: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. - 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).
-
Test for variable mapping. Attempt an SDO download of
0x00to0x1A00:00. Success means the device supports dynamic remapping and you may be able to pack multiple entries. An SDO abort (typical codes:0x06010002write-to-read-only,0x06090030value range,0x08000022wrong 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. -
Capture the bus. With a CAN analyzer, put the node in Operational (NMT command
0x01with node-ID, or0x00for 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. - 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
- Count the ADIs you intend to map cyclically in each direction and assume, until proven otherwise, one PDO each.
- Confirm the PDO count fits the default connection set (4 TPDO + 4 RPDO); plan explicit COB-ID assignment if it does not.
- Confirm no mapped ADI exceeds 64 bits.
- Compute bus load at the target cycle time and bit rate; leave headroom for SDO, heartbeat and EMCY.
- Read back
0x16xx/0x1Axxfrom the live device and archive the decoded map with the project files. - 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.