Complete guide: Choosing an industrial controller
To test CAN bus on a Raspberry PLC, connect CAN H to CAN H and CAN L to CAN L between two PLCs, bring up the can0 interface at the same bitrate on both, run candump can0 on one PLC and cansend can0 111#FF on the other. If the first PLC prints can0 111 [1] FF, the CAN controller, the wiring and the bitrate are correct.
This test was made with two Raspberry PLC v3, where the CAN controller is an MCP2515 on the SPI bus of the Raspberry Pi. In the current Raspberry PLC family, CAN is an expansion board with the same controller: MCP2515, CAN 2.0B, up to 1 Mbit/s. The test with can-utils is the same. Only the overlay settings change with the hardware version.
What is CAN bus?
CAN (Controller Area Network) is a serial bus where every node sends short frames with an identifier, and every node receives all frames. It was designed for wiring inside vehicles, and it is now used in machines, mobile equipment and industrial devices. When two nodes transmit at the same time, the frame with the lowest identifier wins the bus and the other node retries, so no data is lost in a collision.
| Feature | Classic CAN (CAN 2.0) |
|---|---|
| Identifier | 11 bits (standard, CAN 2.0A) or 29 bits (extended, CAN 2.0B) |
| Data per frame | 0 to 8 bytes |
| Physical layer | Differential pair, CAN H and CAN L, usually twisted |
| Termination | 120 Ω at each end of the bus |
| Bitrate | Up to 1 Mbit/s. The bus gets shorter as the bitrate goes up |
| Error handling | CRC and acknowledge bit in every frame; a node with too many errors goes to bus off |
On Linux, the CAN controller appears as a network interface (can0) through SocketCAN, so you configure it with ip and test it with the can-utils tools.
What you need
- Two Raspberry PLC with CAN: a v3, or a current model with the CAN expansion board.
- A 12 to 24 Vdc power supply for each PLC.
- A twisted pair cable for CAN H and CAN L.
- Two 120 Ω resistors, one at each end of the bus, if your boards do not have them.
Check the CAN interface on each PLC
- Use the Raspberry PLC image, or build it with the configuration files as explained in how to build a Raspberry PLC image from Raspberry Pi OS.
- Check that SPI is enabled. The MCP2515 talks to the Raspberry Pi through SPI.
- Check that the configuration file has the overlay of the CAN controller. On the Raspberry PLC v3 it is this line, with the 20 MHz crystal and the interrupt on GPIO 5 of that board:
The file isdtoverlay=mcp2515-can0,interrupt=5,oscillator=20000000/boot/firmware/config.txton Raspberry Pi OS Bookworm and/boot/config.txton older images. On a CAN expansion board, use the oscillator and interrupt values of its user guide, not the v3 values. - After a reboot, check that the driver found the controller. The mcp251x driver writes a line when it initializes the MCP2515:
dmesg | grep -i mcp251 - Bring up the interface and check its state:
The interface must be UP and the CAN state ERROR-ACTIVE. Use the same bitrate on both PLCs.sudo ip link set can0 up type can bitrate 500000 restart-ms 100 ip -details -statistics link show can0 - The v3 image also brings up
can0at boot with the file/etc/network/interfaces.d/can0. Its content is:
This file needs ifupdown and ifconfig (net-tools). If your image does not use them, bring up the interface with theauto can0 iface can0 inet manual pre-up /sbin/ip link set can0 type can bitrate 500000 triple-sampling on restart-ms 100 up /sbin/ifconfig can0 up down /sbin/ifconfig can0 downipcommand of the previous step. - Install can-utils, which gives the
candump,cansendandcangencommands:sudo apt update sudo apt install can-utils
Wire the CAN bus between two PLCs
Connect CAN H of the first PLC to CAN H of the second one, and CAN L to CAN L. Use a twisted pair. If the PLCs do not share the power supply, also connect a common ground reference.

The bus needs a 120 Ω resistor at each end, also with only two nodes. With the power off, you should measure about 60 Ω between CAN H and CAN L. Check in the user guide of your PLC if the board already has a termination resistor.
Send and receive a CAN frame
1. Listen on the first PLC. Open a terminal and start candump. It prints every frame that reaches can0.
candump can0

2. Send a frame from the second PLC. 111#FF means identifier 0x111 (hexadecimal, 11 bits) and one data byte, 0xFF.
cansend can0 111#FF

3. Read the result on the first PLC. candump shows the interface, the identifier, the number of data bytes in brackets and the data:
can0 111 [1] FF
![Terminal of the first Raspberry PLC: candump can0 receives the frame can0 111 [1] FF](/web/image/759618/canbus-raspberry-plc-candump.webp)
More frames to test the bus:
cansend can0 123#DEADBEEF # standard ID 0x123, 4 data bytes
cansend can0 18FF1234#0102030405 # extended 29-bit ID, 5 data bytes
candump -ta can0 # received frames with absolute time
cangen can0 -g 100 # one random frame every 100 ms
If the frame does not arrive
| Symptom | Usual cause | What to check |
|---|---|---|
can0 does not exist | No overlay, SPI off, or wrong oscillator or interrupt values | The overlay line, SPI, and dmesg | grep -i mcp251 |
can0 is DOWN | The interface was not brought up | sudo ip link set can0 up type can bitrate 500000 |
| cansend says "No buffer space available" | No other node acknowledges the frames, so the transmit queue fills up | The other PLC is on, same bitrate, CAN H and CAN L not swapped, termination |
| State ERROR-PASSIVE or BUS-OFF | Too many errors on the bus | Bitrate, termination, wiring. With restart-ms the controller recovers from bus off by itself |
| Frames arrive with errors in the statistics | Noise or a long stub | Twisted pair, short branches, one termination at each end only |
From a test frame to a CAN application
A frame from the terminal proves the hardware. A real device usually speaks a higher layer protocol on top of CAN, such as CANopen in industrial drives and sensors, or SAE J1939 in vehicles and mobile machines. In a program, you use the same can0 interface from Python with the python-can library, or from C with SocketCAN sockets.
See CANopen on a Raspberry PLC. Two worked examples from the PLC Solution Library read a CANopen encoder and inclinometer on a solar tracker, and control a LOVATO VLB3 drive over CANopen.
FAQ about CAN bus on a Raspberry PLC
Does the Raspberry PLC have CAN bus?
The Raspberry PLC v3 has an MCP2515 CAN controller. In the current family, CAN is an expansion board with the MCP2515 controller, CAN 2.0B, up to 1 Mbit/s. Ask for it when you order the PLC.
Which bitrate should I use?
The one of the other devices on the bus: all nodes must use the same. 500 kbit/s and 250 kbit/s are common. Lower bitrates allow longer cables.
Do I need termination resistors with only two PLCs?
Yes. The bus needs 120 Ω at each end, whatever the number of nodes. Without termination, frames can fail even on a short cable.
Does the MCP2515 support CAN FD?
No. The MCP2515 is a CAN 2.0B controller: classic frames with up to 8 data bytes.
Why does cansend fail with "No buffer space available"?
Because no other node acknowledges the frames. Check that the second PLC is on and listening at the same bitrate, and check the wiring and the termination.
More about the Raspberry PLC
- How to build a Raspberry PLC image from a Raspberry Pi OS
- Modbus TCP and RTU guide for Raspberry Pi PLCs
- How to program the interrupt inputs of the Raspberry PLC with Python
- How to connect a Raspberry PLC to Wi-Fi
- Choosing an industrial controller
Choose the model and the I/O mix in the Raspberry PLC family.