Coder Social home page Coder Social logo

canopen's Introduction

CANopen for Python

A Python implementation of the CANopen standard. The aim of the project is to support the most common parts of the CiA 301 standard in a simple Pythonic interface. It is mainly targeted for testing and automation tasks rather than a standard compliant master implementation.

The library supports Python 3.8 or newer.

Features

The library is mainly meant to be used as a master.

  • NMT master
  • SDO client
  • PDO producer/consumer
  • SYNC producer
  • EMCY consumer
  • TIME producer
  • LSS master
  • Object Dictionary from EDS
  • 402 profile support

Incomplete support for creating slave nodes also exists.

  • SDO server
  • PDO producer/consumer
  • NMT slave
  • EMCY producer
  • Object Dictionary from EDS

Installation

Install from PyPI using :program:`pip`:

$ pip install canopen

Install from latest master on GitHub:

$ pip install https://github.com/christiansandberg/canopen/archive/master.zip

If you want to be able to change the code while using it, clone it then install it in develop mode:

$ git clone https://github.com/christiansandberg/canopen.git
$ cd canopen
$ pip install -e .

Unit tests can be run using the pytest framework:

$ pip install -r requirements-dev.txt
$ pytest -v

You can also use :mod:`unittest` standard library module:

$ python3 -m unittest discover test -v

Documentation

Documentation can be found on Read the Docs:

http://canopen.readthedocs.io/en/latest/

It can also be generated from a local clone using Sphinx:

$ pip install -r doc/requirements.txt
$ make -C doc html

Hardware support

This library supports multiple hardware and drivers through the python-can package. See the list of supported devices.

It is also possible to integrate this library with a custom backend.

Quick start

Here are some quick examples of what you can do:

The PDOs can be access by three forms:

1st: node.tpdo[n] or node.rpdo[n]

2nd: node.pdo.tx[n] or node.pdo.rx[n]

3rd: node.pdo[0x1A00] or node.pdo[0x1600]

The n is the PDO index (normally 1 to 4). The second form of access is for backward compatibility.

import canopen

# Start with creating a network representing one CAN bus
network = canopen.Network()

# Add some nodes with corresponding Object Dictionaries
node = canopen.RemoteNode(6, '/path/to/object_dictionary.eds')
network.add_node(node)

# Connect to the CAN bus
# Arguments are passed to python-can's can.Bus() constructor
# (see https://python-can.readthedocs.io/en/latest/bus.html).
network.connect()
# network.connect(interface='socketcan', channel='can0')
# network.connect(interface='kvaser', channel=0, bitrate=250000)
# network.connect(interface='pcan', channel='PCAN_USBBUS1', bitrate=250000)
# network.connect(interface='ixxat', channel=0, bitrate=250000)
# network.connect(interface='vector', app_name='CANalyzer', channel=0, bitrate=250000)
# network.connect(interface='nican', channel='CAN0', bitrate=250000)

# Read a variable using SDO
device_name = node.sdo['Manufacturer device name'].raw
vendor_id = node.sdo[0x1018][1].raw

# Write a variable using SDO
node.sdo['Producer heartbeat time'].raw = 1000

# Read PDO configuration from node
node.tpdo.read()
node.rpdo.read()
# Re-map TPDO[1]
node.tpdo[1].clear()
node.tpdo[1].add_variable('Statusword')
node.tpdo[1].add_variable('Velocity actual value')
node.tpdo[1].add_variable('Some group', 'Some subindex')
node.tpdo[1].trans_type = 254
node.tpdo[1].event_timer = 10
node.tpdo[1].enabled = True
# Save new PDO configuration to node
node.tpdo[1].save()

# Transmit SYNC every 100 ms
network.sync.start(0.1)

# Change state to operational (NMT start)
node.nmt.state = 'OPERATIONAL'

# Read a value from TPDO[1]
node.tpdo[1].wait_for_reception()
speed = node.tpdo[1]['Velocity actual value'].phys
val = node.tpdo['Some group.Some subindex'].raw

# Disconnect from CAN bus
network.sync.stop()
network.disconnect()

Debugging

If you need to see what's going on in better detail, you can increase the logging level:

import logging
logging.basicConfig(level=logging.DEBUG)

canopen's People

Contributors

acolomb avatar af-silva avatar allesblinkt avatar christiansandberg avatar comkieffer avatar erlend-aasland avatar fredrikhoyer avatar friederschueler avatar gsulc avatar henrikbrixandersen avatar luminize avatar marcogario avatar mbuijs avatar meifonglow avatar paoloteti avatar racerep avatar samsamfire avatar sandyman avatar semiversus avatar sorki avatar sudlav avatar sveinse avatar tuwuhs avatar unsanded avatar uwasmuth avatar vongostev avatar walmis avatar wodz avatar yegorich avatar ymkim92 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

canopen's Issues

How to send PDO3_RX with payload?

I need to get a bit more familiar with canopen API to translate my old code. I need to run a PDO3_RX against a node "to_node_id" and i am wondering how i am going to do this with canopen and python. How can i send a PDO3_RX with payload is my first question. The second question is how i register a handler to listen for a response i am expecting.

Below is how the PDO3 request was build in my old code. Any help is highly appreciated. Thanks and kind regards

frame->function_code = CANOPEN_FC_PDO3_RX; //0x08 << 7 = 0x400
frame->rtr = 0;
frame->data_len = 8;
frame->payload.data[0] = 0x80 | (to_node_id & 0x7F); //SDO request with server node_id
frame->payload.data[1] = action; //00
frame->payload.data[2] = 0x1f; //1F
frame->payload.data[3] = 0x00; //subindex 0x00
frame->payload.data[4] = 0x00 | (to_node_id & 0x7F); //server
frame->payload.data[5] = 0x00 | (from_node_id & 0x7F); //client
frame->payload.data[6] = 0x80;
frame->payload.data[7] = 0x12;

canopen_frame_send(sock, frame);
canopen_frame_free(frame);

Request: Configurable SDO timeout or network enumeration feature

We use the following code to enumerate CANOpen devices on the network

network = range(1,128)
enumerated_devices = []
for id, p in enumerate(network):
    try:
        node = network[id]
        node.nmt.state = 'PRE-OPERATIONAL'
        dtype = node.sdo.upload(0x1000, 0)
        if id not in self.enumerated_pucks:
            enumerated_devices.append(id)
    except Exception as e:
        pass

# Do stuff with enumerated_devices

The current timeout makes this process rather slow. How would you advice we enumerate the network faster?

In an earlier version, I changed sdo.py to only retry 1, and set the timeout to 0.1 seconds, which was good enough for testing. However, we'd like to do it the correct way.

Error cleaner TPDO

I'm trying to implement a TPDO2 that will be called periodically every 5s and send a value, but when I start pdo.tx [2] I get this error:

# python commTest.py 
Creating object CanOpen
Read .eds and create node
Connecting socketCan with CanOpen
Init TPDO2

Traceback (most recent call last):
  File "commTest.py", line 25, in <module>
    node.pdo.tx[2].clear()
  File "/usr/lib/python2.7/site-packages/canopen/pdo.py", line 135, in __getitem__
    return self.maps[key]
KeyError: 2

Code:

import canopen
import sys
import struct


print("Creating object CanOpen")
network = canopen.Network()

print("Read .eds and create node")
node = network.add_node(1, 'model.eds')

