Skip to content
ISO 11898-1 (classical CAN, CAN FD, CAN XL in the 2024 edition), ISO 15765-2 (ISO-TP); Bosch CAN 2.0 and CAN FD 1.0

CAN bus

The two-wire bus of vehicles, machines, batteries and chargers, and the transport that CANopen, SAE J1939 and UDS run on: short frames with an identifier that names the message and sets its priority, CAN FD for longer and faster frames, CAN XL for up to 2048 bytes, and ISO-TP for messages above one frame.

Layer
Physical and data link, plus ISO-TP transport; the protocols on top define the messages
Medium
Two-wire differential bus, 120 Ω at each end; Linux SocketCAN, USB serial-line (slcan) adapters
Frames
Classical CAN (8 bytes), CAN FD (64 bytes), CAN XL (2048 bytes); 11- or 29-bit identifiers
Library
go-canbus
CLI
canbusctl
Interop
canbus-interop v0.5.0

CAN (Controller Area Network) is the bus that Bosch designed for cars in the 1980s and that now runs far beyond them: in trucks, tractors and construction machines, in robots, lifts and medical devices, inside battery packs, inverters, EV chargers and heat pumps. All nodes share one twisted pair. Any node can send, and a frame carries no address: its identifier names the message, and because the lower identifier wins arbitration bit by bit, it also sets the priority. Classical CAN carries 8 bytes per frame, CAN FD up to 64 bytes with a faster data phase, and CAN XL, in the 2024 edition of ISO 11898-1, up to 2048 bytes. ISO-TP segments longer messages, and a DBC file says which bits of which frame hold which signal.

CAN stops there. It defines how frames get onto the wire and to every node, not what a device is or how a network is managed, so it is a transport: the protocols on top give the frames their meaning. In machines and automation that is CANopen, with its object dictionary, SDO, PDOs and network management; in trucks and mobile machines SAE J1939; in diagnostics UDS over ISO-TP. OT Fabric builds them in layers too: go-canbus is the CAN transport, and go-canopen runs on it.

Where you meet it

  • Battery management systems, inverters, DC/DC converters and EV chargers, where CAN connects the cells, the power electronics and the controller
  • Vehicles and mobile machines: cars, trucks, buses, tractors, construction and mining equipment, forklifts and AGVs, often with SAE J1939 or CANopen on top
  • Industrial machines, robots, drives and sensors, lifts and medical equipment, most of them with CANopen on top
  • Test benches, data loggers and diagnostics, where engineers record traces, decode them with a DBC file and replay them

Quickstart

From the command line

Download canbusctl from GitHub Releases, or go install github.com/otfabric/canbusctl@latest. Without hardware, a Linux virtual CAN interface is enough to try it:

Terminal window
# A CAN FD capable virtual interface (Linux)
sudo ip link add vcan0 type vcan && sudo ip link set vcan0 mtu 72 up
# Watch an interface and decode with a DBC file, passively
canbusctl monitor -i can0 --dbc vehicle.dbc
# Send a frame on vcan (a real bus needs --yes)
canbusctl send -i vcan0 123#DEADBEEF
# Record a trip, then convert or replay it
canbusctl record -i can0 -o trip.blf --duration 10m
canbusctl trace convert trip.blf trip.asc
canbusctl replay trip.blf -i vcan0 --speed 2
# A CANable or other serial-line adapter, on any OS, listen-only
canbusctl monitor -i slcan:/dev/ttyACM0 --slcan-bitrate 250000
# Encode a message from a database, or generate typed Go from it
canbusctl dbc encode vehicle.dbc Engine Speed=1500 Gear=Second
canbusctl dbc generate vehicle.dbc -o vehicle/vehicle.go

canbusctl is passive by default: monitor, record, stats and every dbc command never transmit, and every command that does needs --yes on an interface that is not virtual, with limits on rate, count and duration.

From Go

Terminal window
go get github.com/otfabric/go-canbus

Receive filtered frames from a SocketCAN interface and decode them with a DBC file (abridged from the go-canbus README):

