RS485 CAN HAT - hwthomas/ccs-chademo GitHub Wiki
Notes taken (with modifications) from "CAN communication on RaspberryPI with SocketCAN" by Pragmatic Linux
see https://www.pragmaticlinux.com/2021/10/can-communication-on-the-raspberry-pi-with-socketcan/
The Waveshare RS485/CAN hat attaches to the 40-pin GPIO connector on your Raspberry PI. The add-on board contains a Microchip MCP2515 CAN controller and a Texas Instruments SN65HVD230 CAN transceiver. The screw terminal connector and the 2.54 male header connector, expose the CAN transceiver’s CAN high and CAN low signals. You need those to connect to the actual CAN bus. The CAN transceiver translates the CAN high and low signals to the right signal and voltage levels for the CAN controller’s transmit and receive pins. SPI communication enables the Raspberry PI to communicate with the CAN controller itself.
The Linux kernel of the Raspberry PI operating system can handle a CAN device, based on the Microchip MCP2515. We just need to enable it with the help of a device tree overlay. Assuming that your Raspberry PI is all booted up, run the following command to edit the config.txt file in the boot partition:
sudo nano /boot/config.txt (or possibly /boot/firmware/config.txt)
Add this line to the file:
dtoverlay=mcp2515-can0,oscillator=12000000,interrupt=25,spimaxfrequency=2000000
This assumes the manufacturer installed a 12 MHz crystal oscillator on your Waveshare RS485/CAN hat. It’s the shiny silver colored and oval shaped component on the edge of the board. The number on it should read 12.000.
One more step, before we can use the Waveshare RS485/CAN hat as a SocketCAN interface on the Raspberry PI: We need to enable SPI communication with the help of the raspi-config tool. Open it by running command:
sudo raspi-config
Go to section Interface Options → SPI and select Yes to enable the SPI interface, and reboot.
Run the following command to list all CAN devices that the Linux kernel detected:
ip addr | grep "can"
Before our Raspberry PI can bring the can0 SocketCAN network interface in the UP state, we need to first load the SocketCAN related kernel modules. Open up the terminal again and run these commands:
sudo modprobe can
sudo modprobe can_raw
To verify that the SocketCAN related kernel modules loaded properly, run:
lsmod | grep "can"
Bring the can0 SocketCAN network interface in the UP state. It is a two step process:
Configure the SocketCAN network interface. Transition the SocketCAN network interface to the UP state. Commencing with the first step, open up the terminal and run the command:
sudo ip link set can0 type can bitrate 500000 restart-ms 100
This configures the can0 network interface for a CAN communication speed of 500,000 bits/second. Feel free to adjust this to match the CAN communication speed on your CAN bus. Furthermore, it configures can0 to automatically re-initialize the CAN controller in case of a CAN bus off event, after 100 milliseconds. Feel free to adjust this if needed, but 100 milliseconds works fine in most cases.
With the can0 SocketCAN network interface configured, we can attempt to transition it to the UP state. From the terminal run the command:
sudo ip link set up can0
To verify that the can0 SocketCAN network interface successfully transitioned to the UP state,run
ip addr | grep "can"
We next need to install the can-utils package on our Raspberry PI system:
sudo apt install can-utils
For receiving and displaying CAN messages, we run the candump program from the terminal:
candump -tz can0
NB -tz
prints timestamp on each message
We send a CAN message with the cansend
program. For example:-
CAN identifier: 456h; CAN data: 00h FFh AAh 55h 01h 02h 03h 04h (8 bytes)
cansend can0 456#00FFAA5501020304
If you only have a single RS485/CAN module attached to the RPi, and you monitor the CAN_H and CAN_L lines with a scope, you will see that after sending just this 1 message the output continues indefinitely. This is because part of the CAN message, which all other stations will respond to, is an inbuilt ACK, and if the transmitting node does not receive one, it will retransmit its message (and so on and...).
You can run candump
in another terminal at the same time, to see the transmitted message on the CAN bus, but - this doesn't seem to work at the moment, and candump
will hang until it sees a message from another node.
Note that you need to perform the above steps each time you reboot your Raspberry PI
ie
sudo modprobe can
sudo modprobe can_raw
sudo ip link set can0 type can bitrate 500000 restart-ms 100
sudo ip link set up can0
Luckily, you can automatic these steps, as follows.
First, add a file to the /etc/modules-load.d/
directory (needs root permissions) so that the can
and can_raw
SocketCAN kernel modules are loaded at boot time.
sudo nano /etc/modules-load.d/can.conf
with contents
can
can_raw
on separate lines, and save.
Use systemd-networkd
to manage SocketCAN network interfaces, and enable for restart on boot-up
sudo systemctl start systemd-networkd
sudo systemctl enable systemd-networkd
Configure SocketCAN network interface
sudo nano /etc/systemd/network/80-can.network
Add the following lines to this 80-can.network
file, and save.
[Match]
Name=can0
[CAN]
BitRate=500K
RestartSec=100mS
Reboot the system and check that the systemd-networkd
interface is running, and with the correct parameters
ip addr | grep "can"
ip -details link show can0
Install python-can library
pip3 install python-can