print("Connecting socketCan with CanOpen")
network.connect(bustype='socketcan', channel='can0')

print("Init TPDO2")
node.pdo.read()
node.pdo.tx[2].clear()

The idea is a TPDO2 that the function will be executed every 5s, based on COB-ID 0x283

canopen version 0.5.0.dev5(db5f1d4)

how to use a modified version of python-can

Hey Christian,

Really great project! I do have a question: Is there a way to install python-can so that I can modify it and canpoen use that modified version.

many thanks

SDO-Server

Hello,

Is it possible to use the canopen library as a sdo server? I'm trying to build a simulator for a canopen hardware and as far as I've seen it's only possible to use as sdo client.

Kind regards,
Sascha

canopen.sdo.SdoCommunicationError: No SDO response received

Hi!
I'm trying to start with your canopen python library, and I even can't make examples from git work without errors. :(

My code is a copy-paste one from example:

import canopen

# Start with creating a network representing one CAN bus
network = canopen.Network()

# Add some nodes with corresponding Object Dictionaries
node = network.add_node(6, 'd:\\MyDocs\\Libs\\py\\_work\\canopen-master\\test\\sample.eds')
network.add_node(7, 'd:\\MyDocs\\Libs\\py\\_work\\canopen-master\\test\\sample.eds')

# Connect to the CAN bus
# Arguments are passed to python-can's can.interface.Bus() constructor
# (see https://python-can.readthedocs.io/en/latest/bus.html).
#network.connect(bustype='socketcan', channel='can0')
# network.connect(bustype='kvaser', channel=0, bitrate=250000)
# network.connect(bustype='pcan', channel='PCAN_USBBUS1', bitrate=250000)
network.connect(bustype='virtual', channel=0, bitrate=250000, can_filters = None)
# network.connect(bustype='vector', app_name='CANalyzer', channel=0, bitrate=250000)
# network.connect(bustype='nican', channel='CAN0', bitrate=250000)

#network.scanner.search()

# Read a variable using SDO
device_name = node.sdo['Manufacturer device name'].raw
vendor_id = node.sdo[0x1018][1].raw

# Write a variable using SDO
node.sdo['Producer heartbeat time'].raw = 1000

# Read PDO configuration from node
node.pdo.read()
# Re-map TxPDO1
node.pdo.tx[1].clear()
node.pdo.tx[1].add_variable('Application Status', 'Status All')
node.pdo.tx[1].add_variable('Application Status', 'Actual Speed')
node.pdo.tx[1].trans_type = 254
node.pdo.tx[1].event_timer = 10
node.pdo.tx[1].enabled = True
# Save new PDO configuration to node
node.pdo.save()

# Transmit SYNC every 100 ms
network.sync.start(0.1)

# Change state to operational (NMT start)
node.nmt.state = 'OPERATIONAL'

# Read a value from TxPDO1
node.pdo.tx[1].wait_for_reception()
speed = node.pdo.tx[1]['Application Status.Actual Speed'].phys

# Disconnect from CAN bus
network.sync.stop()
network.disconnect()

eds file used in code I've got from canopen-master\test
And here is what a interpreter prints to console after runnig script

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "D:\Tools\WinPython-2.7.6.4\python-2.7.6\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 540, in runfile
    execfile(filename, namespace)
  File "D:/MyDocs/SDBCS/_Trash/CAN/can_first_steps.py", line 30, in <module>
    device_name = node.sdo['Manufacturer device name'].raw
  File "D:\Tools\WinPython-2.7.6.4\python-2.7.6\lib\site-packages\canopen\common.py", line 64, in raw
    value = self.od.decode_raw(self.data)
  File "D:\Tools\WinPython-2.7.6.4\python-2.7.6\lib\site-packages\canopen\common.py", line 24, in data
    return self.get_data()
  File "D:\Tools\WinPython-2.7.6.4\python-2.7.6\lib\site-packages\canopen\sdo.py", line 240, in get_data
    return self.sdo_node.upload(self.od.index, self.od.subindex)
  File "D:\Tools\WinPython-2.7.6.4\python-2.7.6\lib\site-packages\canopen\sdo.py", line 150, in upload
    with ReadableStream(self, index, subindex) as fp:
  File "D:\Tools\WinPython-2.7.6.4\python-2.7.6\lib\site-packages\canopen\sdo.py", line 369, in __init__
    response = sdo_client.request_response(request)
  File "D:\Tools\WinPython-2.7.6.4\python-2.7.6\lib\site-packages\canopen\sdo.py", line 118, in request_response
    return self.read_response()
  File "D:\Tools\WinPython-2.7.6.4\python-2.7.6\lib\site-packages\canopen\sdo.py", line 102, in read_response
    raise SdoCommunicationError("No SDO response received")
canopen.sdo.SdoCommunicationError: No SDO response received

The same errors I've got when used ixaat usb-to-can II module and changed a code to

network.connect(bustype='ixaat', channel=0, bitrate=250000, can_filters = None)

What am I doing wrong?

Novice question

Hi:
I am student who is learning CANopen
Now i am trying to implement your code on raspberry and controlling an electronic car.
The system goes well when i sent NMT and SYNC command
but when a try to Read a variable using SDO
I have put the eds document into folder named objectdictionary
I received error like that
Could please advice me what mistake i might make.

Traceback (most recent call last):
File "", line 1, in
File "/home/pi/canopen-master/canopen/sdo.py", line 155, in getitem
entry = self.od[index]
File "/home/pi/canopen-master/canopen/objectdictionary/init.py", line 66, in getitem
return self.names.get(index) or self.indices[index]
KeyError: 8197

Regards,

Siqi

Question - Object Dictionary, Ingenia Motion Drive

Hello,
I am looking to work with a servo drive from Ingenia motion control with CANopen. I have been able to put the drive into 'OPERATIONAL' mode and the PDOs are present on the Bus when i move the motor. (I have been decoding them with a picoscope).... also from Can-utils i am able to do a Candump, so i know data is able to come through my beaglebone.

Ingenia has an object dictionary available for download, and i am using this. i am quite sure my issue is down to the fact i've just started to learn this / don't have full application understanding, so i will be very greatfull for a kick in the right direction !

I keep getting traceback results saying "was not found in object dictionary"

Traceback (most recent call last):
  File "HelloCan.py", line 7, in <module>
    device_name = node.sdo['VendorName'].raw
  File "/usr/local/lib/python2.7/dist-packages/canopen/sdo.py", line 176, in __getitem__
    entry = self.od[index]
  File "/usr/local/lib/python2.7/dist-packages/canopen/objectdictionary/__init__.py", line 61, in __getitem__
    raise KeyError("%s was not found in Object Dictionary" % name)
KeyError: 'VendorName was not found in Object Dictionary'
Exception in thread can.notifier (most likely raised during interpreter shutdown):
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
  File "/usr/lib/python2.7/threading.py", line 763, in run
  File "/usr/local/lib/python2.7/dist-packages/can/notifier.py", line 41, in rx_thread
  File "/usr/local/lib/python2.7/dist-packages/can/interfaces/socketcan/socketcan_ctypes.py", line 98, in recv
<type 'exceptions.AttributeError'>: 'NoneType' object has no attribute 'debug'

The program i have been using is below..... but this has now become a mess with my trying different things. I must have communication estabilished as i am able to put the drive into the OPERATIONAL state

import canopen
network = canopen.Network()
network.connect(channel='can0' , bustype='socketcan')
node = network.add_node(20, 'object_dictionary.eds')
network.add_node(7, 'object_dictionary.eds')
network.nmt.state = 'OPERATIONAL'
device_name = node.sdo['VendorName'].raw
VendorID = node.sdo[0x1018][1].raw
#node.sdo['Producer heartbeat time'].raw = 1000

node.pdo.read()
node.pdo.tx[3].clear()
node.pdo.tx[3].add_variable('Application Status', 'Status All')
node.pdo.tx[3].add_variable('Application Status', 'Position actual value')
node.pdo.tx[3].trans_type = 254
node.pdo.tx[3].event_timer = 10
node.pdo.tx[3].enabled = True

#node.pdo.rx[4].clear()
#node.pdo.rx[4].add_variable('Application Status', 'Command All')
#node.pdo.rx[4].add_variable('Application Status', 'Command Speed')
#node.pdo.rx[4].enable = True

network.nmt.state = 'PRE-OPERATIONAL'
node.pdo.save()
node.pdo.export('database.dbc')
network.nmt.state = 'OPERATIONAL'
node.pdo.rx[3]['Application Commands.Target position'].phys = 1000
node.pdo.rx[3].start(0.1)
#node.pdo.state = 'OPERATIONAL'
with open('output.txt', 'w') as f:
        for i in range(50):
                node.pdo.tx[3].wait_for_reception()
                speed = node.pdo['Application Status.Actual Speed'].phys
                f.write('%s\n' % speed)
#def print_speed(message):
#       print('%s recived' %(var.name, var.raw))
node.pdo.tx[3].add_callback(print_speed)
time.sleep(5)
node.pdo.rx[3].stop()

network.disconnect()

a sample of the .eds file i am using is below, and i assume when i use the example provided device_name_obj = node.object_dictionary['ManufacturerDeviceName']
vendor_id_obj = node.object_dictionary[0x1018][1]

the fact the ingenia .eds does not have 'ManufacturerDeviceName' in the file is my issue ?
I have been trying lots of different things.... like 'VendorName' as this is in the file. but still i am doing something wrong

[FileInfo]
FileName=0x19_0x29C_0x127
FileVersion=1
FileRevision=28
EDSVersion=402
Description=EDS for emcl chip
CreationTime=10:06AM
CreationDate=04-23-2013
CreatedBy=Ingenia Motion Control
ModificationTime=12:34AM
ModificationDate=06-14-2017
ModifiedBy=Ingenia Motion Control

[DeviceInfo]
VendorName=Ingenia Motion Control
VendorNumber=668
ProductName=emcl
ProductNumber=25
RevisionNumber=295
OrderCode=25
Baudrate_10=1
Baudrate_20=1
Baudrate_50=1
Baudrate_125=1
Baudrate_250=1
Baudrate_500=1
Baudrate_800=0
Baudrate_1000=1
SimpleBootUpMaster=0
SimpleBootUpSlave=1
Granularity=8
DynamicChannelsSupported=0
GroupMessaging=0
NrOfRXPDO=4
NrOfTXPDO=4
LSS_Supported=1

[MandatoryObjects]
SupportedObjects=3
1=0x1000
2=0x1001
3=0x1018

[1000]
ParameterName=Device Type
ObjectType=0x7
DataType=0x0007
AccessType=ro
DefaultValue=0x20192
PDOMapping=0x0

[1001]
ParameterName=Error Register
ObjectType=0x7
DataType=0x0005
AccessType=ro
PDOMapping=0x0

[1018]
SubNumber=0x5
ParameterName=Identity Object
ObjectType=0x9

[1018sub0]
ParameterName=Number of Entries
ObjectType=0x7
DataType=0x0005
AccessType=const
DefaultValue=0x4
PDOMapping=0x0

[1018sub1]
ParameterName=VendorID
ObjectType=0x7
DataType=0x0007
AccessType=ro
DefaultValue=0x29C
PDOMapping=0x0

Provide optional counter parameter in SYNC messages

Thanks so much for this library! It's exactly what we needed for the project I'm working on!

According to the spec, SYNC messages can have an optional counter parameter:

The optional parameter counter shall be incremented by 1 with every transmission. The maximum value shall be the current value as defined in the synchronous counter overflow value (see sub-clause 7.5.2.22). In case the maximum value is reached the counter shall be set to 1 with the next transmission. The initial value of the counter after the NMT service boot-up shall be 1. The value of the counter shall be reset to 1 if the CANopen device transits from the NMT state stopped into the NMT state pre-operational or into the NMT state operational.

When writing tests against a device, it would be handy to be able to provide this count value.

A good first step would be to be able to provide it in the transmit() call: network.sync.transmit(42).

Full support would involve maintaining a count value, resetting it when necessary, and wrapping according to the overflow value, then sending it with each SYNC after using network.sync.start(0.1).

For now, I've implemented a workaround in my project with network.send_message(0x80, bytes([count])), and that works fine, but wondering if it would be better to have it built into the library.

strange problem with sdo transfers

Here is my session with corresponding candump to see what is put on the wire:

l.network = canopen.Network()
l.network.connect(channel='can0', bustype='socketcan', bitrate=100000)
l..node = self.network.add_node(id, 'LPCBootrom.eds')

#unlock
l.node.sdo[0x5000].raw = 0x5a5a
#can0 67D [8] 2B 00 50 00 5A 5A 00 00
#can0 5FD [8] 60 00 50 00 00 00 00 00

#prepare sectors 0 7
l.node.sdo[0x5020].raw = 0x0700
#can0 67D [8] 2B 20 50 00 00 07 00 00
#can0 5FD [8] 60 20 50 00 00 00 00 00

#erase sector 0 7
l.node.sdo[0x5030].raw = 0x0700
#can0 67D [8] 2B 30 50 00 00 07 00 00
#can0 67D [8] 2B 30 50 00 00 07 00 00
#can0 5FD [8] 60 30 50 00 00 00 00 00
#can0 5FD [8] 80 30 50 00 09 00 00 0F

Now, objects 0x5020 and 0x5030 are defined exactly the same in EDS but in the second case transfer is performed twice. Why? The second transfer fails (with custom error code thanks to NXP) as write to 0x5030 must be preceded by write to 0x5020.

LPCBootrom.eds.txt

RPDO for multiple devices

Hello,

I apologize if this isn't the right place to ask this, as I'm not sure it counts as an "issue".

I'm attempting to synchronize to two Allied Motion motors via RPDO messages. I've successfully managed to get them all to transmit PDO messages on sync broadcasts, but I can't even get a single one to respond to PDO messages (Which I think I'm sending using alliedmotor1.pdo.rx[4]['EN'].raw = 1, or enable motor). I'm guessing that I'm doing something wrong, but I can't quite see what.

