CANopen library providing functionality to implement responder nodes
Project description
A CANopen library to implement responder nodes.
Backends:
CAN interfaces via python-can
Synopsis
Pure Python implementation
Licensed under MIT (2021 Günther Jena)
Source code hosted on GitHub.com
Tested on Python 3.7, 3.8, 3.9, and 3.10
Unit tested with pytest, coding style enforced with Black, static type checking with mypy, static code analysis with Pylint, documentation generated with Sphinx
Supports CiA301 (EN 50325-4)
Feature List
Object Dictionary:
Provides callbacks for validation, update, download, and read operations
Supports records, arrays, and variables
EDS Support:
Dynamic generation of EDS files
Automatically provided via object 0x1021 (“Store EDS”)
SDO Servers:
Supports up to 128 SDO servers
Expedited, segmented, and block transfer for upload and download
Dynamically configurable COB-IDs
Custom upload and download handlers supported
PDO Support:
Up to 512 TPDOs and 512 RPDOs
Dynamically configurable
Transmission types: synchronous (acyclic and every nth sync) and event-driven
Supports inhibit time
EMCY Producer Service:
Dynamically configurable COB-ID
Supports inhibit time
Heartbeat Producer Service:
Dynamically configurable
NMT Slave Service:
Boot-up service
Callback for state change provided
SYNC Consumer Service:
Dynamically configurable COB-ID
Callback for received sync provided
CiA305 Layer Setting Service:
Supports fast scan
Configurable bitrate and node ID
Identify remote responder supported
CAN Interface Abstraction:
Full support for python-can
Automatic CAN ID filtering by subscribed services
Scheduling:
Supports threaded and async operation
TODO:
Build object dictionary via reading an EDS file
Support MPDOs
TIME consumer service
Up- and download handler as I/O streams
Examples
Creating a Node:
import can
from durand import CANBusNetwork, Node, Variable, Record, DatatypeEnum
bus = can.Bus(bustype='socketcan', channel='vcan0')
network = CANBusNetwork(bus)
node = Node(network, node_id=0x01)
Congratulations! You now have a CiA-301 compliant node running. The Layer Setting Service is also supported out of the box.
Adding Objects:
od = node.object_dictionary
# Add variable at index 0x2000
od[0x2000] = Variable(DatatypeEnum.UNSIGNED16, access='rw', value=10, name='Parameter 1')
# Add record at index 0x2001
record = Record(name='Parameter Record')
record[1] = Variable(DatatypeEnum.UNSIGNED8, access='ro', value=0, name='Parameter 2a')
record[2] = Variable(DatatypeEnum.REAL32, access='rw', value=0, name='Parameter 2b')
od[0x2001] = record
Accessing Values:
The objects can be read and written directly by accessing the object dictionary:
print(f'Value of Parameter 1: {od.read(0x2000, 0)}')
od.write(0x2001, 1, value=0xAA)
Adding Callbacks:
A more event-driven approach is to use callbacks. The following callbacks are available:
validate_callbacks: Called before a value in the object dictionary is updated
update_callbacks: Called when the value has been changed (via od.write or via CAN bus)
download_callbacks: Called when the value has been changed via CAN bus
read_callback: Called when an object is read (return value is used)
od.validate_callbacks[(0x2000, 0)].add(lambda v: v % 2 == 0)
od.update_callbacks[(0x2001, 2)].add(lambda v: print(f'Update for Parameter 2b: {v}'))
od.download_callbacks[(0x2000, 0)].add(lambda v: print(f'Download for Parameter 1: {v}'))
od.set_read_callback(0x2001, 1, lambda: 17)
PDO Mapping:
PDOs can be dynamically mapped via the SDO server or programmatically. The PDO indices start at 0.
node.tpdo[0].mapping = [(0x2001, 1), (0x2001, 2)]
node.tpdo[0].transmission_type = 1 # Transmit on every SYNC
node.rpdo[0].mapping = [(0x2000, 0)]
node.tpdo[0].transmission_type = 255 # Event-driven (processed when received)
Installation
pip install durand
Credits
This library would not be possible without:
python-canopen: CANopen library (by Christian Sandberg)
python-can: CAN interface library (by Brian Thorne)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file durand-0.5.0.tar.gz.
File metadata
- Download URL: durand-0.5.0.tar.gz
- Upload date:
- Size: 37.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.9.22
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
496afa9dce1747ca06186df4c0932da64692ff1b5bd3b6ebcc114f750d9a3f59
|
|
| MD5 |
fd3e11278a98ab4c2b52ab64d133a2c8
|
|
| BLAKE2b-256 |
5d65368ebbb343c441bb8891d6595b5d5bc6bf978feaba872e4291a1ae819e46
|
File details
Details for the file durand-0.5.0-py3-none-any.whl.
File metadata
- Download URL: durand-0.5.0-py3-none-any.whl
- Upload date:
- Size: 31.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.9.22
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a864e83877900a43fb4231b36cea41e9b36773cfb3b7f80ae2199a80cb24836e
|
|
| MD5 |
cdc183de68a5c191554311245fc7acbd
|
|
| BLAKE2b-256 |
55fd9fb92ac8efea37609d85fc6180f283917c8a57ba7bdbe4854fb606e6e5f8
|