Connecting socket CAN adapter to SignalK

Socket can introduction

What is SocketCan?

Put simply SocketCan is a set of CAN drivers and networking stack that enables can bus appear as a network interfaces on a Linux computer.

For a better and more detailed explanation see wikipedia article

Another feature of SocketCAN is the virtual can interface. This acts like the Ethernet loop-back interface and can be very useful for replaying log files without transmitting them on a physical CAN bus.

Note: The scripts and techniques discussed in this document have only been tested on:

  • Raspberry pi 3 B (Revision: a02082)
  • Raspbian jessy (2017-03-02)
  • PiCAN2 (manufacture link)
    • PiCAN2 Duo should work as the second can interface is just a duplicate of the fist using a different SPI CS pin

Setting up the PiCAN2

Make the following changes to the /boot/config.txt file on the Raspberry pi
( sudo nano /boot/config.txt )

enable the spi bus by changing the following line

#dtparam=spi=on to dtparam=spi=on

append the follwing lines to the end of the config.txt file

dtoverlay=mcp2515-can0,oscillator=16000000,interrupt=25
dtoverlay=mcp2515-can1,oscillator=16000000,interrupt=24 #this line is only needed for the PiCAN2 Duo
dtoverlay=spi-bcm2835-overlay

Setting up the SocketCAN interfaces

Append the follwing lines to the /etc/network/interfaces file
(sudo nano /etc/network/interfaces)

#physical can interfaces
allow-hotplug can0
iface can0 can static
bitrate 250000
down /sbin/ip link set $IFACE down
up /sbin/ifconfig $IFACE txqueuelen 10000

Virtual CAN interface

Append the following lines to the /etc/network/interfaces file
(sudo nano /etc/network/interfaces)

 #virtual can interfaces
 auto vcan0
 iface vcan0 inet manual
 pre-up /sbin/ip link add dev $IFACE type vcan
 up /sbin/ifconfig $IFACE up

 

If this has worked correctly (a reboot may be needed) in addition to the regular Ethernet interfaces, ifconfig should display the following

pi@raspberrypi:~ $ ifconfig
can0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
UP RUNNING NOARP MTU:16 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:10
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)

vcan0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
UP RUNNING NOARP MTU:16 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)

Install the CANboat project

step 2 is optional but will keep your home directory a little tidier
setp 3 is needed for the raspberry pi 3 but may not be needed on other Linux distros
1. get the latest package repository catalogue with the command

 sudo apt-get update

2. create a folder to hold the CANboat project

 mkdir ~/canboat
 cd ~/canboat

3. install required module for the compiler with the command

 sudo apt-get install xsltproc

4. clone and build CANboat

 git clone git://github.com/canboat/canboat
 cd canboat
 sudo make
 sudo make install

CANboat should now be good to go.

Testing the interface

A warning about timing issues

the NMEA2000 CAN bus normally runs at 250Kb/s  so if you just issue the following command,

cat canlog.log | socketcan-writer vcan0

then (with the hardware used here) CANboat will only receive/decode approx 25% of the messages transmitted, if you slow the rate of transmission down it solves the problem.

Python script for replaying a log and slowing transmission

The following is a realy simple python script will read a log file (fName) and write each line to stdout with a 0.025 second delay between lines.

to create the script do the following in a suitable folder on your system

 touch logReplay.py
 chmod 775 logReplay.py
 (note you will want to chose apropreate permissions)
 nano logReplay.py

copy the following into the file

#!/usr/bin/env python
from time import sleep
from sys import *
#This is a simple script to re-play a logfile to stdout with a delay between each line

fName = './aava-n2k.data'
delaySec = 0.025
f = open( fName, 'r')
for ln in f:
stdout.write(ln)
sleep(delaySec)

Transmitting messages to socket can interface

For testing purposes we are using the vcan0 interface if you wish to transmit on the physical bus use can0 / can1 instead
logPlay.py | SocketCAN-writer vcan0

Expected errors

Some serial interfaces (Actisense NGT-1) add proprietary messages that are in addition to what was transmitted on the CAN bus, these are distinguished by having a PGN > 16384 (0x4000). If these are sent to CANboat’s socketcan-writer it will throw and error skip the message.

ERROR 2017-05-17T15:35:37.332Z [socketcan-writer] Invalid PGN, too big (0x400f2). Skipping.

Logging received messages

issue the following command will pipe the output from candump to a logfile

candump vcan0 | .fileNameOfLog.File

Setting signalK to listen to a socket can adapter

The json sample below should act as a templete signalK pipedProvder, repalce vcan0 with the aproprate socket can interface.
Restart the signalK server, then when you replay a log file or messages appear on the CAN bus and they should apear in signalK

{
  "id": "n2k-vcan0",
  "pipeElements": [
    {
      "type": "providers/execute",
      "options": {
        "command": "candump vcan0 | candump2analyzer "
      }
    },
    {
      "type": "providers/liner",
      "options": {
        "rawlogging": true,
        "logdir": "logs",
        "discriminator": "2"
      }
    },
    {
      "type": "providers/n2kAnalyzer"
    },
    {
      "type": "providers/n2k-signalk"
    }
  ]
}

Leave a comment