CANopen Examples¶
Receive and send PDOs from a QML application¶
Using the LinX UX designer we can design and test sending CANopen signals on the virtual CAN bus withing the VM. Following example shows how to create a QML application and update it using LinX Manager Fieldbus Access to send and receive CANopen data on the CAN bus.
Prerequisites¶
Data Engine installed on target device.
Fieldbus Access 1.3.0 or greater installed on target device.
Interface
can0
is up.can-utils
installed.
Data Engine and Fieldbus Access is pre-installed on UX Designer VM 4.0. Newer versions can be downloaded from the support site.
Create a QML project¶
Create a new project to use through the example.
Open Qt Creator.
File
>New file or Project...
.Select
CrossControl Project
and pickQt Quick 2 Application
.Follow the on-screen instructions to finalize the project creation:
Display resolution: 800x480
Kit: Desktop
Create a new CANopen bus¶
Open LinX Manager Fieldbus Access from the mode selector (left side).
Select the created project from the project selector drop-down menu.
Create a new CAN bus by pressing the add button and select “Add new CANopen slave bus”.
An empty CANopen bus is created with default settings.
Add transmit (TX) signal¶
Select “Transmitted Signals” tab from the middle panel.
Right mouse click and select “Add new signal”.
New signal created.
Double click the newSignal name and change it to “transmitSignal”.
DE Signal | DE Datatype | Gain | Offset | OD Index | OD Subindex |
---|---|---|---|---|---|
transmitSignal | INT | 1 | 0 | 2270 | 2 |
Add receive (RX) signal¶
Select “Received Signals” tab from the middle panel.
Right mouse click and select “Add new signal”.
New signal created.
Double click the newSignal name and change it to “receiveSignal”.
DE Signal | DE Datatype | Gain | Offset | OD Index | OD Subindex |
---|---|---|---|---|---|
receiveSignal | INT | 1 | 0 | 2170 | 2 |
Create TX PDO¶
Select “TPDO Mapping” tab from the middle panel.
Right mouse click and select “Add new PDO”.
New transmit PDO created.
Double click Transmission Type and set to
Asynchronous Manufacture Specific
PDO Name | COB-ID | Tranmission Type | SYNCs | Inhibit T | Event T | Tot b. |
---|---|---|---|---|---|---|
TPDO_1 | $NODEID+0x180 | Asynchronous Manufacture Specific (Type 254) | 0 |
Create RX PDO¶
Select “RPDO Mapping” tab from the middle panel.
Right mouse click and select “Add new PDO”.
New receive PDO created.
Double click Transmission Type and set to
Asynchronous Manufacture Specific
PDO Name | COB-ID | Tranmission Type | SYNCs | Inhibit T | Event T | Tot b. |
---|---|---|---|---|---|---|
RPDO_1 | $NODEID+0x200 | Asynchronous Manufacture Specific (Type 254) | 0 |
Map signals to PDO¶
Select “TPDO Mapping” tab from the middle panel.
Add the created signal to the PDO. On the TPDO_1, right mouse click and “Add signal”.
Do the same on “RPDO Mapping” tab.
PDO Name | COB-ID | Tranmission Type | SYNCs | Inhibit T | Event T | Tot b. |
---|---|---|---|---|---|---|
TPDO_1 | $NODEID+0x180 | Asynchronous Manufacture Specific (Type 254) | 32 | |||
transmitSignal | 2270 | 2 | INT | 32 |
Update the project¶
With the two PDOs created, the last step to perform with the plugin is to export the configuration and update the active project.
From the projector selector, press “Save” for the changes to take effect.
Verify that the project was updated by opening the General Messages tab (
Alt+6
):LinX Manager Data Engine: Project updated successfully.
Selected project is now updated with new code and files. See How-tos for a complete list of generated files.
Snippet from dataengine.h
:
class DataEngine : public DataEngineBase
{
Q_OBJECT
// Generated Signal MetaProperties
Q_PROPERTY (ShortConsumerSignal* fieldbusAccess_CANopenError_CAN0 READ fieldbusAccess_CANopenError_CAN0 CONSTANT)
Q_PROPERTY (ShortConsumerSignal* fieldbusAccess_CANopenStatus_CAN0 READ fieldbusAccess_CANopenStatus_CAN0 CONSTANT)
Q_PROPERTY (IntProducerSignal* transmitSignal READ transmitSignal CONSTANT)
Q_PROPERTY (IntConsumerSignal* receiveSignal READ receiveSignal CONSTANT)
Display PDO in QML¶
Values from the CAN-bus can now be visualized directly in the UI using the context property dataEngine
. The
documentation for LinX Manager Data Engine contains further instructions how to use the context property (both from
QML and Widget projects).
Open
main.qml
with the editorLocate
// add your GUI code below this line
Add the following to display
receiveSignal
in a Text component:Text { id: rxSignal_Label anchors.centerIn: parent font.pointSize: 20 color: "white" text: "RX Signal: " } Text { id: rxSignal anchors.left: rxSignal_Label.right anchors.top: rxSignal_Label.top color: dataEngine.receiveSignal.status ? "red" : "white" text: dataEngine.receiveSignal.value }
Send PDO value from QML¶
The snippet below will create two buttons in QML. When the first is clicked, it will update the TPDO transmitSignal
and set the value to -50. When the second button is clicked, it will update the same TPDO again and set the
value to 100. The value will be visible on the CAN bus when Fieldbus Access is running (future step).
Add this snippet beneath the code added in the previous section:
Rectangle { id: lowTXSignal width: 220; height: 60 anchors.top: rxSignal.bottom anchors.left: rxSignal_Label.left color: btnMouseArea1.pressed ? Qt.darker("grey", 1.5) : "grey" Text { anchors.centerIn: parent text: "Set value low" } MouseArea { id: btnMouseArea1 anchors.fill: parent onClicked: dataEngine.transmitSignal.value = -50 } } Rectangle { id: highTXSignal width: 220; height: 60 anchors.top: lowTXSignal.bottom anchors.left: rxSignal_Label.left color: btnMouseArea2.pressed ? Qt.darker("grey", 1.5) : "grey" Text { anchors.centerIn: parent text: "Set value high" } MouseArea { id: btnMouseArea2 anchors.fill: parent onClicked: dataEngine.transmitSignal.value = 100 } }
Start Fieldbus Access with generated configuration¶
The application is now prepared to send and receive value from/to the CAN bus. What’s left is to run Data Engine and Fieldbus Access to let it handle the CAN-communication.
Start Data Engine using the desktop shortcut.
Locate the generated configuration file for Fieldbus Access in the project directory.
[project directory]/LinXManager_FieldbusAccess/LinXManager_FA_configfile.json
.Open a terminal and use the command
candump can0
to view the traffic which is sent by Fieldbus Access to the CAN bus.Drag and drop the configuration on the Fieldbus Access shortcut found on the desktop.
Fieldbus Access start to execute based on the information found in the configuration.
Open a new terminal and use the command
cansend can0 000#0100
to change Fieldbus Access state frompre-operational
tooperational
.
Fieldbus Access will start and send initialization messages to the CAN bus.
ccs@LinX-VM:~$ candump can0
can0 701 [1] 00
can0 081 [8] 00 00 00 00 00 00 00 00
can0 000 [2] 01 00
can0 280 [8] 00 00 00 00 00 00 00 00
can0 380 [8] 00 00 00 00 00 00 00 00
can0 480 [8] 00 00 00 00 00 00 00 00
can0 1A0 [8] 00 00 00 00 00 00 00 00
can0 2A0 [8] 00 00 00 00 00 00 00 00
can0 3A0 [4] 00 00 00 00
can0 4A0 [8] 00 00 00 00 00 00 00 00
can0 1B0 [8] 00 00 00 00 00 00 00 00
can0 2B0 [8] 00 00 00 00 00 00 00 00
can0 3B0 [8] 00 00 00 00 00 00 00 00
can0 4B0 [8] 00 00 00 00 00 00 00 00
can0 1C0 [4] 00 00 00 00
can0 2C0 [8] 00 00 00 00 00 00 00 00
can0 3C0 [8] 00 00 00 00 00 00 00 00
can0 4C0 [8] 00 00 00 00 00 00 00 00
Send random PDO data and view in QML¶
With Data Engine and Fieldbus Access running from the previous step, it is now possible to read data from the CAN bus and display the result in the application created earlier.
Compile and start the application from Qt Creator.
Text field for
receiveSignal
are displayed with the value assigned to zero.Open a terminal and use
cangen
to generate random data for PDO1.# Send 4 random bytes every second to PDO1 0x201 (OD Index 0x2170) ccs@LinX-VM:~$ cangen can0 -I 201 -L 4 -g 1000 -v can0 201#52.1E.11.6D can0 201#E1.2D.02.56 can0 201#F7.4A.03.4F can0 201#2B.E4.5C.29
Values for
receiveSignal
is updated based on the values sent on the CAN bus. Color of the text is updated from red to white when the status value changes.
Send PDO value from QML (continued)¶
Pressing any of the two buttons will update transmitSignal (TPDO 1)
and later
sent to the CAN bus by Fieldbus Access. The physical value from the application
is scaled with the configured gain and offset before it is visible on the CAN
bus.
Physical | Gain | Offset | Raw (hex) |
---|---|---|---|
-50 | 1 | 0 | 0xCEFFFFFF |
100 | 1 | 0 | 0x64000000 |
Use candump can0
to view the CAN frames sent by Fieldbus Access:
ccs@LinX-VM:~$ candump can0
can0 181 [4] CE FF FF FF # Transmit value -50
can0 2A0 [8] 00 00 00 00 CE FF FF FF
can0 181 [4] 64 00 00 00 # Transmit value 100
can0 2A0 [8] 00 00 00 00 64 00 00 00
Display CANopen errors in a list view¶
The tool injects the project with a model which stores CANopen stack errors.
Information stored in the model can be displayed in QML, for example with a
ListView
or TableView
. The model is accessed via the context property
canopenStatusModel
.
More information of how errors are generated and about CANopen error model can be found on the Error Handling page.
Example of a ListView
in QML which displays four roles from the error model:
ListView {
width: parent.width
height: parent.height
model: canopenStatusModel
delegate: Row {
width: parent.width
spacing: 25
Text {
text: bus
}
Text {
text: type
}
Text {
text: message
}
Text {
text: received
}
}
Show stack status in QML¶
The system signal fieldbusAccess_CANopenStatus_CAN#
receives stack state
specific information from the Network Management (NMT).
State | Code (hex) |
---|---|
Initialisation | 0x00 |
Pre-Operational | 0x04 |
Operational | 0x05 |
Stopped | 0x7F |
Open
main.qml
with the editorAdd the following to display received status in a Text component:
Text { anchors.right: parent.right anchors.bottom: parent.bottom color: "#C00" font.pixelSize: 32; text: (dataEngine.fieldbusAccess_CANopenStatus_CAN0.value === FieldbusAccessCANopenStatusModel.NodeStateInitialisation) ? "Initialisation" : (dataEngine.fieldbusAccess_CANopenStatus_CAN0.value === FieldbusAccessCANopenStatusModel.NodeStateStopped) ? "Stopped" : (dataEngine.fieldbusAccess_CANopenStatus_CAN0.value === FieldbusAccessCANopenStatusModel.NodeStateOperational) ? "Operational" : (dataEngine.fieldbusAccess_CANopenStatus_CAN0.value === FieldbusAccessCANopenStatusModel.NodeStatePreOperational) ? "Pre Operational" : "N/A"; }
The state
will change based on the reception of current CANopen stack status
from the Fieldbus Access runtime. This is done by comparing the
fieldbusAccess_CANopenStatus_<CAN0>
signal value with
FieldbusAccessCANopenStatusModel.<state>
. CAN0 automatically added if “0” is the interface number selected in the bus settings.
Another suitable control that can be used is the StatusIndicator
QML type.
Import QtQuick.Extras 1.4
to have access to this type. The indicator will be
shown in green when the status is in state Operational
and unlit otherwise.
import QtQuick.Extras 1.4
StatusIndicator {
anchors.centerIn: parent
color: "green"
active: dataEngine.fieldbusAccess_CANopenStatus_CAN0.value === FieldbusAccessCANopenStatusModel.NodeStateOperational
}
Test status property with CAN data¶
The status will quickly go from
Initialisation
toPre-Operational
.Send CANopen master
operational
signal.cansend can0 000#0100
Status will change to
Operational
.