By: Catherine H., SW Developer at GradientOne
GradientOne supports cloud based data acquisition and visualization from devices using the CANopen protocol. CANopen is frequently used for embedded systems in automation. It is used in a wide range of industries including medical devices, automotive, heavy machinery, aerospace, and more. In this first of two blog posts, we'll cover how to acquire plotting data by repeatedly sending a polling message and storing the results. In the next post, we'll cover downloading plotting data from the trace tool. For access to our CANopen demo website, please fill out this form.
A Brief introduction to CANopen
CANopen is a OSI-Model compliant communication protocol at the network layer. Like with other packets at the network layer, such as IP packets, CANopen packets have an ID (11 bits long) and data (0-8 bytes). In linux, CAN devices will show up in ip and packets can be written and read to them using the socketcan kernel module. The python library python-can has a simple binding for sending and receiving can packets.
Link with IP packets, the ID simply directs the packets to appropriate node in the network, as well as indicates the type of the message. The actual instructions are contained in the data, like TCP packets within IP packets. The motor controller's object dictionary, that is, the correspondence between a human-readable property, such as target position, and two hexadecimal bytes 0x6040, is required in order to issue commands.
Dictionary objects come in two flavors: Service Dictionary Objects (SDOs) and Process Dictionary Objects (PDOs). They differ in the way they are communicated from the motor controller.
The following diagram shows the flow of CAN packets between a control computer and the motor controller in both data acquisition methods.
GradientOne's CANbus editor
GradientOne allows for sending and receiving CANbus packets through the web browser. To get there, go to https://gradientone-can.appspot.com/instruments. We have connected a CopleyControls AccelNet panel to the gateway for you to acquire live data. In the dropdown menu with "Settings", select "Editor".
You can enter frames in the text area either as:
For this demo, we're going to make the motor move to position 60,000 while collecting data on the motor's position and velocity.
In order to map PDOs, we need to first set the CAN network to pre-operational mode:
The PDO's are mapped by sending a series of SDO's. SDO's can be generated in the editor using the WRITE GradientOne shorthand. Lines starting with # are ignored.
# Set Number of Mapped objects on PDO 1 to zero WRITE 0x00 to number_of_mapped_objects_0_tx on node 1 # set the COB-ID of PDO 1 to address + off (0x81010080) WRITE 0x81010080 to pdo_cob-id_0_tx on node 1 # set transmission type to every sync (0x01) WRITE 0x01 to pdo_type_0_tx on node 1 # map PDO 1 to the actual motor position (0x224000), expected data is 4 bytes long (0x20) WRITE 0x20,0x00,0x40,0x22 to pdo_mapping_0_1_tx on node 1 # set the COB-ID of PDO 1 to address + on (0x81010000) WRITE 0x81010000 to pdo_cob-id_0_tx node 1 # Set Number of total Mapped objects on PDO 1 to one WRITE 0x01 to number_of_mapped_objects_0_tx on node 1
Next, do the same for 0x6069 to PDO 2:
# Set Number of Mapped objects on PDO 2 to zero WRITE 0x00 to number_of_mapped_objects_1_tx on node 1 # set the COB-ID of PDO 2 to address + off (0x82010080) WRITE 0x82010080 to pdo_cob-id_1_tx on node 1 # set transmission type to every sync (0x01) WRITE 0x01 to pdo_type_1_tx on node 1 # map PDO 2 to the actual velocity (0x606900), expected data is 4 bytes long (0x20) WRITE 0x20,0x00,0x69,0x60 to pdo_mapping_1_1_tx on node 1 # set the COB-ID of PDO 2 to address + on (0x82010000) WRITE 0x82010000 to pdo_cob-id_0_tx on node 1 # Set Number of total Mapped objects on PDO 2 to one WRITE 0x01 to number_of_mapped_objects_1_tx on node 1
Finish mapping the PDO's by setting the CANopen network to operational:
Next, send the command to move to position 60,000:
# Set position mode to target position (0x01) WRITE 0x01 to mode_of_operation on node 1 # Set target position to 60,000 (0xc0270900) WRITE 0xc0270900 to trajectory_generator_position_command on node 1 # Set control word bit 4 (address 0x6040) to move (0x3f00) WRITE 0x3f00 to control_word on node 1 # Set control word bit 4 to done (0x2f00) WRITE 0x2f00 to control_word on node 1
Finally, we want to send several SYNC messages to collect data. With GradientOne's shorthand, we can do this in one step, using a for loop:
SYNC for i in range(0, 20)
Copy and paste these packets into the text area of the CANbus and click add, then click run.
You should see the GradientOne shorthand get translated into the corresponding IDs, command codes and data in the table below.
Once SYNC has been run more than once, the data will be added to a plot:
GradientOne also can simplify this data acquisition process by pulling out values from the Electronic Data Sheet (EDS). To get a trace with this method, click on "Settings" under dropdown menu:
Enter a name Config Name, set the testination to 60,000, set the time window to 1, and select "poll" under DAq method:
The "properties" drop-down will then populate with all of the OD addresses that can be mapped to a PDO. From these properties, select "actual_load_position" and "actual_velocity". After clicking "Save", the config name will show up above the plot. To send this test run to the motor, click on "Run":
The plot should look something like this:
In part two, we'll go over how to use motor controller's trace tool to download data.