CanOpenDeviceMonitorThe CANopen Device Monitor (CDM) is a powerful CanOpen tool.
It provides a high-level scripting API using the language TclTk 8.4. To get started with CDM programming, you should be familiar with TclTk.
Scripts can be loaded and executed opening the Console (Menue: View->Console), enter:
(cdm) 1 % source script.tcl
global frame
set frame [::cdm::addTab Heartbeat]
label $frame.label -text "Heartbeat interval (ms):"
entry $frame.entry -width 10
button $frame.okButton -text "Change heartbeat interval" -command changeHB
grid $frame.label -row 0 -column 0
grid $frame.entry -row 0 -column 1
grid $frame.okButton -row 2 -column 0 -columnspan 2
proc changeHB { } {
global frame
set val [$frame.entry get]
w 0x1017 0 u16 $val
}
## the CDM 2.x command for ::cdm::addTab is cdm_addTab?
## the w command in CDM 2.x does not require the 0x prefix for hex values
toplevel .mytoplevel wm title .mytoplevel "NMT Control Desk" wm geometry .mytoplevel "300x200" button .mytoplevel.b1 -text "Start" -command "start 0" button .mytoplevel.b2 -text "Enter Preop" -command "preop 0" button .mytoplevel.b3 -text "Stop" -command "stop 0" pack .mytoplevel.b1 .mytoplevel.b2 .mytoplevel.b3
global myVal
set myVal 0
proc doIncrementJob { } {
global myVal
w 0x6200 1 u8 $myVal
incr myVal
if { $myVal >= 255 } {
set myVal 0
}
}
# run doIncrementJob every 500 ms
::common::every doIncrementJob 500
## common::every is not available in CDM 2.x
# at first the PDO must be configured # as it is a RPDO of the device, you have to use the command # set_rpdo set cobId 0x333 set transmissionType "event" set_rpdo local 1 $cobId $transmissionType 0x6200 1 0x6200 2 # now the PDO can be sent by wpdo set num 1 set length 2 set value1 0x00 set value2 0xaa wpdo $num $length $value1 $value2 # or wpdo 1 2 0x00 0x55 # to send this PDO every second # use the function ::common::every ::common::every "wpdo 1 2 0x00 0x55" 1000 ## common::every is not available in CDM 2.x ## the syntax of wpdo and set_rpdo is different from CDM 2.x
# the following script provides the every command for CDM 2.x users
proc every { script interval } {
eval $script
after $interval [info level 0]
}
# Check the execution time of a script with time
# Send a PDO 1000-times as fast as possible and see how long it takes
time { ::pdo::wpdo 1 } 1000
# configure a PDO and show the received PDO
# at first the PDO must be configured
# As the device sends the PDO, it's a TPDO of the device
# and must be configured with ::pdo::set_tpo?
# ::pdo::set_tpdo <type> <number> <cobId> <transmissionType>
# <1st mapped index> <sub> .. <nth mapped index> <sub>
::pdo::set_tpdo local 1 0x1a0 event 0x2010 0x0
#
# After that, you need a Callback-Function that is called
# every time the PDOs is received.
# The following is a little example:
proc myCallback { num length dataList } {
# just put the data to the console
puts "PDO $num received: $dataList"
}
# Now the Callback function has to be registered.
#::pdo::setPDOIndication <num> <callback function>
::pdo::setPDOIndication 1 myCallback
# Now myCallback is called on reception of the PDO 1
# Don't forget to start the network
start 0
# If the PDO can be requested by RTR, just use
::pdo::rpdo 1
# to request it.
# To change a configured PDO, it must be reset by disabling the first
# bit of the PDO
::pdo::set_tpdo local 1 0x800001a0 event
# now PDO 1 can be reconfigured
Some CDM commands require strings formated as base64. E.g. to send octet strings or domain data from a script. Convertion to base64 can easyly be done by the built-in tcl commands.
# convert a string to base64 set x [::base64::encode "I love CDM"] # even with non-printable characters set x [::base64::encode "\x01\x02\x03\x04"] # decode base64 ::base64::decode "d3d3LmNhbmV4cGVydHMuZGU="
The good news at first. The tcl commands haven't changed between these two CDM versions. But the following CDM commands have changed:
cdm_set_remote_id? -> ::cdm::setRemoteID cdm_load_eds? -> ::cdm::loadEds cdm_profilescan? -> ::cdm::profileScan cdm_banner? -> ::cdm::banner cdm_get_remote_id? -> ::cdm::getRemoteID cdm_userdialog? -> ::cdm::userDialog cdm_string_center? -> ::cdm::stringCenter cdm_addTab? -> ::cdm::addTab cdm_deleteTab? -> ::cdm::deleteTab cdm_string_fill? -> ::cdm::stringFill cdm_addTestTab? -> ::cdm::addTestTab cdm_puts_datetime? -> ::cdm::putsDateTime cdm_comment_input? -> ::cdm::commentInput cdm_procedure? -> ::cdm::setAction # the first :: can be omitedThat are not only the names that have changed, but the number and kind of the arguments, too.
Further the index argument of all SDO commands like r, w etc. have to be changed. Look at the following example:
# CDM 2.x syntax w 2000 0 u16 10 # CDM 3.x syntax w 0x2000 0 u16 10
Additionally a specific node ID can be addressed now by putting the node ID before the w or r command.
# read from node 10 10 r 0x1000 0 u32 # read from node 22 22 r 0x1000 0 u32
Reception of PDO:
# register your old cdm_pdo_ind? procedure # do this for all your pdo ::pdo::setPDOIndication 1 cdm_pdo_ind?