import canopen
import time

network = canopen.Network()

# network.connect(channel='PCAN_USBBUS1', bustype='pcan', bitrate=125000)
network.connect(bustype='socketcan', channel='can0', bitrate=125000)
# network.nmt.state = 'RESET'
# network.nmt.state = 'OPERATIONAL'
alliedmotor1 = network.add_node(0x01, 'AM_Drive.eds')
alliedmotor5 = network.add_node(0x05, 'AM_Drive.eds')

alliedmotor1.sdo['DCV'].raw = 1
# alliedmotor1.sdo['EN'].raw = 1

alliedmotor5.sdo['DCV'].raw = 1
alliedmotor5.sdo['EN'].raw = 1


#Motor 1 PDO setup
alliedmotor1.pdo.read()
alliedmotor1.pdo.tx[1].clear()
alliedmotor1.pdo.tx[1].add_variable('CV')
alliedmotor1.pdo.tx[1].add_variable('DCV')
alliedmotor1.pdo.tx[1].trans_type = 1
alliedmotor1.pdo.tx[1].enabled = True

alliedmotor1.pdo.rx[1].clear()
alliedmotor1.pdo.rx[1].add_variable('EN')
alliedmotor1.pdo.rx[1].enabled = True

alliedmotor5.pdo.read()
alliedmotor5.pdo.tx[1].clear()
alliedmotor5.pdo.tx[1].add_variable('CV')
alliedmotor5.pdo.tx[1].add_variable('DCV')
alliedmotor5.pdo.tx[1].trans_type = 1
alliedmotor5.pdo.tx[1].enabled = True

