Skip to content

Commit 643be1c

Browse files
committed
initial commit
0 parents  commit 643be1c

18 files changed

+1759
-0
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
build-*
2+
*.user

.gitmodules

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "lib/ADS"]
2+
path = lib/ADS
3+
url = https://github.com/Beckhoff/ADS.git

Example/.gitignore

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# This file is used to ignore files which are generated
2+
# ----------------------------------------------------------------------------
3+
4+
*~
5+
*.autosave
6+
*.a
7+
*.core
8+
*.moc
9+
*.o
10+
*.obj
11+
*.orig
12+
*.rej
13+
*.so
14+
*.so.*
15+
*_pch.h.cpp
16+
*_resource.rc
17+
*.qm
18+
.#*
19+
*.*#
20+
core
21+
!core/
22+
tags
23+
.DS_Store
24+
.directory
25+
*.debug
26+
Makefile*
27+
*.prl
28+
*.app
29+
moc_*.cpp
30+
ui_*.h
31+
qrc_*.cpp
32+
Thumbs.db
33+
*.res
34+
*.rc
35+
/.qmake.cache
36+
/.qmake.stash
37+
38+
# qtcreator generated files
39+
*.pro.user*
40+
41+
# xemacs temporary files
42+
*.flc
43+
44+
# Vim temporary files
45+
.*.swp
46+
47+
# Visual Studio generated files
48+
*.ib_pdb_index
49+
*.idb
50+
*.ilk
51+
*.pdb
52+
*.sln
53+
*.suo
54+
*.vcproj
55+
*vcproj.*.*.user
56+
*.ncb
57+
*.sdf
58+
*.opensdf
59+
*.vcxproj
60+
*vcxproj.*
61+
62+
# MinGW generated files
63+
*.Debug
64+
*.Release
65+
66+
# Python byte code
67+
*.pyc
68+
69+
# Binaries
70+
# --------
71+
*.dll
72+
*.exe
73+

Example/Example.pro

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
QT += quick
2+
CONFIG += c++11
3+
4+
# The following define makes your compiler emit warnings if you use
5+
# any Qt feature that has been marked deprecated (the exact warnings
6+
# depend on your compiler). Refer to the documentation for the
7+
# deprecated API to know how to port your code away from it.
8+
DEFINES += QT_DEPRECATED_WARNINGS
9+
10+
INCLUDEPATH += ../include
11+
INCLUDEPATH += ../ADS
12+
13+
# You can also make your code fail to compile if it uses deprecated APIs.
14+
# In order to do so, uncomment the following line.
15+
# You can also select to disable deprecated APIs only up to a certain version of Qt.
16+
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
17+
18+
SOURCES += \
19+
main.cpp \
20+
plcdriver.cpp
21+
22+
RESOURCES += qml.qrc
23+
24+
# Additional import path used to resolve QML modules in Qt Creator's code model
25+
QML_IMPORT_PATH =
26+
27+
# Additional import path used to resolve QML modules just for Qt Quick Designer
28+
QML_DESIGNER_IMPORT_PATH =
29+
30+
# Default rules for deployment.
31+
qnx: target.path = /tmp/$${TARGET}/bin
32+
else: unix:!android: target.path = /opt/$${TARGET}/bin
33+
!isEmpty(target.path): INSTALLS += target
34+
35+
HEADERS += \
36+
plcdriver.h
37+
38+
win32:CONFIG(release, debug|release): LIBS += -L$$PWD/../build-qads-Desktop-Debug/release/ -lqads
39+
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/../build-qads-Desktop-Debug/debug/ -lqads
40+
else:unix: LIBS += -L$$PWD/../build-qads-Desktop-Debug/ -lqads
41+
42+
INCLUDEPATH += $$PWD/../build-qads-Desktop-Debug
43+
DEPENDPATH += $$PWD/../build-qads-Desktop-Debug
44+
INCLUDEPATH += $$PWD/../lib/ADS/AdsLib
45+
DEPENDPATH += $$PWD/../lib/ADS/AdsLib