main.go
conn, err := socketcan.Open("can0", socketcan.WithFD())
bus, _ := canbus.NewBus(conn, canbus.WithStartOnSubscribe())
defer bus.Close()
sub, _ := bus.Subscribe(canbus.WithFilters(canbus.FilterSet{
Filters: []canbus.Filter{canbus.ExactStandard(0x123)},
}))
db, _, err := dbc.ParseFile("vehicle.dbc")
for {
f, err := sub.Receive(ctx)
if err != nil {
return
}
_, signals, _ := db.DecodeFrame(&f)
for _, s := range signals {
fmt.Println(s.Signal.Name, s.Physical, s.Signal.Unit)
}
}

The same Bus runs on a serial-line adapter (slcan.Open) on Linux, macOS and Windows, or on the in-memory virtual bus in tests. ISO-TP runs on top of it with isotp.Dial, and so does go-canopen: every CANopen service takes a canbus.Bus.

What go-canbus and canbusctl support

Frames Classical CAN 2.0A and 2.0B, CAN FD with BRS and ESI, remote and error frames, CAN XL with priority, VCID, SDU type and acceptance field
Transports Linux SocketCAN with kernel filters, timestamps and drop accounting; serial-line (slcan, LAWICEL) adapters such as CANable, CANtact and USBtin on every OS; an in-memory virtual bus with seeded faults
Interface administration List and inspect interfaces, bit rates, CAN FD, restart, vcan and vxcan through rtnetlink, kept apart from opening a socket
ISO-TP Userspace and Linux kernel; normal, extended and mixed addressing, flow control, CAN FD, messages above 4095 bytes
Traces candump, JSON Lines, pcap and pcapng, Vector ASC and BLF, PEAK TRC; replay with original or scaled timing
Databases DBC and KCD read and write, AUTOSAR 4 ARXML read; Intel and Motorola, signed, float, scaling, value tables, multiplexing, exact 64-bit raw values; typed Go code generation
Fault testing A seeded bridge that drops, duplicates, delays, reorders and corrupts frames between two interfaces
Platforms Linux (amd64, arm64, armv7) for SocketCAN; frames, slcan, the virtual bus, ISO-TP, traces and databases also on macOS and Windows. No cgo

OT Fabric projects for CAN bus

canbusctl

Monitor, record, convert and replay CAN, CAN FD and CAN XL traffic, decode and encode with DBC, KCD or ARXML, run ISO-TP, simulate a database and test under faults. Passive by default; transmitting on a real bus needs --yes.

go-canbus

The CAN transport for Go: classical CAN, CAN FD and CAN XL frames on Linux SocketCAN, serial-line (slcan) adapters on every OS and a virtual bus, with ISO-TP, capture and replay in seven trace formats, and DBC, KCD and ARXML databases with a signal codec and a Go code generator. go-canopen runs on it. No cgo.

go get github.com/otfabric/go-canbus

canbus-interop

Seven independent CAN references in containers behind one contract: can-utils with the kernel's ISO-TP, python-can, socketcan-rs, Scapy, python-can-isotp, cantools and canmatrix, on Linux virtual CAN.

go-canopen

CANopen (CiA 301) and CANopen FD on go-canbus: object dictionary, SDO and USDO, NMT, heartbeat, PDOs and MPDOs, SYNC, EMCY, TIME, LSS, a complete device and a CiA 302 network manager, EDS/DCF files, typed Go from an EDS and the CiA 402 drive profile. No cgo.

go get github.com/otfabric/go-canopen
  • CANopen
GitHub

canopenctl

Monitor and decode CANopen traffic, read and write object dictionaries over SDO or USDO, manage nodes with NMT, assign node-IDs with LSS, boot a network as a CiA 302 manager, configure PDOs and MPDOs, work with EDS, DCF and concise DCF files, drive CiA 402 axes and simulate devices. Read-only by default; changes on a real bus need --yes.

  • CANopen
GitHub

Who is behind CAN bus

The organizations that publish, test, certify or host open-source work for CAN bus. Listed for reference, not as partners. Compare membership and fees.