network.nmt.state = 'PRE-OPERATIONAL'
alliedmotor1.pdo.save()
alliedmotor5.pdo.save()

network.sync.start(0.1)
alliedmotor1.pdo.rx[4]['EN'].raw = 1
alliedmotor1.pdo.rx[1].start(0.1)
network.nmt.state = 'OPERATIONAL'



for i in range(10):
    alliedmotor5.pdo.tx[1].wait_for_reception()
    print alliedmotor1.pdo.tx[1]['CV'].raw, alliedmotor5.pdo.tx[1]['CV'].raw, \
        alliedmotor1.pdo.tx[1]['DCV'].raw, alliedmotor5.pdo.tx[1]['DCV'].raw

alliedmotor1.sdo['EN'].raw = 0
alliedmotor5.sdo['EN'].raw = 0

network.sync.stop()
network.disconnect()

Bit mapping in PDOs

Hi Christian,

Sorry I'am so annoying, but I have again an Issue.

Bit mapping for PDOs isn't implemented right?
The problem is that the variables are decoded as unsigned integer 8 but used are only 4 bits in the message. i.e.:

Byte 1:
0000 1111
value1 value2

Best regards

sdo on windows

Hi,
I am having hard time with current lib on windows. I tried 0.3 from pip and it worked (having known issues but still). Current git master (as of today) gives error when reading from device. Here is example session:

import canopen
n = canopen.Network()
n.connect(bustype='ixxat', channel=0, bitrate=100000)
node = n.add_node(125, 'my.eds')
node.sdo[0x1000].raw
Traceback (most recent call last):
File "", line 1, in
File "canopen\common.py", line 64, in raw
value = self.od.decode_raw(self.data)
File "canopen\common.py", line 24, in data
return self.get_data()
File "canopen\sdo.py", line 229, in get_data
return self.sdo_node.upload(self.od.index, self.od.subindex)
File "canopen\sdo.py", line 104, in upload
return ReadableStream(self, index, subindex).read()
File "canopen\sdo.py", line 342, in init
response = sdo_client.send_request(request)
File "canopen\sdo.py", line 78, in send_request
raise SdoCommunicationError("No SDO response received")
canopen.sdo.SdoCommunicationError: No SDO response received

Other things I tried seems to work (Network.scanner() returns list of nodes, node.nmt.send_command() does send proper packet). The most annoying thing is that on linux with 'socketcan' driver exactly the same code with exactly the same EDS works. In both cases python-can and python-canopen are the same version.

Any hints welcome

Using "network.scanner.search()" gives an error

Hello. Thanks for bringing CANOpen to Python.
When I run the following code:

#!/usr/bin/env python
import canopen

network = canopen.Network()
network.connect(channel='can0', bustype='socketcan')
network.scanner.search()
network.disconnect()

I get the this error:

Traceback (most recent call last):
  File "can_scan.py", line 6, in <module>
    network.scanner.search()
  File "/home/quad/.local/lib/python2.7/site-packages/canopen/network.py", line 342, in search
    self.network.send_message(0x600 + node_id, sdo_req)
  File "/home/quad/.local/lib/python2.7/site-packages/canopen/network.py", line 167, in send_message
    self.check()
  File "/home/quad/.local/lib/python2.7/site-packages/canopen/network.py", line 209, in check
    exc = self.notifier.exception
AttributeError: 'Notifier' object has no attribute 'exception'

Problem while getting VISIBLE_STRING SDOs

When getting VISIBLE_STRING SDO if this one is correctly ended by a \0 char but not fully filled with \0 decoding generate an error.

I suggest to add these few lines to correct the problem.

diff --git a/canopen/objectdictionary/init.py b/canopen/objectdictionary/init.py
index c05fe7c..ab57d45 100644
--- a/canopen/objectdictionary/init.py
+++ b/canopen/objectdictionary/init.py
@@ -279,8 +279,14 @@ class Variable(object):

 def decode_raw(self, data):
     if self.data_type == VISIBLE_STRING:
  •        endOfString=data.find(0) 
    
  •        if endOfString>0:
    
  •            data=data[:endOfString]
           return data.decode("ascii")
       elif self.data_type == UNICODE_STRING:
    
  •        endOfString=data.find(0) 
    
  •        if endOfString>0:
    
  •            data=data[:endOfString]
           # Is this correct?
           return data.decode("utf_16_le")
       elif self.data_type in self.STRUCT_TYPES:
    

Bug in node without EDS file

When I try to run the following code:

import canopen
network = canopen.Network()
node = network.add_node(45, object_dictionary=None)
network.connect(channel=0, bustype="ixxat", can_filters=None)
node.sdo[0x1018][2].raw
network.disconnect()

I get an error:

No handlers could be found for logger "canopen.objectdictionary.eds"

If I attach your sample.eds, everything works.

I think there's something wrong in eds.py on line 42

  • I'm working with version 0.4.0 from pip
  • tried with 0.5.0.dev1

Difference between PDO and SDO reading of the same index

Hello,

First off, thanks for the speedy pdo.read fix! Once all that was working I came across another issue.

I am having an issue where if I read the value at an index using the sdo I get the expected value but when I try to use synchronous pdo transfers of the same index I get the wrong value.

Do pdo's do anything internally that might effect scaling?

I checked to make sure that no scaling factors have been introduced but I figured if a scaling factor was present it would've scaled the sdo aswell.

Any help is greatly appreciated!

Cheers

New PyPi release

Hey,

Could you release a new PyPi version, as the last version is 0.5.1 which was released in October.

Best regards

"network.disconnect" error

Hello. Running the code below:

#!/usr/bin/env python
import canopen
network = canopen.Network()
network.connect(channel='can0', bustype='socketcan')
network.disconnect()

Gives the following error:

  File "can_test.py", line 21, in <module>
    network.disconnect()
  File "/home/quad/.local/lib/python2.7/site-packages/canopen/network.py", line 111, in disconnect
    self.notifier.stop()
AttributeError: 'Notifier' object has no attribute 'stop'

LSS fastscan, next release

Hi,
at a first glance it looks like LSS support is almost complete (at least in the master branch) with only fastscan missing. Is anyone having a look at it? What's the current plan for the next release?

Thank you!

