Recent Posts
Beginner’s Guide to Using SocketCAN with Raspberry Pi and PICAN Board
Posted by
onThis guide will walk you through the basics of using SocketCAN on a Raspberry Pi with a PICAN CAN Bus HAT. We will cover what SocketCAN is and how it works, then explain how to set up the hardware (attaching the PICAN board and wiring the CAN bus). Next, we’ll detail the software configuration on Raspberry Pi OS to enable the CAN interface, including device tree overlay setup and verifying that the CAN interface (
can0
) is working. Finally, we’ll demonstrate using Python (via the python-can
library) to send and receive CAN messages. This guide is written for beginners, with clear step-by-step instructions and code examples.
What is SocketCAN?
SocketCAN is a collection of CAN drivers and a networking stack integrated into the Linux kernel. It abstracts CAN bus interfaces as network devices, so they can be accessed using the standard Berkeley socket API similar to TCP/IP networking. In practice, this means a CAN interface (like one provided by the PICAN board) will appear as a network interface (e.g. can0
) on Linux. You can configure it with network tools (such as the ip
command) and read/write CAN frames using socket calls. This unified interface simplifies development, allowing developers to leverage existing networking concepts for CAN bus communication. SocketCAN supports standard CAN2.0A/B as well as CAN FD (Flexible Data Rate) frames, and works with higher-layer protocols (ISO-TP, CANopen, J1939, etc.) through additional software. It also has broad tool support: for example, you can use command-line utilities (candump
, cansend
from can-utils) or libraries like python-can to interact with CAN devices on SocketCAN.
Key benefits of SocketCAN include: a standardized programming interface (using AF_CAN
sockets in C or high-level libraries in Python), built-in kernel filtering of CAN IDs, and compatibility with debugging tools (such as Wireshark integration for CAN). All of this means you don’t need proprietary drivers or special APIs to work with CAN on Linux – if your hardware is supported by SocketCAN, it will “just show up” as a network interface.
About the PICAN Board
The PICAN board series (offered by Copperhill Technologies) is an add-on HAT that gives the Raspberry Pi CAN-bus capability. It contains a Microchip MCP2515 stand-alone CAN controller (connected via SPI) and a CAN transceiver (such as the MCP2551 or TJA1050) onboard. The board uses the Pi’s 40-pin GPIO header for power and SPI communication. It provides a standard DB9 connector and/or screw terminals for connecting to a physical CAN bus (the DB9 is often wired for OBD-II compatibility). The PICAN board adheres to the HAT form factor, meaning it fits right on top of the Pi and is powered by it. From the software perspective, the PICAN’s CAN controller is supported by the SocketCAN driver (MCP2515 driver in the Linux kernel), so when properly configured it appears as a network interface named can0
. Programming can then be done in high-level languages like C or Python using SocketCAN APIs.
Some key features of the PICAN board include support for CAN 2.0B at speeds up to 1 Mb/s, indicator LEDs, and an onboard 120 Ω termination resistor that can be enabled via jumpers if your CAN bus needs termination. The PICAN’s MCP2515 uses an external clock (usually a 16 MHz crystal) and an interrupt line to the Raspberry Pi (typically GPIO25) to signal received data. We will need these details when configuring the software.
Hardware Setup – Raspberry Pi and PICAN Board
Before working on software, set up the hardware. Power off your Raspberry Pi and disconnect it from any power source before attaching the PICAN board. Carefully align the PICAN board’s 40-pin connector with the Raspberry Pi’s GPIO header, and press the board down until it seats firmly on the header pins. You may use standoffs or spacer screws in the mounting holes to secure the board, which helps maintain a good connection. The PICAN board should cover the Pi’s GPIO header completely; ensure no pins are misaligned or bent during insertion.
Next, connect the PICAN to your CAN bus or test setup. If you are connecting to an existing CAN network or another node: use the DB9 port or the screw terminals on the PICAN. The DB9 pinout by default typically follows the OBD-II CAN standard (CAN_H and CAN_L on specific pins, as documented in the PICAN user guide), but the board may allow reconfiguration via solder bridges for different pinouts. If using the screw terminal, wire the CAN High (CAN_H) and CAN Low (CAN_L) lines of your bus to the corresponding terminals on the PICAN, and a ground reference if required (common ground between nodes).
Termination: In a CAN bus network, the two endpoints of the bus must have 120 Ω terminators. The PICAN board has an optional 120 Ω termination resistor on board. By default it might be unconnected; you can enable it by placing a jumper on the provided header or soldering the bridge (refer to the PICAN manual for specifics). If your Raspberry Pi with PICAN is at one end of the CAN network, enable this terminator. If it’s in the middle of an existing network (or if you are just doing a point-to-point test with two devices), make sure exactly two terminators are present in total. For initial testing with just a single PICAN and no other CAN device, you can use the loopback mode (explained later) instead of a physical second node.
Once the PICAN HAT is attached and any necessary wiring is done, you can power on the Raspberry Pi to proceed with software configuration.
Raspberry Pi OS Configuration for CAN Interface
The Raspberry Pi’s Linux kernel includes the driver for the MCP2515 CAN controller, but it is not enabled by default. We need to enable the SPI bus (which the MCP2515 uses) and tell the system that an MCP2515 is attached with certain parameters (SPI channel, oscillator frequency, interrupt). This is done through a Device Tree Overlay.
1. Enable SPI on the Raspberry Pi: The MCP2515 communicates via SPI, which is disabled on Raspberry Pi OS by default for the main SPI0 interface. There are two ways to enable it:
-
Using Raspberry Pi Configuration / raspi-config: If you have a desktop environment, you can open Raspberry Pi Configuration, go to the Interfaces tab, and enable SPI. On the command-line, you can do the same by running
sudo raspi-config
, navigating to Interface Options, and enabling SPI. This will setdtparam=spi=on
in the Pi’s boot configuration. -
Or manually editing
/boot/config.txt
: Add the following line to the file/boot/config.txt
(with root permissions):This ensures the SPI master interface is enabled at boot.
2. Add the MCP2515 CAN overlay: Below the dtparam=spi=on
line (in the same /boot/config.txt
file), add a line to load the MCP2515 CAN controller overlay with the correct settings. For the PICAN board, use:
This overlay line tells the kernel that an MCP2515 is connected (as CAN interface 0) with a 16 MHz oscillator and that the MCP2515’s interrupt line is tied to GPIO25 (which is true for the PICAN hardware). The overlay will automatically handle binding the driver to SPI channel 0 (CE0 on SPI0 by default). Save the config.txt
changes and reboot the Raspberry Pi.
Note: Older documentation may mention adding dtoverlay=spi-bcm2835
or dtoverlay=spi-bcm2835-overlay
. This was used on legacy systems to select the newer SPI driver, but on current Raspberry Pi OS (kernels 4.4 and later) the bcm2835 SPI driver is the default, so you do not need to add that line. Simply enabling spi=on
and the mcp2515-can0
overlay is sufficient. The overlay itself will enable the SPI bus if it wasn’t already enabled, so the dtparam=spi=on
is essentially a safety/enabler for SPI generally.
After adding the overlay and rebooting, the kernel should probe the MCP2515 on boot. You can check that the overlay loaded correctly by inspecting the kernel log. For example, run:
In the boot messages you should see confirmation that the CAN controller was initialized. A successful log looks like: “mcp251x spi0.0 can0: MCP2515 successfully initialized.” If instead you see an error like “Cannot initialize MCP2515. Wrong wiring?”, double-check that the PICAN board is properly seated, powered, and that the overlay parameters match your hardware (especially the oscillator value and interrupt pin).
At this point, if everything is correct, the system should have created a CAN network interface named can0
(for a single-channel PICAN board). You can verify this by running ls /sys/class/net
or ip link show
. The can0
interface might be “down” by default (not active yet), which is normal.
Enabling and Verifying the CAN Interface
Now that the system knows about the CAN hardware, we need to bring up the can0
interface and test it. SocketCAN interfaces aren’t “up” (active) until you explicitly enable them, similar to how an Ethernet interface might be down until configured.
1. Set the bitrate and bring the interface up: Decide on the CAN bus bitrate you want to use. This must match any other devices you intend to communicate with. Common CAN speeds are 125000, 250000, 500000, or 1000000 bits per second (1 Mbps). The PICAN (MCP2515) supports up to 1 Mb/s bus speed. Use the ip
utility to bring up the interface. For example, to set 500 kbps:
This command configures can0
for 500,000 bits/s and puts it “up” (online). You can verify the interface status with:
It should show can0
with state UP and the configured bitrate. You can also use ifconfig can0
which should now show the interface with an MTU (typically 16) and no TX/RX errors (initially). At this point, the CAN controller is active and ready to send/receive frames on the bus.
2. (Optional) Enable loopback for testing: If you do not have a second CAN node to communicate with and want to test the interface by itself, you can enable loopback mode. Loopback causes the CAN controller/driver to echo transmitted frames back to itself (internal loopback) without putting them on the physical bus. To use loopback, bring the interface down and up with the loopback on
parameter:
Now any frame you send on can0
will be received by can0
as well (this is useful for self-test). If you have another device or a second Raspberry Pi + PICAN, you don’t need loopback – you can directly test communication between the two nodes.
3. Test CAN communication using can-utils: It’s often helpful to use the Linux CAN utilities to verify everything is working. Install the can-utils package if you haven’t already (e.g. sudo apt install can-utils
). Open two terminals on the Raspberry Pi (or use a multiplexer like tmux). In one terminal, run the command to listen for CAN frames:
This will print any CAN frames received on can0
. In another terminal, try sending a test CAN message using:
This sends a CAN frame with ID 0x001 and data bytes DE AD BE EF (in hex). If loopback mode is on (or if you have another node that responds or if you wired two PiCAN boards together), you should see the frame appear in the candump
output. For example, in loopback you would see the frame you sent, possibly twice (one for send echo and one as receive). This confirms that the SocketCAN layer is operating. If you don’t see any output, recheck the configuration or ensure that another node is present and transmitting.
Once basic sending/receiving is confirmed with can-utils, you know the kernel driver and hardware are set up correctly. You may want to configure the interface to come up automatically on boot with a given bitrate. This can be done by adding commands to your /etc/network/interfaces
(on older systems) or using a systemd network unit. For example, adding the following to /etc/network/interfaces
will bring up can0 on boot with 500k bitrate:
This ensures your CAN interface is ready whenever the Pi starts, which is useful for headless or embedded deployments.
Using Python for CAN Communication
With the CAN interface (can0
) enabled in SocketCAN, you can send and receive CAN messages using Python. We will use the python-can library, which provides a high-level API for CAN bus interfaces (and it supports SocketCAN as one of its backends). Make sure you have Python 3 installed on your Raspberry Pi (which is default on recent OS versions) and then install python-can:
This will install the library and its dependencies. (If running your Python code with root privileges is not ideal, you might also need to bring can0
up in user-space or adjust CAN socket permissions. For most simple uses, running with sudo
or making sure the interface is up beforehand is enough.)
Python-can basics: The python-can library uses a Bus object to represent a connection to a CAN interface, and a Message class to represent CAN frames. When using SocketCAN, no additional drivers are needed – python-can will interface with the kernel SocketCAN subsystem.
Below is an example Python script that sends a CAN message and then waits to receive one:
Let’s break down what this does. First, we instantiate a CAN Bus connecting to can0
using the SocketCAN interface. (The library will default to using the SocketCAN backend when you specify interface='socketcan'
and an existing channel like can0
.) Then we construct a Message
object with a specific CAN ID and some data. In this example, the ID is 0x123 and the data payload is 3 bytes: 0x11, 0x22, 0x33. We specify is_extended_id=False
because 0x123 is a standard 11-bit identifier (for a 29-bit extended ID, you’d set that True and use a larger ID value).
Using bus.send(msg)
, we transmit the CAN frame. The code catches can.CanError
in case the send fails (for example, if the transmit buffer is full or interface is down). On success, it prints a confirmation.
Next, bus.recv(timeout=1.0)
waits for a CAN frame to be received on the bus, up to 1 second. If a frame arrives, it returns a Message object; if the timeout passes with no frame, it returns None
. In our code, we then check and print the received message’s ID and data (converting data bytes to hex for display). The Message
object also has other attributes you can use, such as .dlc
(data length code) and .timestamp
. If you were doing continuous monitoring, you could omit the timeout or use a loop to continuously call bus.recv()
or even iterate over the bus (python-can supports iterating over bus
to yield incoming messages).
Important: For the above send/receive example to actually receive something, there needs to be a frame on the bus. If you are using loopback mode (as set earlier), then the message you send will be received by the same interface, and the script will print the message it sent. If loopback is off, then you will only receive a message if another device on the CAN bus sends something. In a real-world scenario, you might have another node (another PICAN on a second Pi, an Arduino with a CAN shield, etc.) sending responses or periodic messages. For testing, using the loopback can help simulate that within one device.
Python-can also supports more advanced usage: for example, you can set up listeners, filters to only receive certain CAN IDs, or even use the Bus as a context manager. But the simple example above is enough to demonstrate basic send and receive.
Conclusion
In this guide, we covered how to equip a Raspberry Pi with CAN bus functionality using the PICAN board and Linux’s SocketCAN system. You learned that SocketCAN integrates CAN into the Linux network stack, making CAN devices accessible as network interfaces and programmable via standard socket calls or convenient libraries. We went through the hardware setup of attaching the PICAN HAT to the Raspberry Pi and connecting to a CAN bus. We then configured the Raspberry Pi OS by enabling SPI and adding a device tree overlay for the MCP2515 CAN controller on the PICAN, using the correct oscillator frequency and interrupt pin. After reboot, the can0
interface was brought up with a chosen bitrate, and we verified communication using the can-utils
tools (like candump
and cansend
). Finally, using the python-can
library, we demonstrated sending and receiving CAN messages in Python, which is a powerful way to integrate CAN bus data into your own programs (for logging, control, or gateway applications).
With this setup, your Raspberry Pi can now participate in CAN bus networks – for example, reading data from automotive OBD-II, controlling industrial CAN nodes, or communicating between microcontrollers. The combination of PICAN hardware and SocketCAN software provides a relatively simple, open-source friendly platform for CAN development. As a next step, you might explore higher-layer CAN protocols (such as CANopen or J1939) depending on your project needs, or implement filters and handlers in Python for more complex CAN messaging tasks. Happy CAN hacking!
Want to learn programming but feel overwhelmed by complex languages or uninspiring tutorials? Whether you’re aiming to boost your career, change industries, or explore a rewarding new hobby, this book makes learning Python fun, fast, and practical—no prior experience required.
Python is the world’s most in-demand language, topping the 2024 Stack Overflow survey thanks to its leading role in AI, data science, and web development. Its clean, readable syntax makes it perfect for beginners, yet it’s powerful enough to handle advanced, professional projects. With Python, you can create almost anything—automate everyday tasks, build websites and games, analyze data, or even develop cutting-edge AI applications.
You’ll start by setting up Python and writing your first lines of code in minutes. From there, you’ll master the essentials—syntax, variables, data types, loops, functions, and logic—while learning to think like a programmer, focusing on solving problems rather than memorizing commands. Hands-on projects will reinforce every concept, helping you build real, functional programs from day one. Along the way, you’ll gain the confidence to debug errors like a pro and begin assembling a portfolio of work you can proudly share.
This book is for students seeking clarity and direction, professionals adding coding to their skill set, career changers breaking into tech without a computer science degree, hobbyists eager to create useful tools or fun projects, and educators searching for a classroom-ready resource. Whatever your background, you’ll discover just how far Python can take you in today’s tech-driven world.
Start your Python journey today—and unlock the skills to turn your ideas into reality. More information...