CANopen is a standardised application layer and a family of device profiles that turn a bare CAN bus into a network of interchangeable, self-describing devices. CAN on its own covers only the lowest two layers of the communication stack. It moves messages of at most eight data bytes over a two-wire line, resolves competing transmissions by message priority, and detects errors with a 15-bit CRC and several protocol-level checks [1][3]. What CAN does not define is which identifier belongs to which node, what the bytes inside a message mean, how a tool reads a parameter out of a device, or how a controller notices that a sensor has gone silent. CANopen defines all of that [1][2].
The protocol exists because those missing pieces used to be reinvented in every project. CAN in Automation first specified the CAN Application Layer, which offered a complete set of communication tools but still left every user to design an application-specific profile. CANopen was developed as a profile on top of it for embedded networking in production cells and released in fully revised form in 1995 [2]. Version 4 made the document self-contained, it is published today as CiA 301, and CANopen is one of the application layers standardised in the EN 50325 series [1][2][5].
A CANopen device is described by an object dictionary and an electronic data sheet, it announces itself on power-up, it accepts configuration writes before it may produce process data, and it reports faults through a defined emergency message [1][2]. Typical use cases are machine control, factory and process automation, motion control, medical equipment, maritime electronics, lift control and off-highway vehicles [2][6]. Three real designs appear later, a stepper drive implementing the CiA 402 motion profile, a protocol stack shipped inside a microcontroller SDK, and an isolated bus interface for a controller module [4][5][6].
Technical Details
CAN is message oriented. A frame carries an identifier rather than a destination address, and every node decides for itself whether that identifier is relevant [1][3]. Broadcast and multicast are therefore natural, but identifier assignment becomes a system design decision, and CANopen takes that decision away from the integrator with a default identifier layout and a defined way to change it [1]. The reference model has three layers rather than seven, because inter-network routing, reliable transport and session handling have no role in a control loop [1]. Arbitration stays non-destructive, so the highest-priority message is never lost in a collision, which is what lets a designer reason about worst-case latency [1][3].
The object dictionary
Every CANopen node contains an object dictionary, a lookup table addressed by an unsigned 16-bit index and an unsigned 8-bit subindex that holds every parameter, process value and communication setting the node exposes [1][2]. Knowing it is equivalent to knowing how the device will behave on the bus. A simple variable uses subindex 00h, while an array or record uses subindex 00h for the element count and 01h upwards for the elements [1].
Indexes are grouped by function, as shown in Table 1, which is what makes generic tooling possible. A tool that finds an entry at 6000h knows it is a standardised device profile parameter, while one that finds an entry at 2500h must consult the manufacturer documentation [1][4]. Entries below 1000h describe data types rather than store values, so an entry declared as type 0007h is an UNSIGNED32 [1][2]. The boundaries above A000h should be taken from the current CiA 301 revision, since later revisions assigned meaning to ranges earlier ones reserved [1][4].
| Index range [HEX] | Content | Defined by |
| 0001h – 003Fh | Static and complex data types | CiA 301 |
| 0040h – 009Fh | Manufacturer and profile specific types | Manufacturer, profile |
| 1000h – 1FFFh | Communication profile area | CiA 301 |
| 2000h – 5FFFh | Manufacturer specific area | Manufacturer |
| 6000h – 9FFFh | Standardised device profile area | Device profile |
| A000h – BFFFh | Standardised interface profile area | Interface profile |
Only a few entries are mandatory, namely the device type at 1000h, the error register at 1001h, the identity object at 1018h, one server SDO, and either heartbeat or node guarding [1][2]. A device also ships with an electronic data sheet listing its supported entries, which lets a tool present parameters by name instead of by index [1][2].
Service data objects
A service data object gives one node read and write access to the object dictionary of another. The relationship is client and server, the device whose dictionary is accessed is the server, and every compliant node implements at least one server SDO [1]. Each transfer carries the index and subindex of the target entry in the first three data bytes, a combination called the multiplexor that lets one connection address the whole dictionary unambiguously [1].
Three transfer procedures exist. Expedited transfer is mandatory and moves up to four bytes in a single request and response pair. Segmented transfer is required once a device exposes larger entries, carrying seven payload bytes per segment with a toggle bit that keeps request and response aligned. Block transfer is optional and cuts acknowledgement overhead for large blocks [1][2]. A request that cannot be served draws an abort message carrying a 32-bit code naming the reason [1][4].
The first data byte of every SDO message is a command byte. Its upper three bits carry the command specifier, which distinguishes a download request from an upload request and from the matching responses. For an expedited write the byte also encodes how many of the four data bytes are unused and whether the size is indicated [1][2]. The function below assembles a complete request into a frame structure holding an identifier, a length and eight payload bytes, using fixed-width types, named constants and a single exit point.
#define SDO_REQ_COB_BASE (0x600U)
#define SDO_CS_DOWNLOAD (1U)
#define SDO_EXPEDITED_BYTES (4U)
bool sdo_expedited_write(can_frame_t * const frame,
const uint8_t node_id,
const uint16_t index,
const uint8_t subindex,
const uint32_t value,
const uint8_t size)
{
bool is_valid = false;
if ((frame != NULL) && (node_id >= 1U) && (node_id <= 127U) &&
(size >= 1U) && (size <= SDO_EXPEDITED_BYTES))
{
const uint8_t unused = (uint8_t)(SDO_EXPEDITED_BYTES - size);
uint8_t i;
(void)memset(frame, 0, sizeof(*frame));
frame->identifier = (uint16_t)(SDO_REQ_COB_BASE + node_id);
frame->length = 8U;
/* command specifier, unused byte count, size flags */
frame->payload[0] = (uint8_t)((SDO_CS_DOWNLOAD << 5U) |
(uint8_t)(unused << 2U) |
0x03U);
frame->payload[1] = (uint8_t)(index & 0x00FFU);
frame->payload[2] = (uint8_t)(index >> 8U);
frame->payload[3] = subindex;
for (i = 0U; i < size; i++)
{
frame->payload[4U + i] = (uint8_t)(value >> (8U * i));
}
is_valid = true;
}
return is_valid;
}
A one-byte write therefore produces a command byte of 2Fh, a two-byte write 2Bh and a four-byte write 23h, and the server confirms any of them with 60h [1][2]. The index goes out least significant byte first, which is the order CANopen uses throughout [1][5]. All eight bytes are always transmitted even when one carries information, which is why SDO traffic suits configuration rather than cyclic process data [1][2].
Process data objects
A process data object carries application data with no protocol overhead. All eight data bytes belong to the application, because producer and consumer already agree on the layout through the PDO mapping held in both object dictionaries [1]. Any number of nodes may consume the same PDO, so one input module can feed several output modules with a single message without the controller relaying anything [1][2].
Each PDO is described by two entries. The communication parameter record holds the identifier, the transmission type, the inhibit time and the event timer, and the mapping parameter record lists the dictionary entries packed into the frame, each as a 32-bit value holding the index, the subindex and the length in bits [1]. The mapping index is the communication parameter index plus 200h, so receive parameters at 1400h upwards pair with mappings at 1600h upwards, and transmit parameters at 1800h upwards with mappings at 1A00h upwards [1]. Mapping works bit by bit, so a status flag and a 16-bit measurement share a byte without waste, and a device that refuses a write to the count at subindex 00h simply has a fixed mapping [1][2].
The transmission type byte decides when the frame goes out, as listed in Table 2. Values 0 to 240 tie the PDO to the synchronisation object, and values 254 and 255 make it purely asynchronous, the difference being whether the triggering event is defined by the manufacturer or by the device profile [1].
| Value | Trigger | Character |
| 0 | next SYNC after an internal event | synchronous, acyclic |
| 1 to 240 | every n-th SYNC | synchronous, cyclic |
| 241 to 251 | reserved | reserved |
| 252 | data sampled at SYNC, sent on remote frame | synchronous, remotely requested |
| 253 | data sampled and sent on remote frame | asynchronous, remotely requested |
| 254 | manufacturer specific event | asynchronous |
| 255 | device profile specific event | asynchronous |
Two timers shape the asynchronous cases in Table 2. The inhibit time sets a minimum gap between transmissions in units of 100 microseconds, and the event timer sets a maximum gap in milliseconds so the PDO repeats even when nothing changed [1]. Together they give a change-of-state signal a bounded worst-case bandwidth and a bounded worst-case staleness, and the repetition lets a node that joined late learn the current value without asking [2]. The remaining trigger, the remote frame, is best avoided because handling differs between CAN controller families [2][4].
Synchronisation and fault signalling
The synchronisation object is a periodic broadcast with no data content and the highest priority in the default identifier layout. The interval between two SYNC messages is the communication cycle period at 1006h, and the window reserved after each SYNC for synchronous traffic is the synchronous window length at 1007h [1]. On reception of a SYNC every node producing synchronous PDOs puts its data on the bus, so all measurements refer to the same instant, and commands received during one cycle take effect at the next so that several axes start together [1]. SYNC carries a small jitter, because a frame in progress when the cycle expires cannot be interrupted [1].
The emergency object reports internal faults in eight bytes. The first two hold the error code, whose upper byte gives the error class from the communication profile and whose lower byte refines it in the device profile. The third copies the error register at 1001h, and the remaining five are manufacturer specific [1]. Emergencies are sent once per detected error so a failing node cannot flood the bus, and when every fault has cleared the node sends a final emergency with code 0000h [1].
Network management and supervision
Network management follows a master and slave model, with exactly one node driving the state of the others [1]. Each node runs the state machine summarised in Table 3. After power-on it initialises, enters pre-operational automatically and announces the transition with a boot-up message. In pre-operational, SDO communication works and process data communication does not, which is what makes the state useful for configuration [1][4]. Transitions are commanded on identifier 000h with a command byte and a target node ID, where zero addresses every node at once and is therefore never a valid device address [1].
| State | Entered by | SDO | PDO | SYNC | Emergency | Error control |
| Initialisation | power-on or reset | no | no | no | no | no |
| Pre-operational | automatic after init | yes | no | yes | yes | yes |
| Operational | start remote node | yes | yes | yes | yes | yes |
| Stopped | stop remote node | no | no | no | no | yes |
Supervision comes in two forms. Node guarding is a polling scheme in which the master sends a remote frame to each node and the node answers with its state plus a bit that has to toggle on every reply, and its mirror image, life guarding, lets the node detect that its master has stopped polling after the guard time at 100Ch multiplied by the life time factor at 100Dh [1].
Heartbeat is the alternative and the recommended one. The producer sends its state periodically without being asked, using the producer time at 1017h, and consumers monitor it through an array entry at 1016h holding the monitored node ID and the expected interval [1][2]. It removes the polling load from the master and lets nodes monitor each other directly, which matters in change-of-state systems where a node may legitimately stay silent for a long time [2]. The consumer time has to exceed the producer time, otherwise ordinary jitter gets reported as a loss. Both mechanisms share the identifier 700h plus the node ID, so they cannot run together, and heartbeat takes precedence [1].
Identifier assignment
The pre-defined connection set removes identifier planning from small systems [1][2]. An 11-bit identifier is split into a 4-bit function code and the 7-bit node ID.
The function code fixes the priority class and the node ID separates devices within it. Because the function code sits in the high bits, every message of a higher class outranks every message of a lower class regardless of node ID [1]. Table 4 lists the resulting allocation, covering four PDOs per direction, one SDO connection, the emergency object and the error control message per node. Only the first four PDOs of each direction get a default identifier, and the 7-bit node ID field is why a network is limited to 127 nodes [1][3].
| Communication object | Function code | Identifier |
| NMT module control | 0000b | 000h, broadcast |
| SYNC | 0001b | 080h, broadcast |
| Emergency | 0001b | 080h + node ID |
| Time stamp | 0010b | 100h, broadcast |
| Transmit PDO 1 to 4 | 0011b, 0101b, 0111b, 1001b | 180h, 280h, 380h, 480h + node ID |
| Receive PDO 1 to 4 | 0100b, 0110b, 1000b, 1010b | 200h, 300h, 400h, 500h + node ID |
| SDO server to client | 1011b | 580h + node ID |
| SDO client to server | 1100b | 600h + node ID |
| NMT error control | 1110b | 700h + node ID |
Larger systems reassign identifiers with a configuration tool, keeping SYNC and emergency at the top and leaving SDOs at the bottom because configuration traffic tolerates delay, though the SDO and error control ranges of Table 4 may not be reused [1][2]. Devices without switches get their address through layer setting services, where a tool identifies an unconfigured device by the vendor ID, product code, revision and serial number printed on its label [2][3].
Figure 4 collects the objects of Table 4 from the other side, showing for each one the default identifier and the layout of the eight data bytes that follow it.
Bit rate, bus length and bandwidth
Bit rate and bus length trade against each other, because arbitration requires a signal to propagate to the far end of the bus and back within one bit time [1][3]. Table 5 lists the recommended combinations together with the time a worst-case eight-byte frame occupies at each rate [2][3].
| Bit rate | Maximum bus length | Bit time | Worst-case 8-byte frame |
| 1 Mbit/s | 25 m | 1 µs | 135 µs |
| 800 kbit/s | 50 m | 1.25 µs | 169 µs |
| 500 kbit/s | 100 m | 2 µs | 270 µs |
| 250 kbit/s | 250 m | 4 µs | 540 µs |
| 125 kbit/s | 500 m | 8 µs | 1.08 ms |
| 50 kbit/s | 1 km | 20 µs | 2.70 ms |
| 20 kbit/s | 2.5 km | 50 µs | 6.75 ms |
| 10 kbit/s | 5 km | 100 µs | 13.5 ms |
The frame times in Table 5 follow from the frame format. A base frame carries 44 bits of overhead around the data field plus a three-bit intermission, so a frame with n data bytes occupies at least Nmin(n) = 47 + 8n bit times [1]. Bit stuffing adds at worst ⌊(34 + 8n − 1)/4⌋ more, so a full eight-byte frame takes between 111 and 135 [2]. Bus load then follows, where Ni is the length of the i-th periodic message, Ti its period and fbit the bit rate.
Using the worst-case length gives the pessimistic load, which is the number worth designing against. Bus load is only part of the latency budget, which also contains input detection, the wait for the frame in progress, arbitration delay and receive processing. A full input-to-output cycle at 1 Mbit/s takes roughly half a millisecond at high priority and two to three at lower rates, and a stack that applies outputs in a background task adds an unbounded amount to that [2].
Profiles and frameworks
The communication profile defines how devices talk. Device profiles define what they say, by assigning meaning to the entries from 6000h upwards for one class of device and fixing default PDO mappings so that a device is usable out of the box [1][2]. Frameworks sit alongside the communication profile and extend what appears on the bus, while profiles sit above it [2]. Table 6 lists the most widely used documents, and a product may combine several, as the drive below does [4].
| Document | Type | Scope |
| CiA 301 | communication profile | object dictionary, SDO, PDO, SYNC, EMCY, NMT |
| CiA 302 | framework | managers and programmable devices |
| CiA 303-3 | recommendation | indicator LED behaviour |
| CiA 305 | framework | layer setting services |
| CiA 401 | device profile | generic I/O modules |
| CiA 402 | device profile | drives and motion control |
| CiA 406 | device profile | encoders |
| CiA 1301 | communication profile | CANopen FD |
Interoperability is verified by a conformance test that exercises the mandatory behaviour of a node and checks that it implements every entry its electronic data sheet claims [2]. CANopen FD, the last row of Table 6, carries the same object dictionary model onto CAN FD frames, raising the expedited transfer limit from 4 to 48 bytes [5].
Examples
A stepper drive that implements CiA 402
The PD42-1270 is an integrated stepper unit combining a motion controller and driver stage with a NEMA 17 motor, running firmware that implements the communication profile and the drives and motion control profile [4]. It illustrates what a device profile buys, because almost nothing about controlling it is specific to the product. The communication side is deliberately modest. The drive is an NMT slave supporting bit rates from 20 kbit/s to 1 Mbit/s, with one SDO server offering expedited and segmented transfer, heartbeat production and consumption, SYNC consumption, emergency production, and four receive and four transmit PDOs with dynamic mapping of up to three entries each [4].
The default mappings in Table 7 are pure profile. Every receive PDO starts with the control word at 6040h and every transmit PDO starts with the status word at 6041h, so command and feedback are always present regardless of which PDO an integrator chooses to use [4].
| PDO | Mapping index | First object | Second object |
| RPDO 1 | 1600h | 6040h control word, 16 bit | none |
| RPDO 2 | 1601h | 6040h control word, 16 bit | 6060h modes of operation, 8 bit |
| RPDO 3 | 1602h | 6040h control word, 16 bit | 607Ah target position, 32 bit |
| RPDO 4 | 1603h | 6040h control word, 16 bit | 60FFh target velocity, 32 bit |
| TPDO 1 | 1A00h | 6041h status word, 16 bit | none |
| TPDO 2 | 1A01h | 6041h status word, 16 bit | 6061h modes of operation display, 8 bit |
| TPDO 3 | 1A02h | 6041h status word, 16 bit | 6064h position actual value, 32 bit |
| TPDO 4 | 1A03h | 6041h status word, 16 bit | 606Ch velocity actual value, 32 bit |
The drive runs two independent state machines, one from the communication profile governing whether the device may communicate at all and one from the motion profile governing whether current reaches the motor. They are separate, with one deliberate coupling. Stopping the node through network management forces any axis in the operation-enabled state into the fault state [4]. That is a sound interlock, because a node that may no longer receive commands must not keep driving a load.
Bringing an axis into motion is a sequence of writes. Profile position mode is selected by writing 1 to object 6060h, the control word at 6040h is stepped through 6, 7 and 15 to reach operation enabled with the power stage active, the target position goes to object 607Ah, and writing 31 starts the motion [4]. Each value is a command defined by the profile rather than an arbitrary number, so the sequence is identical for every compliant drive. Writing 15 again afterwards is the step engineers most often miss, because the new setpoint bit is edge triggered and has to return to zero before the next command is accepted [4]. Mapping the control word into a receive PDO, as Table 7 does for RPDO 3, turns the handshake into two frames instead of two SDO exchanges.
Fault reporting uses the standard emergency object with profile-defined codes, covering open load as 1000h, over-current as 2310h to 2312h, over-temperature as 4310h, a following error as 8611h, and communication problems as the 81xx group [4]. Bit rate and node ID live in manufacturer specific entries at 2704h and 2705h, and a change takes effect only after a save signature is written and the module is reset [4]. Two LEDs report the result, a green one blinking in pre-operational and staying on in operational, and a red one flashing at the error warning limit and staying on when the controller is bus off [4]. Those semantics come from the LED recommendation in Table 6 and are identical across compliant products, which makes first commissioning possible without a bus analyser.
A protocol stack inside a vendor SDK
The second example is a CANopen and CANopen FD library distributed inside a microcontroller vendor SDK [5]. It implements a device node with a configurable object dictionary, boot-up and heartbeat production, emergency production, an SDO or USDO server, and four receive and four transmit PDOs. A manager variant adds monitoring of boot-ups, heartbeats and states for the connected nodes, an SDO client for reading and writing remote dictionaries, emergency consumption and sixteen PDOs per direction [5]. Node guarding is not implemented at all, on the grounds that heartbeat is the recommended mechanism, which matches the precedence rule in the communication profile [5].
The central design idea is the process image. All process data lives in one byte array, and every variable is addressed by an offset and a length rather than by a pointer. The stack writes received PDO data into the image and reads transmit data out of it, while the application uses the same image through read and write macros, with offsets generated from an electronic data sheet editor [5]. That one choice solves several problems at once. Byte order is fixed to least significant byte first, matching the CANopen encoding rules. Mapped data is stored as a contiguous block, so building a PDO is a copy rather than a gather operation. And because every access goes through the same two macros, adding a mutex for an RTOS build means editing two definitions instead of auditing the whole codebase [5].
The division of labour beyond that generalises well. The stack owns the object dictionary, the SDO service, heartbeat and emergency production, while the application owns node ID and bit rate selection, the indicator LEDs, the non-volatile memory driver and the reaction to a heartbeat loss [5]. Several emergency codes are raised by the stack itself, including 8200h for an uninterpretable NMT command, 8210h for a receive PDO whose length does not match the mapping, and 8130h for a lost heartbeat [5]. Those three cover the most common integration mistakes and make them visible on the bus instead of leaving them as silent misbehaviour.
An isolated physical layer for a controller module
The third example is a reference design for an isolated CANopen interface aimed at programmable logic controllers and communication modules, built as an expansion board for a single-board Linux computer [6]. It divides a CAN node into a processor running the driver, stack and application, a CAN controller inside that processor handling frames, and a separate transceiver that converts to the differential bus and carries the isolation barrier protecting the controller from interference and destructive voltages [6]. Placing the barrier at the transceiver rather than in the digital domain lets the rest of the node be designed as ordinary low-voltage electronics.
Three components define the interface. The isolated transceiver is ISO 11898-2 compliant, provides 2500 V RMS of isolation, has a typical loop delay of 150 ns and implements a dominant timeout on its transmit input. A push-pull transformer driver generates the isolated supply for the bus side, and a protection array absorbs discharge to IEC 61000-4-2 level 4 while adding at most 15 pF per line [6]. Two of those numbers have protocol consequences. Loop delay and line capacitance both add to the round-trip time arbitration depends on, so they consume part of the bus length budget in Table 5 and are one reason a real installation does not reach the tabulated maximum [6]. The dominant timeout is a safeguard, because a microcontroller that hangs with its transmit line asserted would otherwise hold the bus dominant and silence every other node [6].
The board also carries the elements a commissioning technician touches. Termination of 120 ohm is fitted through a jumper, because it belongs at the two physical ends of the line and nowhere else [3][6]. Two rotary switches select bit rate and node address, and three LEDs report bus errors, run state and traffic, all handled by the application rather than by the stack [5][6]. Bring-up uses the Linux SocketCAN utilities for raw frame traffic and an open source CANopen stack for protocol testing, with two identical boards forming a two-node network [6]. That method is worth copying, because separating raw CAN bring-up from CANopen bring-up means a bit timing problem never gets mistaken for a protocol problem.
Summary
CANopen takes a bus that only knows how to deliver prioritised eight-byte messages and turns it into a network of devices that describe themselves, configure themselves and supervise each other.
The most important points are these. The object dictionary is the device, because every parameter, process value and communication setting is an entry addressed by index and subindex [1][2]. Configuration and process traffic use different mechanisms on purpose, since service data objects address the dictionary at the cost of overhead while process data objects carry nothing but payload [1][2]. Triggering decides bandwidth, and transmission type, inhibit time and event timer together bound both the load and the staleness of a signal [1]. Heartbeat is the supervision mechanism to choose in new designs, and the pre-defined connection set derives every default identifier from the node ID, which makes a small network work with no identifier planning [1][2]. Device profiles are where interoperability comes from, as the drive shows with a start-up sequence identical for every compliant product [4]. Latency, finally, is a system property rather than a bus property, and the software at both ends contributes more to it than the bit rate does [2][5][6].
Bit rates and bus lengths quoted above are recommended combinations rather than hard limits. Real reach depends on the cable, the transceiver loop delay and the electrical environment, and the normative definitions live in CiA 301 and the related CAN physical layer standards [1][2][6].
References
[1] Mohammad Farsi and Manuel Bernardo Martins Barbosa, CANopen Implementation: Applications to Industrial Networks, Research Studies Press Ltd., 2000.
[2] Olaf Pfeiffer, Andrew Ayre and Christian Keydel, Embedded Networking with CAN and CANopen, Revised First Edition, Copperhill Technologies Corporation, 2008.
[3] Manfred Schleicher, Digitale Schnittstellen und Bussysteme, FAS 603, JUMO GmbH & Co. KG, Fulda, June 2008.
[4] TRINAMIC Motion Control GmbH & Co. KG, PD42-1270 CANopen Firmware Manual, Firmware Version V3.26, Document Revision V1.06, 19 October 2021.
[5] Embedded Systems Academy, EmSA CANopen (FD) Libraries for NXP SDKs User Manual, based on Micro CANopen Plus Version 7.00, 27 September 2019.
[6] Texas Instruments, TIDA-01406: Energy Efficient and Isolated CANopen Interface for PLC and Communication Modules, TIDUCW3A, March 2017, revised July 2017.
Leave a Reply