pdo read returns nil, no map loaded

Hi, first thank you for the package, it saved a lot time dealing with the dictionary manually.

i'm using a device from datexel.it (http://www.datexel.it/products/CANOPEN/DAT7016) to get thermocouple data. according to the datasheet, there is one tpdo from the unit. but after calling the pdo.read() method the pdo.tx or pdo.rx were all empty. I wonder if the tx and rx are supposedly to read from the eds file (object dictionary) or from an sdo command return? i wonder if this is a eds issue or i'm missing something here.

i've got the sdo part to work after implementing the connect/disconnect/send_message with a third party CAN driver.

sorry im new to githut too.. let me know if this is the proper place to post such questions.

regards
gz

SDO block transfer

Hi,
This is an excellent looking library! I wish I knew about this a while ago.

I have the (thrilling) task of rewriting some CAN master software I wrote in C# on Windows to Raspberry Pi running Linux, this project looks perfect.

The product I am writing the software for has a bootloader which is written through SDO block transfer.

So I was wondering whether this can be added into the library?

Cheers!

reset communication in nmt state

Hi Christian,

I hardly use 'RESET COMMUNICATION' state.
But I think if it is 'RESET**-**COMMUNICATION', it is better at my CLI.
'PRE-OPERATIONAL' has '-'. Why not for 'RESET COMMUNICATION'.

Regards,
Young

NodeScanner usage

Thanks for the nice library. I looks clean and organized. I tend to migrate project which makes use of libcanopen to your library and make my first steps.

My first step is a node scanner. However it seems i am doing something wrong in the lines below. The return is allways empty []

Thanks in advance for pointers and best from south germany. BTW can_logger.py is able to listen.

import canopen
import time

network = canopen.Network()
network.connect(channel='can0', bustype='socketcan')
node = network.add_node(6, 'sample.eds')

scanner = canopen.network.NodeScanner(network)
time.sleep(30)
print scanner.nodes

PDO and SDO expected and actual data size

Hi ,
I'm currently working on some motor controller.
I got this error when i try to communicate using the "manufacturer address" :
"Mismatch between expected and actual data size"

But I always dump the can and I can see that the node sends the information I request.

Exemple SDO:
#in my case 0x27d5 is the can address
nodeAdr = node.sdo[0x27d5].raw
"Mismatch between expected and actual data size"

But in the Can dump I can see "584 [8] 42 D5 27 00 01 00 00 00"
so it matches the actual address wich is 1 (in the device) .

Exemple PDO:
when I do a :
node.pdo.read()
"Mismatch between expected and actual data size"
the can dump is :

000 [2] 80 04
604 [8] 40 00 14 01 00 00 00 00
584 [8] 42 00 14 01 04 02 00 00
604 [8] 40 00 14 02 00 00 00 00
584 [8] 42 00 14 02 FE 00 00 00

Thanks for your help.

Problem in network.disconnect() at python 3

Hi,

I found a problem while running network.disconnect at python 3.
The message is like this:

Traceback (most recent call last):
  File ".\CalibrationReader.py", line 75, in <module>
    network.disconnect()
  File "C:\Python36\lib\site-packages\canopen\network.py", line 110, in disconnect
    node.pdo.stop()
  File "C:\Python36\lib\site-packages\canopen\pdo.py", line 113, in stop
    pdo_map.stop()
  File "C:\Python36\lib\site-packages\canopen\pdo.py", line 364, in stop
    self._task.stop()
AttributeError: 'NoneType' object has no attribute 'stop'

I don't know why this error doesn't happen in python 2.
Anyway I think we should change stop method something like this at pdo.py: ::

  FROM
    def stop(self):
        """Stop transmission."""
        self._task.stop()
        self._task = None

  TO
    def stop(self):
        """Stop transmission."""
        if self._task is not None:
            self._task.stop()
            self._task = None

PDO COB-ID DefaultValue issue

Hi.

Thanks for this great python canopen implementation.
I am using the EDS import function of python canopen to autogenerate C code for a canopen stack.

I have encountered a small issue in this regard.


[1401sub1]
ParameterName=COB ID
ObjectType=0x7
DataType=0x0007
AccessType=rw
DefaultValue=$NODEID+0x300
PDOMapping=0
LowLimit=0x00000001
HighLimit=0xFFFFFFFF

For all PDO configurations the COB-ID Default value looks like above DefaultValue=$NODEID+0x300 (generated by VectorEds)
But it seems the line var.default = int(eds.get(section, "DefaultValue"), 0) in eds.py cannot handle this $NODEID+ syntax and simply sets it to zero.

If I remove $NODEID+ in the eds I get a warnings from VectorEds that this differs from standard value.

Any suggestions on how to solve this?

My suggestion:

  1. Extract DefaultValue as a string
  2. Evaluate for $NODEID+ and remove it
  3. Convert to int and use as it is done now.

What do you think? (I don't think the $NODEID+ is used for anything in the master, It is just an indication of behavior shown in the EDS file)

Update number of unused bytes in last SDO segment

When trying to perform a SDO segmented download to one of our devices the transfer fails when the data size is not a multiple of 7.

This is due to the client indicating the size of the complete transfer and the server verifying the total number of bytes received after receiving the last segment. When the last segment is received the server interprets n=0b000 as the segment containing 7 bytes of data and thus will fail the transfer due to a mismatch between received and expected.

CAN data from server not datatype of eds, results in type mismatch (or wrong data).

Hi,

It seems that our CAN server (Curtis motor driver) does not reply with bytes in the datatype defined in the eds.

eg: motor_rpm is defined as Int16 in the eds, but we receive b'\xAA\xFF\x00'. This results in "Mismatch between expected and actual data size". If I change to a bigger int we get the unsigned value instead of the signed one (as expected).

How would I go about fixing this given that we cannot change what the CAN server sends, only what is defined in the eds and this drivers code?

I have also noticed that unpack cannot handle extra zero bytes (\x00), but unpack_from (without offset) ignores the extra (\x00) bytes and displays the value correctly.

up = struct.unpack('h', b'\xAA\xFF')
print(up[0]) #successful

up1 = struct.unpack('h', b'\xAA\xFF\x00\x00')
print(up1[0]) #struct.error: unpack requires a bytes object of length 2

up2 = struct.unpack_from('h', b'\xAA\xFF\x00')
print(up2[0]) #successful

I will test using unpack_from instead of unpack in the canopen driver next week but I thought I would ask you for your opinion in the meanwhile.

Thanks in advance!

Kind regards
Tinus

No SDO Repsonse Received

Hello,

First off, thank you for creating this CANopen library! This has helped me greatly. I am, however, running into an issue with access data from the Moog SmartMotor that I am currently using.

The current program I am running is as follows:

import canopen
from canopen.profiles.p402 import Node402
import logging
import time
import pprint

logging.basicConfig(level=logging.DEBUG)
node = canopen.Node402(8, './SM5_0V3R4.eds')
network = canopen.Network()
network.add_node(node)
network.connect(bustype='socketcan', channel='can0', can_filters=None)

node.setup_402_state_machine()
node.sdo[0x6040].raw = 0x06
node.sdo[0x6041].raw

The error message (with debug) is:

DEBUG:can:can config: {'interface': 'socketcan_native', 'channel': 'can0'}
INFO:can.socketcan.ctypes:Loading socketcan ctypes backend
INFO:can.socketcan.ctypes:Loading libc with ctypes
INFO:can.socketcan.native:Loading socketcan native backend
INFO:can.socketcan.native:Created a socket
DEBUG:can.socketcan.native:Binding socket to channel=can0
DEBUG:can.socketcan.native:Bound socket.
INFO:canopen.network:Connected to 'native socketcan channel 'can0''
INITIALISING
INFO:canopen.nmt:Sending NMT command 0x80 to node 8
DEBUG:can.socketcan.native:We've been asked to write a message to the bus
DEBUG:can.socketcan.native.tx:sending: Timestamp:        0.000000        ID: 0000    S          DLC: 2    80 08
INFO:canopen.nmt:Changing NMT state to PRE-OPERATIONAL
DEBUG:canopen.sdo:Reading 0x1800:1 from node 8
DEBUG:can.socketcan.native:We've been asked to write a message to the bus
DEBUG:can.socketcan.native.tx:sending: Timestamp:        0.000000        ID: 0608    S          DLC: 8    40 00 18 01 00 00 00 00
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/canopen/sdo.py", line 100, in read_response
    block=True, timeout=self.RESPONSE_TIMEOUT)
  File "/usr/lib64/python3.6/queue.py", line 172, in get
    raise Empty
