Process Data Object (PDO)¶
The Process Data Object protocol is used to process real time data among various nodes. You can transfer up to 8 bytes (64 bits) of data per one PDO either from or to the device. One PDO can contain multiple object dictionary entries and the objects within one PDO are configurable using the mapping and parameter object dictionary entries.
There are two kinds of PDOs: transmit and receive PDOs (TPDO and RPDO). The former is for data coming from the device and the latter is for data going to the device; that is, with RPDO you can send data to the device and with TPDO you can read data from the device. In the pre-defined connection set there are identifiers for four (4) TPDOs and four (4) RPDOs available. With configuration 512 PDOs are possible.
PDOs can be sent synchronously or asynchronously. Synchronous PDOs are sent after the SYNC message whereas asynchronous messages are sent after internal or external trigger. For example, you can make a request to a device to transmit TPDO that contains data you need by sending an empty TPDO with the RTR flag (if the device is configured to accept TPDO requests).
With RPDOs you can, for example, start two devices simultaneously. You only need to map the same RPDO into two or more different devices and make sure those RPDOs are mapped with the same COB-ID.
Examples¶
A canopen.RemoteNode
has canopen.RemoteNode.rpdo
and
canopen.RemoteNode.tpdo
attributes that can be used to interact
with the node using PDOs. These can be subindexed to specify which map to use (first map
starts at 1, not 0):
# Read current PDO configuration
node.tpdo.read()
node.rpdo.read()
# Do some changes to TPDO4 and RPDO4
node.tpdo[4].clear()
node.tpdo[4].add_variable('Application Status', 'Status All')
node.tpdo[4].add_variable('Application Status', 'Actual Speed')
node.tpdo[4].trans_type = 254
node.tpdo[4].event_timer = 10
node.tpdo[4].enabled = True
node.rpdo[4].clear()
node.rpdo[4].add_variable('Application Commands', 'Command All')
node.rpdo[4].add_variable('Application Commands', 'Command Speed')
node.rpdo[4].enabled = True
# Save new configuration (node must be in pre-operational)
node.nmt.state = 'PRE-OPERATIONAL'
node.tpdo.save()
node.rpdo.save()
# Start RPDO4 with an interval of 100 ms
node.rpdo[4]['Application Commands.Command Speed'].phys = 1000
node.rpdo[4].start(0.1)
node.nmt.state = 'OPERATIONAL'
# Read 50 values of speed and save to a file
with open('output.txt', 'w') as f:
for i in range(50):
node.tpdo[4].wait_for_reception()
speed = node.tpdo['Application Status.Actual Speed'].phys
f.write('%s\n' % speed)
# Using a callback to asynchronously receive values
# Do not do any blocking operations here!
def print_speed(message):
print('%s received' % message.name)
for var in message:
print('%s = %d' % (var.name, var.raw))
node.tpdo[4].add_callback(print_speed)
time.sleep(5)
# Stop transmission of RxPDO
node.rpdo[4].stop()
API¶
- class canopen.pdo.PdoBase(node)[source]¶
Represents the base implementation for the PDO object.
- Parameters:
node (object) – Parent object associated with this PDO instance
- pdo[no]
Return the
canopen.pdo.Map
for the specified map number. First map starts at 1.
- iter(pdo)
Return an iterator of the available map numbers.
- len(pdo)
Return the number of supported maps.
- export(filename)[source]¶
Export current configuration to a database file.
- Parameters:
filename (str) – Filename to save to (e.g. DBC, DBF, ARXML, KCD etc)
- Returns:
The CanMatrix object created
- Return type:
canmatrix.canmatrix.CanMatrix
- subscribe()[source]¶
Register the node’s PDOs for reception on the network.
This normally happens when the PDO configuration is read from or saved to the node. Use this method to avoid the SDO flood associated with read() or save(), if the local PDO setup is known to match what’s stored on the node.