Example/main.cpp

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
#include <QGuiApplication>
2+
#include <QQmlApplicationEngine>
3+
#include <QQmlContext>
4+
#include <QDebug>
5+
6+
// qads "library" headers
7+
#include <tc3manager.h>
8+
#include <tc3value.h>
9+
10+
// this header is required for all examples, one could do without this,
11+
// but for large scale projects an object like this is useful
12+
#include "plcdriver.h"
13+
14+
// this header is used for example 2, where complete structs are
15+
// read and write, respectively. In large scale projects, a header
16+
// like this should be generated (i.e. by parsing Twincat3's TMC file
17+
// and generating C++ code from it)
18+
#include "plcdef.h"
19+
20+
int main(int argc, char *argv[])
21+
{
22+
QGuiApplication app(argc, argv);
23+
24+
PlcDriver data("10.100.20.228.1.1:851", &app);
25+
Tc3Manager* manager = data.manager();
26+
27+
28+
// EXAMPLE 1: single variable access
29+
// change something on the PLC with the set method
30+
qDebug() << manager->value("MAIN.variable")->get();
31+
manager->value("MAIN.variable")->set("connected to plc");
32+
qDebug() << manager->value("MAIN.variable")->get();
33+
34+
// EXAMPLE 2: struct variable access
35+
// read "complex" struct from plc
36+
// change something in the struct and write it to the plc
37+
// read the struct again and let's check, if we actually change something
38+
Tc3Value *exampleStruct = manager->value("MAIN.struct1", sizeof(Plc::ExampleStruct));
39+
Plc::ExampleStruct exampleStructData = exampleStruct->get<Plc::ExampleStruct>();
40+
41+
qDebug() << "Initial value" << exampleStructData.sub1.sub2.integer1;
42+
43+
exampleStructData.sub1.sub2.integer1 += 1;
44+
exampleStruct->set<Plc::ExampleStruct>(exampleStructData);
45+
46+
exampleStructData = exampleStruct->get<Plc::ExampleStruct>();
47+
qDebug() << "New value" << exampleStructData.sub1.sub2.integer1;
48+
49+
50+
// EXAMPLE 3: QML example
51+
// Primitive datatypes (INT, DINT, REAL, ...) - where one can use Tc3Manager::AutoType
52+
// can be bound to properties within QML
53+
qmlRegisterType<Tc3Value>("Tc3Value", 1, 0, "Tc3Value");
54+
qmlRegisterType<PlcButton>("PlcButton", 1, 0, "PlcButton");
55+
qmlRegisterType<PlcAnalogIo>("PlcAnalogIo", 1, 0, "PlcAnalogIo");
56+
57+
QQmlApplicationEngine engine;
58+
QQmlContext* context = engine.rootContext();
59+
60+
// Make generic read/write access to plc available within qml
61+
context->setContextProperty("plcDriver", &data);
62+
63+
// Make qml aware of two buttons - each could start a sequence on the plc
64+
PlcButton btnStartMotor(manager->value("MAIN.btnStartMotor", Tc3Manager::AutoType), &data);
65+
PlcButton btnStopMotor(manager->value("MAIN.btnStopMotor", Tc3Manager::AutoType), &data);
66+
context->setContextProperty("btnStartMotor", &btnStartMotor);
67+
context->setContextProperty("btnStopMotor", &btnStopMotor);
68+
69+
// Editable analog output
70+
PlcAnalogIo nominalMotorSpeed(manager->value("MAIN.nominalSpeed", Tc3Manager::AutoType), &data);
71+
context->setContextProperty("nominalMotorSpeed", &nominalMotorSpeed);
72+
73+
// Display the current value of an analog input with qml (this is readonly, see qml code)
74+
PlcAnalogIo actualMotorSpeed(manager->value("MAIN.actualSpeed", Tc3Manager::AutoType, Tc3Manager::NotificationType::Cycle, 100, 1000), &data);
75+
context->setContextProperty("actualMotorSpeed", &actualMotorSpeed);
76+
77+
// Stress QML with random values, that should update the corresponding ui element whenever a change occurs
78+
// parameters 0,1000 forces to receive every change - you wouldn't want to do this in real life applications,
79+
// also for actual applications, one would implement a QModel for something like that, but we keep it simple here
80+
QVector<PlcAnalogIo*> randval;
81+
for(int i=0; i<10; ++i)
82+
{
83+
randval << new PlcAnalogIo(manager->value(QString("MAIN.randval[%1]").arg(i), Tc3Manager::AutoType, Tc3Manager::NotificationType::Change, 50, 200), &data);
84+
context->setContextProperty(QString("randval%1").arg(i), randval[i]);
85+
}
86+
87+
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
88+
if (engine.rootObjects().isEmpty())
89+
return -1;
90+
91+
return app.exec();
92+
}
93+