queue.Empty

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "test_canopen.py", line 13, in <module>
    node.setup_402_state_machine()
  File "/usr/local/lib/python3.6/site-packages/canopen/profiles/p402.py", line 57, in setup_402_state_machine
    self.pdo.tx[1].read()
  File "/usr/local/lib/python3.6/site-packages/canopen/pdo.py", line 238, in read
    cob_id = self.com_record[1].raw
  File "/usr/local/lib/python3.6/site-packages/canopen/common.py", line 64, in raw
    value = self.od.decode_raw(self.data)
  File "/usr/local/lib/python3.6/site-packages/canopen/common.py", line 24, in data
    return self.get_data()
  File "/usr/local/lib/python3.6/site-packages/canopen/sdo.py", line 240, in get_data
    return self.sdo_node.upload(self.od.index, self.od.subindex)
  File "/usr/local/lib/python3.6/site-packages/canopen/sdo.py", line 150, in upload
    with ReadableStream(self, index, subindex) as fp:
  File "/usr/local/lib/python3.6/site-packages/canopen/sdo.py", line 369, in __init__
    response = sdo_client.request_response(request)
  File "/usr/local/lib/python3.6/site-packages/canopen/sdo.py", line 118, in request_response
    return self.read_response()
  File "/usr/local/lib/python3.6/site-packages/canopen/sdo.py", line 102, in read_response
    raise SdoCommunicationError("No SDO response received")
canopen.sdo.SdoCommunicationError: No SDO response received

The EDS file I am using can be found here

I have tried this both with and without the 402 profile so this is not the issue. The hardware setup is a SmartMotor connected to a Microchip CAN Bus Analyzer. At one point it seemed as if I was getting responses but all of a sudden I keep getting this error message. Also, this happens any time I run node.sdo[0x1000].raw . Any advice would be MUCH appreciated, thank you!

402 device profile

Hi @christiansandberg
First, thank you for sharing this repo. I hope it makes life a bit easier.

I've been using python-can in a machine setup for approx a year, and i've hacked my way around getting my devices into different modes.

I'm using CANOpen motors with a CiA 402 profile (drioves and motion control). These motors are ultimately put in step/dir mode so that the Machinekit stack can drive the motors.

Since you've already laid down a framework I'm looking if extending the canopen library with functionality for writing the Power State engine of these profiles.

Would this be something that fits this library?

a side question:
What would be the best way for me to upload and download SDO messages without an Object Dictionary. I don't have the bytearray data, but instead the index, subindex and value.
for example, I would like to set a value to 0x6041, subindex 0, value 0x06. I'd like to reuse code to convert these to the bytearray which I can then use like nw.nodes[3].sdo.download(0x6041,0,0x06)

Cheers

Reading OD entries that are not 32 bits results in unpack error

I've just started testing out this library for a consulting project. It looks really nice! I've found what I'm pretty sure is a bug.

Problem
I have a CANOpen device with an OD Entry of type I8. When I try to read it from python, I get an unpack error.

Analysis of Problem
It appears that SDO_STRUCT defined on line 14 of sdo.py is hard coded to expect 8 byte SDO responses. I don't have a PR yet, because I wanted to ask about it first.

Proposed Solution
A dictionary of structs for different sized OD entries might be good enough solution. We could then raise an ObjectDictionaryError: Mismatch between expected and actual data size, as currently done when the device sends a 8 byte response, but the python side expects a smaller response.

Traceback (most recent call last):
  File "C:\Users\ig\canopen-science.py", line 35, in <module>
    print "Mode: {0}".format(device_mode.raw)
  File "C:\Python27\lib\site-packages\canopen\common.py", line 64, in raw
    value = self.od.decode_raw(self.data)
  File "C:\Python27\lib\site-packages\canopen\common.py", line 24, in data
    return self.get_data()
  File "C:\Python27\lib\site-packages\canopen\sdo.py", line 242, in get_data
    return self.sdo_node.upload(self.od.index, self.od.subindex)
  File "C:\Python27\lib\site-packages\canopen\sdo.py", line 89, in upload
    response)
error: unpack requires a string argument of length 8

[Q] Novice problem and question

Hello @christiansandberg

I have started recently to read about CanOpen and wanted to test. Which is when I found your repository.

I have been tried to read the heartbeat value, but unfortunately I am not capable of doing it..

The code is the next one (very similar to the example):

    # Start with creating a network representing one CAN bus
    network = canopen.Network()

    # Connect to the CAN bus
    network.connect(bustype='socketcan', channel='can0')

    # Add some nodes with corresponding Object Dictionaries
    node = network.add_node(7, '/home/mlupoiu/Documents/workspace/CANopenTest/bin/object_dictionarys/CANopenSocket.eds')

    node.nmt.state = 'OPERATIONAL'

    print node.object_dictionary[0x1017].name

    # Read a variable using SDO
    heartbeat = node.sdo[0x1017]
    print "The heartbeat is 0x%X" % heartbeat.raw

    # Write a variable using SDO
    #node.sdo['Producer heartbeat time'].raw = 1000

    # Disconnect from CAN bus
    network.disconnect()

I am capable of reading the heartbeat name, but wen I try to read the value i get the next error:

Producer heartbeat time
Traceback (most recent call last):
  File "./src/simple_example.py", line 57, in <module>
    main()
  File "./src/simple_example.py", line 27, in main
    print "The heartbeat is 0x%X" % heartbeat.raw
  File "/home/mlupoiu/Documents/workspace/CANopenTest/external_lib/canopen/canopen/common.py", line 64, in raw
    value = self.od.decode_raw(self.data)
  File "/home/mlupoiu/Documents/workspace/CANopenTest/external_lib/canopen/canopen/common.py", line 24, in data
    return self.get_data()
  File "/home/mlupoiu/Documents/workspace/CANopenTest/external_lib/canopen/canopen/sdo.py", line 199, in get_data
    return self.sdo_node.upload(self.od.index, self.od.subindex)
  File "/home/mlupoiu/Documents/workspace/CANopenTest/external_lib/canopen/canopen/sdo.py", line 109, in upload
    with ReadableStream(self, index, subindex) as fp:
  File "/home/mlupoiu/Documents/workspace/CANopenTest/external_lib/canopen/canopen/sdo.py", line 311, in __init__
    response = sdo_client.send_request(request)
  File "/home/mlupoiu/Documents/workspace/CANopenTest/external_lib/canopen/canopen/sdo.py", line 83, in send_request
    raise SdoCommunicationError("No SDO response received")
