CANopen is the higher-layer protocol that turns a CAN bus into a network of devices. CAN itself only moves short frames with an identifier; CANopen, published by CAN in Automation (CiA) as CiA 301 and standardized as EN 50325-4, says what those frames mean. Every device has an object dictionary, a table of objects addressed by a 16-bit index and an 8-bit sub-index that holds its identity, its communication settings and its application data. SDO reads and writes that dictionary one object at a time, PDOs carry process data in single frames without protocol overhead, and NMT starts, stops and resets nodes, which report their state with heartbeats. EDS files describe a device’s dictionary so that tools can configure it without its manual.
Where you meet it
- Industrial machines, packaging and printing lines, where drives, I/O modules, encoders and valves sit on one CANopen network
- Servo and stepper drives that follow the CiA 402 profile, the same drive model that EtherCAT’s CoE uses
- Lifts and escalators (CiA 417), medical devices, laboratory automation and rail vehicles
- Mobile machines, forklifts, AGVs and light electric vehicles, with battery packs, chargers and motor controllers
- Embedded products that need a well-defined device model on a CAN bus they already have
Quickstart
From the command line
Download canopenctl from GitHub Releases, or go install github.com/otfabric/canopenctl@latest. A Linux virtual CAN interface and a simulated device are enough to try it without hardware:
# A virtual CAN interface (Linux) and a simulated CANopen device, node 5sudo ip link add vcan0 type vcan && sudo ip link set vcan0 upcanopenctl simulate -i vcan0 --node-id 5 &
# Decode live traffic, passivelycanopenctl monitor -i vcan0
# Find nodes 1 to 127 with their device type and identitycanopenctl scan -i vcan0
# Read the vendor-ID of node 5, or every readable object decoded with its EDScanopenctl sdo read 5 0x1018 1 -i vcan0canopenctl sdo dump 5 --eds device.eds -i vcan0 --format table
# Start every node, then watch heartbeats and emergencies (a real bus needs --yes)canopenctl nmt start all -i vcan0canopenctl heartbeat watch -i vcan0 --supervise 1500ms
# Give unconfigured devices node-IDs with LSS, then boot the network as a CiA 302 managercanopenctl lss assign-all --first 10 --store -i can0 --yescanopenctl boot --slave 5=node5.dcf --slave 6 -i can0 --yescanopenctl is read-only by default: monitor, decode and the watch commands never transmit, scan, sdo read and sdo dump send only read requests, and every command that changes a device or the network needs --yes on an interface that is not virtual.
From Go
go get github.com/otfabric/go-canopenA device and a network manager on two ports of a virtual bus, from the go-canopen README. On a real network, open the bus with go-canbus (socketcan.Open("can0"), or an slcan adapter) and the CANopen code does not change:
vb := virtual.New(virtual.Config{Name: "quickstart"})p1, _ := vb.Open()p2, _ := vb.Open()deviceBus, _ := canbus.NewBus(p1)masterBus, _ := canbus.NewBus(p2)
// The device: the CiA 301 communication objects and a node-ID.d, _ := od.Standard(od.Config{NodeID: 5, DeviceType: 0x000F0191, VendorID: 0xF7A, DeviceName: "quickstart", HeartbeatMs: 100})dev, _ := node.New(deviceBus, d)
// The network manager.m, _ := master.New(masterBus)_ = m.Start()defer m.Close()
since := time.Now()_ = dev.Start() // boot-up message, pre-operationaldefer dev.Close()_ = m.WaitBootUp(ctx, 5, since)
c, _ := m.SDO(5)devType, _ := c.ReadUint(ctx, od.IndexDeviceType, 0)name, _ := c.ReadString(ctx, od.IndexDeviceName, 0)fmt.Printf("node 5: device type 0x%08X, %q\n", devType, name)
_ = m.StartNode(ctx, 5)_ = m.WaitState(ctx, 5, canopen.StateOperational)What go-canopen and canopenctl support
| CiA 301 | Object dictionary with access rights, limits and hooks; SDO client and server with expedited, segmented and block transfer; PDOs with every transmission type, inhibit time, event timer, RTR and deadline monitoring; MPDOs (DAM and SAM); NMT master and slave; heartbeat, node guarding and life guarding; SYNC with the synchronous window; EMCY; TIME; store and restore |
| Devices and managers | A complete device built from a dictionary and gated by its NMT state; a network manager with scan, boot procedure, DCF configuration, remote PDOs and one ordered event stream |
| CiA 302 | Network boot-up with error status letters and an optional LSS step, the configuration manager with concise DCFs, program download; no flying master and no SDO manager |
| LSS (CiA 305) | Master and slave: switch, configure node-ID and bit timing, store, inquire, identify, Fastscan and automatic assignment of every unconfigured device |
| CANopen FD (CiA 1301) | USDO, PDOs up to 64 bytes, the 20-byte emergency; built from public sources and not interop tested, because no open stack implements it yet |
| Files | EDS and DCF (CiA 306) read, validate and write; concise DCF; typed Go generated from an EDS |
| CiA 402 | The drive state machine and modes PP, PV, PT, HM, CSP, CSV and CST, as a simulated drive and as a controller |
| Traffic | A dissector for every service, checked against Wireshark’s; canopenctl decodes candump, pcap and pcapng, BLF, ASC, TRC and JSON Lines traces |
| Platforms | Linux (amd64, arm64, armv7) for SocketCAN; slcan adapters and the virtual bus also on macOS and Windows. No cgo |