Install & Compatibility
Where this runs
tested against v2.4.1 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.910 runs
installs and imports cleanly · install 0.0s · import 0.442s · 22.2MB
glibcpy 3.10–3.910 runs
installs and imports cleanly · install 2.5s · import 0.382s · 23MB
21MB installed
● package 21MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
Network
✓ import canopen
network = canopen.Network()
Node
✓ import canopen
node = canopen.Node(node_id, 'eds_file.eds')
SdoError
✓ from canopen.sdo import SdoError
This quickstart demonstrates how to connect to a CAN bus, add a CANopen node using an EDS file, and perform basic SDO (Service Data Object) read/write operations. It includes error handling for common issues like CAN connection problems and missing EDS files. Remember to replace placeholder values for `CAN_BUSTYPE`, `CAN_CHANNEL`, `NODE_ID`, and `EDS_FILE` with your actual setup. A dummy `example.eds` is created if not found, but a real EDS file for your device is crucial for proper communication.
import canopen
import time
import os
# Configuration
CAN_BUSTYPE = os.environ.get('CAN_BUSTYPE', 'socketcan') # e.g., 'socketcan', 'pcan', 'ixxat'
CAN_CHANNEL = os.environ.get('CAN_CHANNEL', 'can0') # e.g., 'can0', 'PCAN_USBBUS1'
NODE_ID = int(os.environ.get('CANOPEN_NODE_ID', '1'))
EDS_FILE = os.environ.get('CANOPEN_EDS_FILE', 'example.eds') # Replace with your device's EDS file
# Create a dummy EDS file for demonstration if it doesn't exist
# In a real application, you would use a manufacturer-provided .eds
if not os.path.exists(EDS_FILE):
print(f"Warning: {EDS_FILE} not found. Using a generic one (may not work with your device).")
with open(EDS_FILE, 'w') as f:
f.write("""
[FileInfo]
; Generated EDS for a generic CANopen device
FileName = ExampleDevice.eds
FileVersion = 1.0
VendorName = Example Vendor
ProductName = Example Product
ProductCode = 0
RevisionNo = 1.0
CreationTime = 2023-01-01 12:00:00
[Device]
DeviceType = 0x00020002
[0x1000] ; Device Type
ParameterName = Device Type
ObjectType = 7
DataType = 0x0007
AccessType = ro
DefaultValue = 0x00020002
[0x1001] ; Error Register
ParameterName = Error Register
ObjectType = 7
DataType = 0x0005
AccessType = ro
DefaultValue = 0x00
[0x2000] ; Example Manufacturer Specific Integer (RW)
ParameterName = My Integer
ObjectType = 7
DataType = 0x0007
AccessType = rw
DefaultValue = 123
""")
try:
# Start with creating a network representing one CAN bus
network = canopen.Network()
# Connect to the CAN bus
# The bustype and channel must match your installed python-can backend
print(f"Connecting to CAN bus: bustype='{CAN_BUSTYPE}', channel='{CAN_CHANNEL}'")
network.connect(bustype=CAN_BUSTYPE, channel=CAN_CHANNEL)
print("Connected to CAN bus.")
# Add a CANopen node with documentation from the EDS file
# For a real device, replace NODE_ID and EDS_FILE with your device's info
node = canopen.Node(NODE_ID, EDS_FILE)
network.add_node(node)
print(f"Added Node {NODE_ID} using {EDS_FILE}.")
# Read a value from the object dictionary (e.g., Device Type 0x1000)
device_type = node.sdo['Device Type'].raw
print(f"Node {NODE_ID} Device Type (0x1000): {hex(device_type)}")
# Write and read a manufacturer-specific object (e.g., 0x2000 subindex 0)
# This assumes your EDS or device supports object 0x2000
try:
original_val = node.sdo[0x2000].raw
print(f"Original value of 0x2000: {original_val}")
new_val = 456
node.sdo[0x2000].raw = new_val
print(f"Wrote {new_val} to 0x2000.")
read_val = node.sdo[0x2000].raw
print(f"Read back value of 0x2000: {read_val}")
assert read_val == new_val
except canopen.sdo.SdoError as e:
print(f"Could not access object 0x2000 on Node {NODE_ID}. This might be an EDS mismatch or device limitation: {e}")
# For real-time data (PDOs), you'd typically start the network's processing loop
# in a separate thread or call network.process() periodically.
# For this quickstart, we'll just demonstrate it briefly.
print("Starting network processing for 1 second...")
network.nmt.state = 'OPERATIONAL' # Set node to operational for PDOs
start_time = time.time()
while time.time() - start_time < 1:
network.process(0.01) # Process messages for 10ms
time.sleep(0.01)
print("Network processing finished.")
except canopen.CanError as e:
print(f"CANopen Error: {e}")
print("Please ensure your CAN hardware is connected and the python-can backend is correctly installed.")
print(f"Tried bustype='{CAN_BUSTYPE}', channel='{CAN_CHANNEL}'")
except FileNotFoundError:
print(f"Error: EDS file '{EDS_FILE}' not found. Please provide a valid EDS file for your device.")
except Exception as e:
print(f"An unexpected error occurred: {e}")
finally:
# Disconnect from CAN bus
if 'network' in locals() and network.is_connected:
print("Disconnecting from CAN bus.")
network.disconnect()
if os.path.exists(EDS_FILE) and 'Warning: ' in locals() and 'generic one' in locals(): # Clean up dummy EDS
os.remove(EDS_FILE)
print(f"Removed dummy EDS file: {EDS_FILE}")
canopen --version
Errors
Common errors & fixes
ModuleNotFoundError: No module named 'canopen'
The 'canopen' library is not installed in the Python environment, or the Python interpreter cannot find it in its search path.
fixInstall the library using pip: `pip install canopen`.
can.CanError: Could not connect to CAN bus
The `canopen.Network.connect()` method failed to establish a connection to the specified CAN bus. This often indicates issues with the `python-can` backend configuration, incorrect channel or bitrate parameters, or problems with the physical CAN interface (e.g., driver issues, device not connected, permissions).
fixEnsure `python-can` is correctly installed for your specific CAN interface (e.g., `pip install 'python-can[pcan]'`). Verify the `bustype`, `channel`, and `bitrate` parameters match your hardware setup and `python-can` configuration. Check device drivers and permissions for the CAN interface.
canopen.sdo.exceptions.SdoCommunicationError: No SDO response received
During an SDO (Service Data Object) communication, the remote CANopen node did not respond within the expected timeout period. This can be due to an incorrect node ID, the node being in the wrong NMT state (e.g., not operational), network communication issues, or the node being unresponsive.
fixVerify the remote node's ID and ensure it is in the 'Operational' NMT state. Check the physical CAN bus for connectivity and termination. Increase the SDO timeout if the network is busy or the node is slow to respond, or ensure the node is actively participating in the CANopen network.
canopen.objectdictionary.ObjectDictionaryError: Mismatch between expected and actual data size
This error occurs when the object dictionary (typically loaded from an EDS file) defines a certain data size for an object, but the actual data received from or sent to the CANopen device via SDO has a different size.
fixReview the EDS file used to load the object dictionary and compare it against the device's actual object dictionary implementation. Ensure the EDS file is correct and matches the firmware version of the device. If writing, ensure the data being sent matches the expected size for the object index and sub-index.
Upgrade
Version history
2.4.1latest on PyPI · released Aug 5, 2025
Audit
Dependencies
python-canrequiredCore dependency for CAN bus communication; specific hardware-related backends (e.g., `python-can[socketcan]`) must be installed separately.