canopen.sdo.SdoCommunicationError: No SDO response received

And with candump I see the Bootup message and the SDO request, but I don't receive any response. I don't know if I am missing something... CANopenSocket.eds.txt

And if i want to communicate with other nodes that are not created in python? I noticed that with node.scanner we can scan connected nodes to the network, but is it posible to send SDO messages to them?
For example I have used the CANopenSocket to create a node, but did not saw any mechanism to send a message to it without using send_message(can_id, data, remote=False) which is a raw CAN message.

Thank you in advance!

Best regards,
Mihai A. Lupoiu

SDO segment upload returns trailing bytes

Consider this code:

d = node.sdo[0x2003][1].data
d
bytearray(b'\xff\xff\xff\xff\x00\x00\x00')
len(d)
7

Dump from candump:
can0 67D [8] 40 03 20 01 00 00 00 00
can0 5FD [8] 40 03 20 01 00 00 00 00
can0 67D [8] 60 00 00 00 00 00 00 00
can0 5FD [8] 07 FF FF FF FF 00 00 00

Upload segment response from the server indicates that:
a) There are 3 trailing bytes to be omitted
b) No more segment data

According to this the only valid data returned are 0xff 0xff 0xff 0xff. So I would expect this to be reflected in returned bytearray(b'\xff\xff\xff\xff') of len == 4 in this case.

The code for segmented upload seems to check number of trailing bytes and cut it off so I don't understand where it comes from.

sdo upload

Hi again,

the last thing i need is to find the equivalent to this expedited sdo upload.

canopen_sdo_upload_exp(sock, cob_id, 0x1018, 0x01, &vendor);

My translation of the call above is this below. However i am not sure if it is a good idea to instantiate add_node with a cob_id. The flow i need to follow to is to get a cob_id with to_node_id, then doing the sdo uploads against (cob_id, index, subindex) and then deregister the cob_id again. I am not using the dictionary here. I just have it in to avoid complaints.

node = network.add_node(cob_id, 'sample.eds')
vendor_id = node.sdo[0x1018][0x01]

print vendor_id.raw

I can observe it is repeating in doing the SDO (looks correct to be) and getting a response back from.
cob-id: 6C, from_node_id: 2C, to_node_id: 0x01

can0 66C [8] 40 18 10 01 00 00 00 00
can0 5EC [8] 43 18 10 01 CB 00 00 00
can0 66C [8] 40 18 10 01 00 00 00 00
can0 5EC [8] 43 18 10 01 CB 00 00 00
can0 66C [8] 40 18 10 01 00 00 00 00

It looks like the filter for the response does not match what is on the wire. Below is the thrown error.
Thanks and kind regards again.

Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
self.run()
File "/usr/lib/python2.7/threading.py", line 763, in run
self.__target(*self.__args, **self.__kwargs)
File "/usr/local/lib/python2.7/dist-packages/can/notifier.py", line 42, in rx_thread
callback(msg)
File "/usr/local/lib/python2.7/dist-packages/can/CAN.py", line 47, in call
return self.on_message_received(msg)
File "/usr/local/lib/python2.7/dist-packages/canopen/network.py", line 206, in on_message_received
self.network.notify(msg.arbitration_id, msg.data, msg.timestamp)
File "/usr/local/lib/python2.7/dist-packages/canopen/network.py", line 171, in notify
callback(can_id, data, timestamp)
File "scan_canbus.py", line 14, in check_model
print vendor_id.raw
File "/usr/local/lib/python2.7/dist-packages/canopen/common.py", line 64, in raw
value = self.od.decode_raw(self.data)
File "/usr/local/lib/python2.7/dist-packages/canopen/common.py", line 24, in data
return self.get_data()
File "/usr/local/lib/python2.7/dist-packages/canopen/sdo.py", line 219, in get_data
return self.sdo_node.upload(self.od.index, self.od.subindex)
File "/usr/local/lib/python2.7/dist-packages/canopen/sdo.py", line 94, in upload
return ReadableStream(self, index, subindex).read()
File "/usr/local/lib/python2.7/dist-packages/canopen/sdo.py", line 331, in init
response = sdo_client.send_request(request)
File "/usr/local/lib/python2.7/dist-packages/canopen/sdo.py", line 70, in send_request
raise SdoCommunicationError("No SDO response received")
SdoCommunicationError: No SDO response received

test_PDO error

Getting a following error when running python setup.py test. This only fires when logging is set to DEBUG and Variable.set_data tries to log a message referencing self.msg.cob_id which is None.

======================================================================
ERROR: test_bit_mapping (test_pdo.TestPDO)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/rmarko/git/canopen/test/test_pdo.py", line 20, in test_bit_mapping
    map['INTEGER16 value'].raw = -3
  File "/home/rmarko/git/canopen/canopen/common.py", line 78, in raw
    self.data = self.od.encode_raw(value)
  File "/home/rmarko/git/canopen/canopen/common.py", line 30, in data
    self.set_data(data)
  File "/home/rmarko/git/canopen/canopen/pdo.py", line 437, in set_data
    self.name, binascii.hexlify(data), self.msg.cob_id)
  File "/usr/lib64/python2.7/logging/__init__.py", line 1155, in debug
    self._log(DEBUG, msg, args, **kwargs)
  File "/usr/lib64/python2.7/logging/__init__.py", line 1286, in _log
    self.handle(record)
  File "/usr/lib64/python2.7/logging/__init__.py", line 1296, in handle
    self.callHandlers(record)
  File "/usr/lib64/python2.7/logging/__init__.py", line 1336, in callHandlers
    hdlr.handle(record)
  File "/usr/lib64/python2.7/logging/__init__.py", line 759, in handle
    self.emit(record)
  File "/usr/lib/python2.7/site-packages/nose/plugins/logcapture.py", line 82, in emit
    self.buffer.append(self.format(record))
  File "/usr/lib64/python2.7/logging/__init__.py", line 734, in format
    return fmt.format(record)
  File "/usr/lib64/python2.7/logging/__init__.py", line 465, in format
    record.message = record.getMessage()
  File "/usr/lib64/python2.7/logging/__init__.py", line 329, in getMessage
    msg = msg % self.args
TypeError: %X format: a number is required, not NoneType

Receiving

Hello Christian,

I'am working in a CANOpen project myself and found your repository. Great work btw!

Its not really an Issue with your code or anything I'am just new to Github and not sure where to put my request.

I would like to implement a thread based receiving (classic client - server based). Therefore no messages will be lost and there is no need to wait for a reception.

Did you consider something like this? Then I could contribute via a branch if you like.

Best regards

Accessing objects not defined in EDS file

Hi again,

i am doing another sdo upload to an index which is not defined in the EDS file.

tag = node.sdo[0x2014][0x01]

