-
-
Notifications
You must be signed in to change notification settings - Fork 31
How to set interact with a UAVCAN node with Raspberry Pi and CAN Hat or BeagleBone
The Raspberry Pi has no builtin CAN interface. So a device needs to be added. For the first tests a virtual CAN interface might be OK. But this is not sufficient for a connection with real hardware.
UAVCAN uses the Socket CAN interface on linux. CAN devices can be listed by typing ifconfig
.
Bitrate depends on your hardware. Typical value is 250k.
The virtual CAN port is already compiled into the default raspbian kernel. It only needs to be enabled.
sudo modprobe vcan
sudo ip link add dev vcan0 type vcan
sudo ip link set up vcan0
The MCP2515 is a CAN controller which connects to the SPI port. Several HATs and breakout boards are available.
edit /boot/config.txt
and add line:
dtoverlay=mcp2515-can0,oscillator=16000000,interrupt=25
values of oscillator and interrupt depend on your hardware.
after each boot enable can interface with:
sudo ip link set can0 up type can bitrate 250000
The MCP2518FD is a CAN FD controller with higher data rata. The MCP2517FD is its predecessor and supports also CAN FD but is not recommended for new designs. Both connect via SPI.
edit /boot/config.txt
and add line:
dtoverlay=mcp251xfd,spi0-0,interrupt=25
keep care that you choose the right interrupt and SPI CE line and populate the corresponding resistor.
enable CAN after boot up with
sudo ip link set can0 up type can bitrate 250000
Unlike the Raspberry Pi the BeagleBone has two builtin CAN controller. You only have to connect a CAN transceiver like TI SN65HVD232. The latest distributions (Debian Buster 10.x) have the CAN controller already enabled in the kernel. You only have to switch the IO pins to CAN mode.
Usually CAN1 is selected because CAN0 interferes with I2C2 which is used to identify capes. CAN1 is routed to pins P9.24 (RX) and P9.26 (TX). Connect the CAN transceiver to these pins. The pins have to be enabled with:
sudo config-pin p9.24 can
and
sudo config-pin p9.26 can
This blog post shows how to automate this: https://www.bacpeters.com/2020/01/25/configuring-the-beaglebone-black-gpio-pins-permanently/
Then the CAN interface has to be enable like on the Raspberry Pi after each boot up:
sudo ip link set can1 up type can bitrate 250000
Attention: On the BeagleBone can1 is used. So replace can0 with can1 in all following examples.
Also the BeagleBone has less computing power than the Raspberry Pi. Therefore every action will take way longer than on the Raspberry Pi.
The CAN interface can be tested with the can-utils. Install the with:
sudo apt-get install can-utils
all messages on the CAN bus can be displayed using
candump -decaxta vcan0
or
candump -decaxta can0
Attention: The physical CAN bus only works correctly if there are at least two active devices connected to the bus. Otherwise Socket-CAN might report: [Errno 105] No buffer space available
.
-
Install libatlas
sudo apt-get install libatlas-base-dev
-
python3 is already installed, link to python 3
-
check pip3 version with
pip3 --version
pip should be 20.3.3 or newer. -
update pip if necessary
pip3 install --upgrade pip
-
install yukat with
pip3 install yakut
This should install yukat in /home/pi/.local/bin
.
To access pyuavcan easily the path should be added to PATH. On raspbian this is done by default. Otherwise update $PATH in .profile
and add the line:
$PATH="$PATH:/home/pi/.local/bin"
Check if yakut installation was successful by typing
yakut --version
This should print the version of yakut.
Generate DSDL with the standard namespaces:
cd ~
yakut compile https://github.com/UAVCAN/public_regulated_data_types/archive/master.zip
This may take a few minutes.
Send test string:
yakut --transport='CAN(can.media.socketcan.SocketCANMedia("vcan0",8),59)' publish uavcan.diagnostic.Record.1.0 '{"text": "Hello world!"}'
59 is the Node-ID and can be changed to any desired value. Node-IDs need to be unique on the system.
The text string should be visable in a second window running candump.
Now the installation of yakut is finished.
Use an Arduino with CAN interface, for example an Arduino MKR Zero with an MKR CAN Shield. Connect the CAN interface of the Raspberry Pi to the one of the Arduino. Connect CANH to CANH and CANL to CANL and GND to GND. Connection of VCC is not necessary and not recommended. Take care of the termination resistor. In the CAN spec it is defined that on both ends of a CAN line a 120 ohm termination should be installed. When you use only a short line with only a few devices connected the correct value of this resistor is not that important. But at least on resistor should be placed on the line.
Load a uavcan sketch onto the Arduino, for example the UAVCAN-Heartbeat-Publish example.
Attention: When running the arduino sketch unattended, comment the initialisation of the serial port. Otherwise the sketch will wait forever at startup and no CAN messages will be sent. Change the following line:
- while(!Serial) { }
+// while(!Serial) { }
The messages can be received by the Raspberry Pi and displayed using candump. Type:
candump -decaxta can0
The output (only heartbeat) should be like:
(1608484588.783110) can0 RX - - 107D550D [8] F0 0F 00 00 00 00 00 EE '........'
(1608484589.786750) can0 RX - - 107D550D [8] F1 0F 00 00 00 00 00 EF '........'
(1608484590.790368) can0 RX - - 107D550D [8] F2 0F 00 00 00 00 00 F0 '........'
(1608484591.794008) can0 RX - - 107D550D [8] F3 0F 00 00 00 00 00 F1 '........'
(1608484592.797639) can0 RX - - 107D550D [8] F4 0F 00 00 00 00 00 F2 '........'
(1608484593.801287) can0 RX - - 107D550D [8] F5 0F 00 00 00 00 00 F3 '........'
The messages can also be displayed by pyuavcan. At the moment only defined messages like the Heartbeat
can be received:
yakut --transport='CAN(can.media.socketcan.SocketCANMedia("can0",8),59)' sub uavcan.node.Heartbeat.1.0
output:
---
7509:
_metadata_:
timestamp:
system: 1608484435.212532
monotonic: 7463.789214
priority: nominal
transfer_id: 16
source_node_id: 13
uptime: 3926
health:
value: 0
mode:
value: 0
vendor_specific_status_code: 0
---
7509:
_metadata_:
timestamp:
system: 1608484436.216082
monotonic: 7464.792549
priority: nominal
transfer_id: 17
source_node_id: 13
uptime: 3927
health:
value: 0
mode:
value: 0
vendor_specific_status_code: 0