Example/main.qml

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import QtQuick 2.10
2+
import QtQuick.Window 2.10
3+
import QtQuick.Controls 1.4
4+
import QtQuick.Layouts 1.3
5+
6+
Window {
7+
visible: true
8+
width: 640
9+
height: 480
10+
color: "#292927"
11+
title: "QAds";
12+
13+
Text {
14+
id: text1
15+
anchors.centerIn: parent
16+
color: "white"
17+
text: plcDriver.value("MAIN.variable").value
18+
}
19+
20+
// Start action on the plc, the plc should reset the button to false
21+
Button {
22+
objectName: "button1"
23+
id: button1
24+
anchors.bottom: parent.bottom
25+
anchors.left: parent.left
26+
text: qsTr("Start")
27+
onClicked: btnStartMotor.setPressed(true)
28+
}
29+
30+
// Start action on the plc, the plc should reset the button to false
31+
Button {
32+
id: button2
33+
anchors.bottom: parent.bottom
34+
anchors.left: button1.right
35+
text: qsTr("Stop")
36+
onClicked: btnStopMotor.setPressed(true)
37+
}
38+
39+
// Spinbox, which can write a value to the plc via binding
40+
SpinBox {
41+
id: spin1
42+
anchors.bottom: parent.bottom
43+
anchors.right: parent.right
44+
value: nominalMotorSpeed.value
45+
suffix: " rpm"
46+
maximumValue: 5000
47+
}
48+
Binding { target: nominalMotorSpeed; property: "value"; value: spin1.value }
49+
50+
// Spinbox, which can only read from the plc
51+
SpinBox {
52+
id: spin2
53+
anchors.bottom: parent.bottom
54+
anchors.right: spin1.left
55+
value: actualMotorSpeed.value
56+
suffix: " rpm"
57+
maximumValue: 5000
58+
stepSize: 100
59+
enabled: false // lets disable it to make it clear to the user that it is readonly
60+
}
61+
62+
ColumnLayout
63+
{
64+
Text { color: "white"; text: randval1.value }
65+
Text { color: "white"; text: randval2.value }
66+
Text { color: "white"; text: randval3.value }
67+
Text { color: "white"; text: randval4.value }
68+
Text { color: "white"; text: randval5.value }
69+
Text { color: "white"; text: randval6.value }
70+
Text { color: "white"; text: randval7.value }
71+
Text { color: "white"; text: randval8.value }
72+
Text { color: "white"; text: randval9.value }
73+
}
74+
}

Example/plcdef.h

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#ifndef PLCDEF_H
2+
#define PLCDEF_H
3+
4+
// C++ representation of PLC datatypes. For a big scale project
5+
// something like this should be generated code. Otherwise,
6+
// it is hard to keep up with changes to structs in a PLC and you
7+
// might run into huge problems, when the PLC programmer decides
8+
// to change the arangment of types within structs;
9+
// Be aware of the correct alignment, you might have to change the
10+
// alignment if you use a different compiler than the author
11+
12+
namespace Plc
13+
{
14+
15+
enum ColorEnum
16+
{
17+
red,
18+
green,
19+
blue
20+
};
21+
22+
struct ExampleSubSubStruct
23+
{
24+
short integer1;
25+
short integer2;
26+
float real1;
27+
ColorEnum color;
28+
};
29+
30+
struct ExampleSubStruct
31+
{
32+
short integer1;
33+
ExampleSubSubStruct sub1;
34+
int integer2;
35+
ExampleSubSubStruct sub2;
36+
float real1;
37+
double lreal1;
38+
ExampleSubSubStruct sub3;
39+
};
40+
41+
struct ExampleStruct
42+
{
43+
char string1[256];
44+
char string2[81];
45+
ExampleSubStruct sub1;
46+
};
47+
}
48+
49+
#endif // PLCDEF_H

0 commit comments

Comments
 (0)