Based on RPi3 installation with 2017-02-16-raspbian-jessie-lite.img
on March 5 2017. Later releases e.g. Raspbian Jessie with Pixel (2017-03-02-raspbian-jessie.img) follow the same installation.
Initial setup, use
raspi-config to enable SPI, I2C and remote GPIO.
Update the system, reboot and install can-utils and SocketCAN.
pi@void3:~ $ sudo apt-get -y update && sudo apt-get -y upgrade ; sudo apt-get autoremove
pi@void3:~ $ sudo apt-get -y install can-utils libsocketcan2 libsocketcan-dev
Reference:
SocketCAN (github)
Linux kernel documentation on CAN networking
Raspberry Pi overlays are described in /boot/overlays/README
- Device Trees, overlays and parameters is in great detail explained here
CAN-bus adapters
Four CAN-bus adapters to install, the LAWICEL USBCAN adapter, the SK Pang PiCAN2 CAN-Bus board, the SK Pang PiCAN2 Duo CAN-bus board and the Sys Tec USB-CAN GW-002-100 adapter.
LAWICEL USBCAN adapter
The USBCAN uses an Philips SJA1000 CAN Controller and an Philips 82C251 CAN Tranceiver. On the USB side is an FTDI FT245RL USB controller. The CAN data is formatted as ASCII instead of binary, known as slcan.
Attach the USBCAN to one of the USB ports of the RPi3.
To follow the entries in /var/log/syslog
do tail -f /var/log/syslog
in another terminal/shell. One could also follow the entries from the kernel ring buffer with dmesg -w
kernel: [40383.223047] usb 1-1.2: new full-speed USB device number 4 using dwc_otg
kernel: [40383.347790] usb 1-1.2: New USB device found, idVendor=0403, idProduct=6001
kernel: [40383.347812] usb 1-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
kernel: [40383.347825] usb 1-1.2: Product: CANUSB
kernel: [40383.347837] usb 1-1.2: Manufacturer: LAWICEL
kernel: [40383.347849] usb 1-1.2: SerialNumber: LWxxxxxx
kernel: [40384.404993] usbcore: registered new interface driver usbserial
kernel: [40384.405090] usbcore: registered new interface driver usbserial_generic
kernel: [40384.405177] usbserial: USB Serial support registered for generic
kernel: [40384.410363] usbcore: registered new interface driver ftdi_sio
kernel: [40384.410472] usbserial: USB Serial support registered for FTDI USB Serial Device
kernel: [40384.410765] ftdi_sio 1-1.2:1.0: FTDI USB Serial Device converter detected
kernel: [40384.410975] usb 1-1.2: Detected FT232RL
kernel: [40384.411932] usb 1-1.2: FTDI USB Serial Device converter now attached to ttyUSB0
Check if the OS sees the CANUSB and which modules are currently loaded.
pi@void3:~ $ lsusb
Bus 001 Device 004: ID 0403:6001 Future Technology Devices International, Ltd FT232 USB-Serial (UART) IC
pi@void3:~ $ lsmod
Module Size Used by
ftdi_sio 31321 0
usbserial 22115 1 ftdi_sio
— snip —
Load the required modules and list them.
pi@void3:~ $ sudo modprobe can
pi@void3:~ $ sudo modprobe vcan
pi@void3:~ $ sudo modprobe can_raw
pi@void3:~ $ sudo modprobe slcan
pi@void3:~ $ lsmod
Module Size Used by
vcan 2065 0
slcan 5590 0
can_raw 6852 0
can 27196 1 can_raw
ftdi_sio 31321 0
usbserial 22115 1 ftdi_sio
-- snip --
kernel: [41207.801732] can: controller area network core (rev 20120528 abi 9)
kernel: [41207.801834] NET: Registered protocol family 29
kernel: [41237.235336] can: raw protocol (rev 20120528)
kernel: [41252.916822] slcan: serial line CAN interface driver
kernel: [41252.916854] slcan: 10 dynamic interface channels.
Now unplug and re-insert the CANUSB, the OS act accordingly.
kernel: [41633.713932] usb 1-1.2: USB disconnect, device number 4
kernel: [41633.714493] ftdi_sio ttyUSB0: FTDI USB Serial Device converter now disconnected from ttyUSB0
kernel: [41633.714556] ftdi_sio 1-1.2:1.0: device disconnected
kernel: [41713.065798] usb 1-1.3: new full-speed USB device number 5 using dwc_otg
kernel: [41713.190585] usb 1-1.3: New USB device found, idVendor=0403, idProduct=6001
kernel: [41713.190607] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
kernel: [41713.190620] usb 1-1.3: Product: CANUSB
kernel: [41713.190632] usb 1-1.3: Manufacturer: LAWICEL
kernel: [41713.190644] usb 1-1.3: SerialNumber: LWxxxxxx
kernel: [41713.194922] ftdi_sio 1-1.3:1.0: FTDI USB Serial Device converter detected
kernel: [41713.195122] usb 1-1.3: Detected FT232RL
kernel: [41713.201043] usb 1-1.3: FTDI USB Serial Device converter now attached to ttyUSB0
Append the modules can
, vcan,can_raw
,slcan
to /etc/modules
so loading is done automatically.
sudo su
echo $'can\nvcan\ncan_raw\nslcan' >> /etc/modules
Bind the ttyUSB0
device to slcan
device, name the interface slcan0
, set CAN-bus speed 250 Kb/s (see canusb manual). Why it is initialized with -o=open -c=close is beyond me…
sudo slcand -o -c -f -s5 /dev/ttyUSB0
slcand[5703]: starting on TTY device /dev/ttyUSB0
slcand[5704]: attached TTY /dev/ttyUSB0 to netdevice slcan0
The slcan0
netdevice should be visible but in the state DOWN. So bring it to UP state.
pi@void3:~ $ ip addr | grep can
4: slcan0: <NOARP> mtu 16 qdisc noop state DOWN group default qlen 10
link/can
pi@void3:~ $ sudo ifconfig slcan0 up
pi@void3:~ $ ip addr | grep can
4: slcan0: <NOARP,UP,LOWER_UP> mtu 16 qdisc pfifo_fast state UNKNOWN group default qlen 10
link/can
For testing, i connected the USBCAN to an J1939 ECU and dump some CAN-bus traffic.
Note that the red led is lit and the green led blinks on traffic on the CAN-bus.
pi@void3:~ $ candump slcan0
slcan0 18FEFC00 [8] 00 00 00 E8 00 00 00 00
slcan0 0CFF8100 [8] A0 00 01 00 00 00 FF FF
slcan0 18FECA00 [8] 00 FF 00 00 00 00 FF FF
slcan0 0CF00400 [8] 00 CD 7D 00 00 00 00 00
slcan0 0CF00300 [8] 00 7D 00 00 00 00 00 00
slcan0 18FEDF00 [8] CD 00 00 00 00 00 00 00
slcan0 18FEEF00 [8] 19 00 00 00 00 7D 00 00
slcan0 18FEE500 [8] 00 00 00 00 00 00 00 00
slcan0 18FEEE00 [8] 69 46 E0 25 E0 25 5A 00
slcan0 18FEF200 [8] 00 00 00 00 00 00 7D 00
slcan0 18FEF600 [8] 00 32 2A 00 00 A0 24 00
slcan0 18FEE400 [8] 00 00 00 00 00 00 00 00
slcan0 18FEF700 [8] 00 00 00 00 E0 01 E0 01
slcan0 0CFF4700 [8] 00 00 00 00 00 00 00 00
slcan0 18FEFF00 [8] 01 00 00 00 00 00 00 00
slcan0 0CF00400 [8] 00 CD 7D 00 00 00 00 00
slcan0 0CF00400 [8] 00 CD 7D 00 00 00 00 00
slcan0 0CF00300 [8] 00 7D 00 00 00 00 00 00
slcan0 0CFF4700 [8] 00 00 00 00 00 00 00 00
pi@void3:~ $ netstat -i -l
Kernel Interface table
Iface MTU Met RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg
eth0 1500 0 0 0 0 0 0 0 0 0 BMU
lo 65536 0 0 0 0 0 0 0 0 0 LRU
slcan0 16 0 101339 0 0 0 0 0 0 0 ORU
wlan0 1500 0 108172 0 25282 0 75044 0 0 0 BMRU
The Old Way i.e. with udev
- Create three files and fill them with the content below
sudo vi /etc/udev/rules.d/90-slcan.rules
sudo vi /usr/local/bin/slcan_add.sh
sudo vi /usr/local/bin/slcan_remove.sh
- Make the shell files executable
sudo chmod +x /usr/local/bin/slcan_add.sh
sudo chmod +x /usr/local/bin/slcan_remove.sh
- reboot (
sudo reboot
) to apply the new udev rules
- test the netdevice
slcan0
with candump slcan0
# file: /etc/udev/rules.d/90-slcan.rules
# Lawicel CANUSB module
# For similar devices, change "CANUSB" to "6001".
ACTION=="add", ENV{ID_MODEL}=="CANUSB", ENV{SUBSYSTEM}=="tty", RUN+="/usr/bin/logger [udev] Lawicel CANUSB detected", RUN+="/usr/local/bin/slcan_add.sh $kernel"
ACTION=="remove", ENV{ID_MODEL}=="CANUSB", ENV{SUBSYSTEM}=="usb", RUN+="/usr/bin/logger [udev] Lawicel CANUSB removed", RUN+="/usr/local/bin/slcan_remove.sh"
#!/bin/sh
# file: /usr/local/bin/slcan_add.sh
# Bind the USBCAN device, -s5 (250Kb/s)
slcand -o -c -f -s5 /dev/$1
sleep 1
ifconfig slcan0 up
#!/bin/sh
# file: /usr/local/bin/slcan_remove.sh
# Remove the USBCAN device
pkill slcand
Use udevadm monitor --property
to monitor for hints if it does not work.
Commands related to slcan
- slattach :: attach a network interface to a serial line
- slcan_attach
- slcand
- slcanpty
Usage: slattach [-ehlLmnqv] [-k keepalive] [-o outfill] [-c cmd] [-s speed] [-p protocol] tty
---------------------------------------------------------------------------------
Usage: slcan_attach [options] tty
Options: -o (send open command 'O\r')
-c (send close command 'C\r')
-f (read status flags with 'F\r' to reset error states)
-s <speed> (set CAN speed 0..8)
-b <btr> (set bit time register value)
-d (only detach line discipline)
-w (attach - wait for keypess - detach)
-n <name> (assign created netdevice name)
Examples:
slcan_attach -w -o -f -s6 -c /dev/ttyS1
slcan_attach /dev/ttyS1
slcan_attach -d /dev/ttyS1
slcan_attach -w -n can15 /dev/ttyS1
---------------------------------------------------------------------------------
Usage: slcand [options] <tty> [canif-name]
Options: -o (send open command 'O\r')
-c (send close command 'C\r')
-f (read status flags with 'F\r' to reset error states)
-s <speed> (set CAN speed 0..8)
-S <speed> (set UART speed in baud)
-t <type> (set UART flow control type 'hw' or 'sw')
-b <btr> (set bit time register value)
-F (stay in foreground; no daemonize)
-h (show this help page)
Examples:
slcand -o -c -f -s6 ttyslcan0
slcand -o -c -f -s6 ttyslcan0 can0
---------------------------------------------------------------------------------
slcanpty creates a pty for applications using the slcan ASCII protocol and
converts the ASCII data to a CAN network interface (and vice versa)
Usage: slcanpty <pty> <can interface>
e.g. 'slcanpty /dev/ptyc0 can0' creates /dev/ttyc0 for the slcan application
e.g. for pseudo-terminal 'slcanpty /dev/ptmx can0' creates /dev/pts/N
SK Pang electronics PiCAN2 CAN-Bus board for Raspberry Pi 2/3![PiCAN2]()
PiCAN2 board uses uses the Microchip MCP2515 CAN controller with MCP2551 CAN transceiver. Connection are made via DB9 or 3 way screw terminal. Interrupt RX on GPIO25. Manual Schematic
File: /boot/overlay/README
Name: mcp2515-can0
Info: Configures the MCP2515 CAN controller on spi0.0
Load: dtoverlay=mcp2515-can0,<param>=<val>
Params: oscillator Clock frequency for the CAN controller (Hz)
spimaxfrequency Maximum SPI frequence (Hz)
interrupt GPIO for interrupt signal
Add to /boot/config.txt
# Enable MCP2515 on SPI
# dtparam=spi=on
dtoverlay=mcp2515-can0,oscillator=16000000,interrupt=25
dtoverlay=spi-bcm2835-overlay
After an reboot, lsmod should list two new entries i.e. mcp251x
, can_dev
.
/etc/modprobe.d/raspi-blacklist.conf
is empty, so no worries here.
$ sudo depmod -a
$ sudo ip link set can0 up type can bitrate 250000 listen-only on
kernel: [epoch] CAN device driver interface
kernel: [epoch] IPv6: ADDRCONF(NETDEV_CHANGE): can0: link becomes ready
kernel: [epoch] can: controller area network core (rev 20120528 abi 9)
kernel: [epocj] NET: Registered protocol family 29
kernel: [epoch] can: raw protocol (rev 20120528)
$ candump -cae can0,0:0,#FFFFFFF
SK Pang electronics PiCAN2 Duo CAN-Bus board for Raspberry Pi 2/3
PiCAN2 Duo board uses uses the Microchip MCP2515 CAN controller with MCP2551 CAN transceiver. Connection are made 4 way screw terminal. Interrupt RX on GPIO25 and GPIO24. Manual Schematic
Installation is the same as the PiCAN2 with the additional line in /boot/config.txt
# Enable MCP2515 on SPI
# dtparam=spi=on
dtoverlay=mcp2515-can0,oscillator=16000000,interrupt=25
dtoverlay=mcp2515-can1,oscillator=16000000,interrupt=24
dtoverlay=spi-bcm2835-overlay
SYS TEC USB-CAN GW-002-100![SYS TEC electronic GW-002-100 SYS TEC electronic GW-002-100]()
This is an isolated USB CAN adapter from 2008 and is still in use on Windows 10 (unsupported). Linux does not recognize the adapter.
kernel: [48959.081101] usb 1-1.5: new full-speed USB device number 6 using dwc_otg
kernel: [48959.182630] usb 1-1.5: New USB device found, idVendor=0878, idProduct=1102
kernel: [48959.182652] usb 1-1.5: New USB device strings: Mfr=0, Product=0, SerialNumber=0
The manual and systec can code for the one with spare time…
SocketCAN tools
The virtual CAN-bus interface is often used for replaying stored CAN-bus traffic.
$ sudo modprobe vcan
$ sudo ip link add vcan0 type vcan
$ sudo ip link set vcan0 up
candump
candump -cae any,0:0,#FFFFFFFF
shows everything, including errors, on the CAN-bus.
candump -cae can0,3CD:7FF
shows only data of specific ID’s i.e. 3CD…7FF
candump -l can0,0:0,#FFFFFFFF
dumps all data, excluding errors, to a file
Enabling Logfile ‘candump-2017-03-11_160601.log‘
(1489244835.086277) can0 742#05
(1489244835.091032) can0 0A484082#0000000000000000
(1489244835.096506) can0 732#05
(1489244835.101695) can0 0C000003#01E02E7DFFFFFFFF
(1489244835.106290) can0 722#05
(1489244835.107590) can0 721#05
(1489244835.115500) can0 0CF00400#00CD7D0000000000
(1489244835.119888) can0 0C000003#01E02E7DFFFFFFFF
(1489244835.138204) can0 0C000003#01E02E7DFFFFFFFF
(1489244835.139441) can0 0CFD9303#FFFFFFC3FFFFFFFF
canplayer vcan0=can0 -v -l 10 -I candump-2017-03-11_160601.log
replays data to can0
cansniffer can0
shows CAN-bus data grouped by the messages identifiers (ID)
Usage: candump [options] <CAN interface>+
(use CTRL-C to terminate candump)
Options: -t <type> (timestamp: (a)bsolute/(d)elta/(z)ero/(A)bsolute w date)
-c (increment color mode level)
-i (binary output - may exceed 80 chars/line)
-a (enable additional ASCII output)
-S (swap byte order in printed CAN data[] - marked with '`' )
-s <level> (silent mode - 0: off (default) 1: animation 2: silent)
-b <can> (bridge mode - send received frames to <can>)
-B <can> (bridge mode - like '-b' with disabled loopback)
-u <usecs> (delay bridge forwarding by <usecs> microseconds)
-l (log CAN-frames into file. Sets '-s 2' by default)
-L (use log file format on stdout)
-n <count> (terminate after receiption of <count> CAN frames)
-r <size> (set socket receive buffer to <size>)
-d (monitor dropped CAN frames)
-e (dump CAN error frames in human-readable format)
-x (print extra message infos, rx/tx brs esi)
-T <msecs> (terminate after <msecs> without any reception)
Up to 16 CAN interfaces with optional filter sets can be specified
on the commandline in the form: <ifname>[,filter]*
Comma separated filters can be specified for each given CAN interface:
<can_id>:<can_mask> (matches when <received_can_id> & mask == can_id & mask)
<can_id>~<can_mask> (matches when <received_can_id> & mask != can_id & mask)
#<error_mask> (set error frame filter, see include/linux/can/error.h)
CAN IDs, masks and data content are given and expected in hexadecimal values.
When can_id and can_mask are both 8 digits, they are assumed to be 29 bit EFF.
Without any given filter all data frames are received ('0:0' default filter).
Use interface name 'any' to receive from all CAN interfaces.
Examples:
candump -c -c -ta can0,123:7FF,400:700,#000000FF can2,400~7F0 can3 can8
candump -l any,0~0,#FFFFFFFF (log only error frames but no(!) data frames)
candump -l any,0:0,#FFFFFFFF (log error frames and also all data frames)
candump vcan2,92345678:DFFFFFFF (match only for extended CAN ID 12345678)
candump vcan2,123:7FF (matches CAN ID 123 - including EFF and RTR frames)
candump vcan2,123:C00007FF (matches CAN ID 123 - only SFF and non-RTR frames)
Usage: cansniffer [can-interface]
Options: -m <mask> (initial FILTER default 0x00000000)
-v <value> (initial FILTER default 0x00000000)
-q (quiet - all IDs deactivated)
-r <name> (read sniffset.name from file)
-b (start with binary mode)
-B (start with binary mode with gap - exceeds 80 chars!)
-c (color changes)
-f (filter on CAN-ID only)
-t <time> (timeout for ID display [x100ms] default: 50, 0 = OFF)
-h <time> (hold marker on changes [x100ms] default: 10)
-l <time> (loop time (display) [x100ms] default: 2)
Use interface name 'any' to receive from all can-interfaces
commands that can be entered at runtime:
q<ENTER> - quit
b<ENTER> - toggle binary / HEX-ASCII output
B<ENTER> - toggle binary with gap / HEX-ASCII output (exceeds 80 chars!)
c<ENTER> - toggle color mode
#<ENTER> - notch currently marked/changed bits (can be used repeatedly)
*<ENTER> - clear notched marked
rMYNAME<ENTER> - read settings file (filter/notch)
wMYNAME<ENTER> - write settings file (filter/notch)
+FILTER<ENTER> - add CAN-IDs to sniff
-FILTER<ENTER> - remove CAN-IDs to sniff
FILTER can be a single CAN-ID or a CAN-ID/Bitmask:
+1F5<ENTER> - add CAN-ID 0x1F5
-42E<ENTER> - remove CAN-ID 0x42E
-42E7FF<ENTER> - remove CAN-ID 0x42E (using Bitmask)
-500700<ENTER> - remove CAN-IDs 0x500 - 0x5FF
+400600<ENTER> - add CAN-IDs 0x400 - 0x5FF
+000000<ENTER> - add all CAN-IDs
-000000<ENTER> - remove all CAN-IDs
if (id & filter) == (sniff-id & filter) the action (+/-) is performed,
which is quite easy when the filter is 000
Usage: canplayer <options> [interface assignment]*
Options: -I <infile> (default stdin)
-l <num> (process input file <num> times)
(Use 'i' for infinite loop - default: 1)
-t (ignore timestamps: send frames immediately)
-g <ms> (gap in milli seconds - default: 1 ms)
-s <s> (skip gaps in timestamps > 's' seconds)
-x (disable local loopback of sent CAN frames)
-v (verbose: print sent CAN frames)
Interface assignment: 0..n assignments like <write-if>=<log-if>
e.g. vcan2=can0 ( send frames received from can0 on vcan2 )
extra hook: stdout=can0 ( print logfile line marked with can0 on stdout )
No assignments => send frames to the interface(s) they had been received from.
Lines in the logfile not beginning with '(' (start of timestamp) are ignored.
can-utils :
asc2log, bcmserver, can-calc-bit-timing, canbusload, candump, canfdtest, cangen,
cangw, canlogserver, canplayer, cansend, cansniffer, isotpdump, isotpperf,
isotprecv, isotpsend, isotpserver, isotpsniffer, isotptun, log2asc, log2long,
slcan_attach, slcand, slcanpty