The thrown exception looks like a failed lookup in the dictionary. I was able to create partly valid entries into the EDS but got back:

Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
self.run()
File "/usr/lib/python2.7/threading.py", line 763, in run
self.__target(*self.__args, **self.__kwargs)
File "scan_canbus.py", line 34, in getUVRtime_tf
print('%d-%d-%d' %(tag.raw[0], monat.raw[0], jahr.raw[0]))
File "/usr/local/lib/python2.7/dist-packages/canopen/common.py", line 64, in raw
value = self.od.decode_raw(self.data)
File "/usr/local/lib/python2.7/dist-packages/canopen/objectdictionary/init.py", line 268, in decode_raw
"Mismatch between expected and actual data size")
ObjectDictionaryError: Mismatch between expected and actual data size

Is the code my only friend for documentation of EDS?

Thanks in advance and best.

Python 3 change for p402

Hi,

To get the the profiles/p402.py function on_PDO_callback to work in Python 3 I had to change:

for key, value in POWER_STATES_402.iteritems():

to

for key, value in POWER_STATES_402.items():

Cheers! 😄

Unable to configure PDO "KeyError: 1"

Hi,

We are trying to configure the PDO object of a Curtis motor controller.
However after executing:

print(node.pdo.read()) node.pdo.tx[1].clear() node.pdo.tx[1].add_variable(0x1018, 1) node.pdo.tx[1].add_variable('Motor Speed') node.pdo.tx[1].trans_type = 1 node.pdo.tx[1].enabled = True

We receive:

None Traceback (most recent call last): File "driver.py", line 59, in <module> node.pdo.tx[1].clear() File "/usr/local/lib/python3.4/dist-packages/canopen/pdo.py", line 133, in __getitem__ return self.maps[key] KeyError: 1

It seems that no config could be read, which might seem logical because there has not yet been any config made. However, how can we make the config when we cannot access any of the mapping?

Attached you can find the eds used:
os123xes.txt

Thanks in advance!

Kind regards
Tinus

[Q] how can I enable or disable logs?

Hi,

I like this code but I am not good at Python.
I want to enable all logger output or some of modules.
Can you advise me how to do that?

Regards,
Young

Why does Maps use a range value of 32?

Thanks for the framework and putting your time in!

File: pdo.py
Class: Maps
Function: init

Why map_no in range(32)? I would expect 127 as range value.

Kind regards

node.sdo and KeyError

Hi again,

i am using the raw way to do sdo communication using

node = network.add_node(cob_id, edsfile)
datum = node.sdo[0x2497][0x01]

However i get a KeyErrror back. I did assume that with the sdo method i avoid any interaction with the dictionary. I use plenty other indexes which work, but this is the first one which is blocked. Obviously in sdo.py there is a lookup.

Thanks in advance

datum = node.sdo[0x2497][0x01]
File "/usr/local/lib/python2.7/dist-packages/canopen/sdo.py", line 155, in getitem │······
entry = self.od[index] │······
File "/usr/local/lib/python2.7/dist-packages/canopen/objectdictionary/init.py", line 66, in __getitem│······
__ │······
return self.names.get(index) or self.indices[index] │······
KeyError: 9367

Value does not fit in specified type error

Hi,

I need to set a value 0xFF in register 0x6060 by means of an SDO.

my eds shows:

[6060]
ParameterName=Modes of operation
ObjectType=0x7
DataType=0x0002
AccessType=rww
DefaultValue=0x00
PDOMapping=1

I use the following which works fine for the homing mode (0x06):

self.node.sdo['Modes of operation'].raw = 0x06

I get the following error:

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/home/machinekit/canopen/canopen/common.py", line 78, in raw
    self.data = self.od.encode_raw(value)
  File "/home/machinekit/canopen/canopen/objectdictionary/__init__.py", line 320, in encode_raw
    raise ValueError("Value does not fit in specified type")
ValueError: Value does not fit in specified type

Any thought on how can I solve this to that I can send this value via SDO?

Subindex not found when reading pdo

Hi,

I am trying to familiarise myself with CANopen and came across your library (which is great!).

I am trying to read the PDO configurations but I am getting an error that states 'Subindex 5 was not found'.

Are you able to explain what is happening when the PDO configuration is read? And what would the index be that is related to subindex 5?

Thanks!

Slave node support

This is a general issue for adding support for creating slave nodes. This could be used for implementing real nodes on a CANopen network (using e.g. RaspberryPi) or simulating nodes in a test environment.

This will be divided up in smaller subtasks:

  • Split up master and slave functionality (this issue)
  • Some interface for connecting Object Dictionary to actual data
  • SDO server (#20)
  • NMT slave
  • PDO slave
  • SYNC slave
  • EMCY producer

Cannot parse $NODEID

Tried to create a Copley drive node from EDS file, got error when parsing lines with $NODEID literal in it.
Problematic lines (CopleyAmp.eds):

[1200sub1]
ParameterName=SDO COB-ID Client->Server
ObjectType=7
DataType=7
AccessType=RO
PDOMapping=0
DefaultValue=$NODEID+1536
LowLimit=$NODEID+1536
HighLimit=$NODEID+1536

Error:

In [4]: node = network.add_node(6, './CopleyAmp.eds')
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-4-b30d33f7eaa4> in <module>()
----> 1 node = network.add_node(6, './CopleyAmp.eds')

/home/tuwuhs/.local/lib/python2.7/site-packages/canopen/network.pyc in add_node(self, node, object_dictionary)
     87         """
     88         if isinstance(node, int):
---> 89             node = Node(node, object_dictionary)
     90         node.network = self
     91         self.nodes.append(node)

/home/tuwuhs/.local/lib/python2.7/site-packages/canopen/node.pyc in __init__(self, node_id, object_dictionary)
     32 
     33         if object_dictionary:
---> 34             self.set_object_dictionary(object_dictionary)
     35 
     36         self.sdo = SdoClient(self, node_id)

/home/tuwuhs/.local/lib/python2.7/site-packages/canopen/node.pyc in set_object_dictionary(self, object_dictionary)
     63         if not isinstance(object_dictionary,
     64                           objectdictionary.ObjectDictionary):
---> 65             object_dictionary = objectdictionary.import_od(object_dictionary)
     66         self.object_dictionary = object_dictionary
     67 

/home/tuwuhs/.local/lib/python2.7/site-packages/canopen/objectdictionary/__init__.pyc in import_od(filename)
     38     if filename.endswith(".eds"):
     39         from . import eds
---> 40         return eds.import_eds(filename)
     41     elif filename.endswith(".epf"):
     42         from . import epf

/home/tuwuhs/.local/lib/python2.7/site-packages/canopen/objectdictionary/eds.pyc in import_eds(filename)
     52             entry = od[index]
     53             if isinstance(entry, objectdictionary.Record):
---> 54                 var = build_variable(eds, section, index, subindex)
     55                 entry.add_member(var)
     56 

/home/tuwuhs/.local/lib/python2.7/site-packages/canopen/objectdictionary/eds.pyc in build_variable(eds, section, index, subindex)
     64     var.access_type = eds.get(section, "AccessType")
     65     if eds.has_option(section, "LowLimit"):
---> 66         var.min = int(eds.get(section, "LowLimit"), 0)
     67     if eds.has_option(section, "HighLimit"):
     68         var.max = int(eds.get(section, "HighLimit"), 0)

ValueError: invalid literal for int() with base 0: '$NODEID+1536'

I'm on 0.3.0.dev7.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.