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.

  1. Open Qt Creator.

  2. File > New file or Project....

  3. Select CrossControl Project and pick Qt Quick 2 Application.

  4. Follow the on-screen instructions to finalize the project creation:

    1. Display resolution: 800x480

    2. Kit: Desktop

Create a new CANopen bus

  1. Open LinX Manager Fieldbus Access from the mode selector (left side).

  2. Select the created project from the project selector drop-down menu.

  3. Create a new CAN bus by pressing the add button Add bus and select “Add new CANopen slave bus”.

  4. An empty CANopen bus is created with default settings.

Add transmit (TX) signal

  1. Select “Transmitted Signals” tab from the middle panel.

  2. Right mouse click and select “Add new signal”.

  3. New signal created.

  4. 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

  1. Select “Received Signals” tab from the middle panel.

  2. Right mouse click and select “Add new signal”.

  3. New signal created.

  4. 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

  1. Select “TPDO Mapping” tab from the middle panel.

  2. Right mouse click and select “Add new PDO”.

  3. New transmit PDO created.

  4. 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

  1. Select “RPDO Mapping” tab from the middle panel.

  2. Right mouse click and select “Add new PDO”.

  3. New receive PDO created.

  4. 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

  1. Select “TPDO Mapping” tab from the middle panel.

  2. Add the created signal to the PDO. On the TPDO_1, right mouse click and “Add signal”.

  3. 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.

  1. From the projector selector, press “Save” for the changes to take effect.

  2. Verify that the project was updated by opening the General Messages tab (Alt+6):

    LinX Manager Data Engine: Project updated successfully.

  3. 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).

  1. Open main.qml with the editor

  2. Locate // add your GUI code below this line

  3. 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).

  1. 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.

  1. Start Data Engine using the desktop shortcut.

  2. Locate the generated configuration file for Fieldbus Access in the project directory. [project directory]/LinXManager_FieldbusAccess/LinXManager_FA_configfile.json.

  3. Open a terminal and use the command candump can0 to view the traffic which is sent by Fieldbus Access to the CAN bus.

  4. Drag and drop the configuration on the Fieldbus Access shortcut found on the desktop.

  5. Fieldbus Access start to execute based on the information found in the configuration.

  6. Open a new terminal and use the command cansend can0 000#0100 to change Fieldbus Access state from pre-operational to operational.

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.

  1. Compile and start the application from Qt Creator.

  2. Text field for receiveSignal are displayed with the value assigned to zero.

  3. 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
    
  4. 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
  1. Open main.qml with the editor

  2. Add 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

  1. Start GUI application

  2. Start Fieldbus Access with generated configuration

  3. The status will quickly go from Initialisation to Pre-Operational.

  4. Send CANopen master operational signal.

    cansend can0 000#0100
    
  5. Status will change to Operational.