This repository contains a Python module used for instantiating CANopen nodes in Linux, especially for a Raspberry Pi. The socketcanopen
module contains classes to instantiate a CANopen node application. This module now requires the can module, replacing the original socketcan module. Each node must be initialized with at least one can.BusABC
instance, a node-ID (integer, 1 to 127), and a socketcanopen.ObjectDictionary
instance.
Example node applications are provided:
canopen-node-sdo.py
is the simplest implentation of a node that supports SDO communication.canopen-node-sdo-normal.py
has object dictionary entries with values greater than 4 bytes to demonstrate normal (non-expedited) SDO.canopen-node-eds.py
imports the CANopen object dictionary from an EDS file (node.eds
).canopen-node-pdo.py
adds synchronous PDO support.canopen-master.py
is a complex example of a CANopen Master that involves using GPIOs and how to interact with changes to the object dictionary.
systemd
.service
unit files and instructions for starting the node applications at boot are also provided.
Example protocol adaptors are provided: Note that these are very crude and do not provide buffering.
- CANopen-to-HTTP (
canopen-http.py
, implementation of CiA 309-5) - CAN-to-WebSocket (
websocketcan-server.py
, uses SocketCAN message structure;websocketcan.js
andwebsocketcanopen.js
provide wrappers to JavaScript's WebSocket, which can be used to decode messages in client browser)
-
Install the latest version of Raspbian.
-
(Optional) Because of a driver issue, you may need to add
dtoverlay=mmc
to/boot/config.txt
for the Raspberry Pi to boot. -
(Optional) Run
sudo raspi-config
and adjust internationalization options. -
(Optional) Prevent flash memory corruption:
-
Change
/etc/fstab
to:proc /proc proc defaults 0 0 /dev/mmcblk0p1 /boot vfat ro,noatime 0 2 /dev/mmcblk0p2 / ext4 defaults,noatime 0 1 none /var/log tmpfs size=1M,noatime 0 0
-
Disable swap memory:
sudo dphys-swapfile swapoff sudo dphys-swapfile uninstall sudo update-rc.d dphys-swapfile remove
-
Reboot:
sudo reboot
-
-
Connect MCP2515 circuit(s) to the Raspberry Pi
SPI0
bus. Interrupt GPIOs are defined in step 4. -
If necessary, enable writable boot partition:
sudo mount -o remount,rw /dev/mmcblk0p1 /boot
-
Run
sudo raspi-config
- Interfacing Options
- SPI: Enable/Disable automatic loading (Yes)
- Interfacing Options
-
Configure SPI Module: Change
/boot/config.txt
to:dtoverlay=mcp2515-can1,oscillator=16000000,interrupt=24 dtoverlay=mcp2515-can0,oscillator=16000000,interrupt=25
Note: It appears the order of the mcp2515-can* overlay determines which SPI CE is used (first listing gets spi0.1/CE1, second listing get spi0.0/CE0), even though the documentation says otherwise. See raspberrypi/linux#1490 for more info.
Note: The
oscillator
andinterrupt
parameters may be different for your application. -
Reboot to enable the MCP2515 drivers.
-
Setup CAN interfaces
- Manual
sudo ip link set can0 up type can bitrate 1000000 sudo ip link set can1 up type can bitrate 1000000
- Automatic (start at boot-up)
- Copy can_if to
/home/pi/
(or change location incan_if.service
- Modify
can_if
lineCAN_IF=""
toCAN_IF="can0@1000000,2000 can1@1000000,2000"
(may vary per application) - Set
can_if
to be globally executable (chmod +x can_if
) - Copy
can_if.service
to/etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable can_if.service
sudo reboot
orsudo systemctl start can_if.service
- Copy can_if to
-
(Optional) Install
can-utils
for debuggingsudo apt install can-utils
git clone https://github.com/bggardner/canopen-rpi.git
cd canopen-rpi
pip3 install -e .
Many examples are provided. The simplest code is when using an EDS file:
#!/usr/bin/env python3
import can
import signal
import socketcanopen
can_bus = can.Bus("vcan0", bustype="socketcan")
node_id = 0x02
canopen_od = socketcanopen.ObjectDictionary.from_eds(os.path.dirname(os.path.abspath(__file__)) + '/node.eds', node_id)
node = socketcanopen.Node(can_bus, node_idd, canopen_od)
signal.pause() # Run forever
-
Setup CANopen Master
- Copy canopen-master.py to
/home/pi/
- Copy canopen-master.service to
/etc/systemd/service/
and configure withsystemctl
likecan_if.service
above
- Copy canopen-master.py to
-
Setup CAN-to-WebSocket Adapter
- Copy websocketcan-server.py to
/home/pi/
- Copy websocketcan-server.service to
/etc/systemd/service/
and configure withsystemctl
likecan_if.service
above
- Copy websocketcan-server.py to