Hi,
zurzeit beschäftige ich mit dem Programm Qt, habe gesehen das man
grafische Oberflächen damit programmieren kann. Nun habe ich einen
Tachoinstrumenten programmiert und bin wie folgt vorgegangen.
Habe mir in Gimp die Bilder eines Tachos zusammen geschnitten und mit
dem QT Designer die einzelnen png Bilder plaziert ein die Nadel jetzt
auch zum laufen gebracht. Ich habe für die Programmierung slider benutzt
mit der man durch ziehen des des Buttons der Geschwidisgkeitszeiger
bewegt wird.
Nun zu meiner Frage ich möchte gerne die Pfeiltaste auf der Tastatur
benutzen damit sich der Zeiger bewegt, habe in der bibliothek nicht
gescheites gefunden, was mich weiterbringt, vielleicht könnt ihr mir
weiterhelfen??
Hier ist der Code für die Rotaion des Zeigers:
[
Image {
id: zeiger
x: 218; y: 0
height: 215
smooth: true
source: "geschw_zeiger.png"
transform: Rotation {
id: zeigerRotation
origin.x: 5; origin.y: 215
//! [needle angle]
angle: Math.min(Math.max(-150, root.value*3.5 - 200), 150)
Behavior on angle {
SpringAnimation {
spring: 0.4
damping: .15
}
}
//! [needle angle]
}
}
]
ich danke euch schonmal im Voraus.
Gruss
Flat
Hallo,
sollte der gezeigte Code "QML" darstellen, dann würde ich die Verwendung
von "QML Keys Element" (http://doc.qt.nokia.com/qml-keys.html)
empfehlen.
Hi,
Danke nochmal für deine Antwort. Nun habe ich jetzt das Problem, dass
ich nicht genau weis wie ich das eingeben soll.
Wo ich noch den Slider benutzt habe wurde der Zeiger mit einem
Eingabewert Value bewegt.
Ich will das der Value wert, wenn ich jetzt auf die Up Taste drauf
drücke, hoch zählt.
Ich hoffe ich konnte mich verständlich ausdrücken.
Hier ist ein Abschnitt vom Code:
Zeiger {
id: zeiger
x: 420
y: 80
anchors.verticalCenterOffset: 0
anchors.horizontalCenterOffset: 0
anchors.centerIn: parent
value: 20
Keys.onPressed: { if (event.key == Qt.Key_Up);
???
}
Ich bin neu in Qml, deshalb würde ich mich eure Hilfe freuen.
Ich danke schonmal im Voraus.
Hi,
habe das jetzt so gelöst indem ich den value wert mit der Up taste auf
100 rotiert lasse
und mit der Down Taste auf 0. Hier ist der Code:
1
focus: true
2
Keys.onPressed: { if (event.key === Qt.Key_Up)
3
4
root.value= 100;
5
6
else if (event.key ===Qt.Key_Down)
7
8
root.value= 0
9
}
Nun möchte ich aber nur eine Taste benutzen.
Sprich wenn ich auf Up drücke soll es auf den Value wert = 100 laufen
und wenn ich loslasse dann soll es auf den value wert = 0 zurück
rotieren.
Und ich habe gleich noch eine frage, wie kann ich den Value wert
anzeigen lassen, sodass man z.B nicht auf die Nadelstellung achten muss
sondern den Wert direkt ablesen kann.
Ich danke für eure Tipps
Gruss
Flat
Hi,
ich bins nochmal weiß hier jemand wie ich den Timer integrieren kann,
sodass ich den digitalen Wert von Tacho zählen lassen kann.
Ohne Timer wird bei mir nur 100 und 0 angezeigt.
Es ist vielleicht ne Triviale Frage für euch aber würde mich auf eine
Hilfestellung trotzdem freuen.
Gruss
Flat
Hi,
du meintest ja wenn das laufen nach und nach passieren soll, muss man
einen Timer integrieren, ich weiß nur nicht wie. Hast du vielleicht ein
Beispiel Code, wie man das realisieren kann.
Wenn die Nadel bei 200 steht soll als digitalen Wert auch 200 angezeigt
werden.
Kann mir hier einer helfen?
Gruss
Flat
Flat schrieb:> Hi,>> du meintest ja wenn das laufen nach und nach passieren soll, muss man> einen Timer integrieren, ich weiß nur nicht wie.
Hast du denn schon gefunden, wie ein Timer hier prinzipiell
funktioniert?
Ein Timer ist nichts anderes, als eine Möglichkeit, wie du in
regelmässigen Zeitabständen Code ausführen lassen kannst.
Und das kannst du jetzt mit einer zusätzlichen Variablen dazu benutzen,
eine nachlaufende Variable zu erzeugen.
Deine Tastendrücke setzen nicht mehr root.value auf einen bestimmten
Wert, sondern eine andere Variable. Nennen wir sie mal den Sollwert.
In der Timerfunktion vergleichst du bei jedem Aufruf diesen Sollwert mit
root.value und wenn root.value kleiner als der Sollwert ist, dann
erhöhst du es um zb. 1. Ist es größer dann verringerst du root.value um
1.
Was erreichst du dadurch: der für die Funktionalität 'Zeigerrotation'
zuständige Wert ändert sich in diskreten Zeiteinheiten (die durch den
Timer vorgegeben sind) immer nur um 1 Einheit. Und zwar nur dann, wenn
es eine Abweichung von diesem Sollwert gibt. root.value 'läuft diesem
Sollwert' hinterher.
Beispiel. root.Value sei 0
In deinen Tastenfunktionen setzt du den Sollwert auf 100 und die
Timerfunktion wird alle 0.01 Sekunden aufgerufen
Sekunden Sollwert root.value
0.00 0 0 Ausgangszustand
0.01 0 0 Jetzt drückst du die Taste
und setzt den Sollwert auf
100
0.02 100 0 value ist kleiner als der
Sollwert, Also wird value
erhöht
0.03 100 1
0.04 100 2
0.05 100 3
...
1.01 100 99
1.02 100 100 value und Sollwert sind
gleich, also passiert
nichts weiter
1.03 100 100
1.04 100 100 Du lässt die Taste los
und dein Code setzt daher
den Sollwert auf 0
1.05 0 100 jetzt ist value größer
als Sollwert, daher wird
in der Timerfunktion value
um 1 verringert
1.06 0 99
1.07 0 98
...
in der Timerfunktion wird value langsam dem Sollwert nachgeführt. Ist
value kleiner als der Sollwert, dann wird value um 1 erhöht. Beim
nächsten Aufruf der Timerfunktion kurze Zeit später passiert ja wieder
das gleiche, da wird dann value erneut erhöht, wenn es immer noch
kleiner ist. Ist value größer als der Sollwert den wird value
verringert.
Von Ausserhalb setzt du nicht mehr den value sondern den Sollwert. Der
Timermechanismus sorgt dann dafür, dass value langsam und in Schritten
sich diesem Sollwert annähert.
Im Endeffekt bedeutet das dann für dich: Du drückst eine Taste und der
Zeiger bewegt sich in kleinen Schritten auf den zugehörigen Wert. Sind
die Schritte klein genug und erfolgen sie schnell genug, dann "dreht"
dein Zeiger entsprechend auf den Sollwert.
Aber erst mal musst du rausfinden, wie du da einen Timer ins System
kriegst, wie du ihm sagst, in welchen Zeitabständen welcher Code
ausgeführt werden soll. Jetzt bist du drann die Doku zu durchforsten,
wie das geht.
Hi,
sorry das ich mich so spät melde, hatte noch eine Menge zu tun.
Super!!! Vielen dank nochmal für deine Antwort. Jetzt kann ich es mir
wenigstens vorstellen, wie das geht. Ich mach mich die Tage dann an die
Arbeit, ich schreib dann den Quellcode hier rein, wenn ich was
gescheites zusammengebastelt habe :)
Was ich immer Fragen wollte, also folgendes bei meinem Rechner zu Hause
ruckelt der Zeiger wenn es bewegt wird. Und wenn ich beide Zeiger bewege
ist es meist schlimmer. Die Zeiger bleiben stehen und es stürzt ab.
Doch auf meinem Laptop funktioniert das ganze flüssig, okey es hat
etwas mehr Leistung als mein Rechner und hat eine Grafikkarte.
Der Rechner zu Hause, der hat nur eine OnBoard Grafikkarte, hat aber 4GB
Arbeitsspeicher und ein Prozessor mit 3GHz Dual Core, es ruckelt stark.
Liegt es an der Grafikkarte oder meint ihr der Prozessor ist auch
schwach?
Eventuell werde ich mir dann eine Grafikkkarte kaufen müssen.
Ich danke schonmal für eure Antworten.
Muss diese Seite echt loben, habe auch das gleiche in ein qt Forum
gepostet und mir wurde nicht oder unzureichend geholfen. Ihr seid super
:)
Flat schrieb:> Der Rechner zu Hause, der hat nur eine OnBoard Grafikkarte, hat aber 4GB> Arbeitsspeicher und ein Prozessor mit 3GHz Dual Core, es ruckelt stark.
Könnte eine Sache des Grafiktreibers sein.
Grundsätzlich hast du mit 3Ghz eine Rechenleistung an der Hand, die für
die meisten Menschen unvorstellbar hoch ist. OK, das BS frisst dir da
wieder vieles weg und durch die diversen Softwareschichten wird das
ganze auch nicht schneller. Aber meistens ist das eine Treibersache und
ob der Treiber die vorhandene Hardware gut ausnutzt.
Hmm an den treibern kann es nicht liegen, Ich habe die aktuellsten
Treiber installiert schon vor dem aufsetzen von Windows, und das ist
grad mal ein Monat her. Vielleicht liegt es ja doch an der
Onboard-Grafikkarte.
Ich weiß ich frag zuviel aber kam bei diesen Sache nicht weiter.
Ich habe auch einiges im Internet darüber gefunden aber, hat nicht so
recht funktioniert. Es geht darum, dass ich die Anwendung die ich
erstellt habe an einem anderen Rechner ausführen möchte. So nun habe ich
herausgefunden, dass ich das dynamisch linken muss und die dazugehörigen
dlls in den Ordner mit einfügen muss, habe ich auch soweit gemacht. Wenn
ich jetzt die exe Datei starte bekomme ich ein weißes Fenster. Was mache
ich falsch.
Habe die folgenden Dlls reingepackt:
libgcc_s_dw2-1.dll
mingwm10.dll
QtCore4.dll
QtDeclarative4.dll
QtGui4.dll
QtNetwork4.dll
QtScript4.dll
QtSql4.dll
QtXmlPatterns4.dll
Wenn ich diese Dlls nicht reinmache, gibt der mir ne Fehlermeldung,
nachdem ich sie alle nacheinander reingemacht habe, zeigt es mir nun ein
weißes Fenster an. Wisst ihr was noch fehlt?
Hi,
hab es jetzt hinbekommen, die zeigerstellung digital anzeigen zu lassen,
dafür habe ich die Winkelstellung des Zeigers genommen.
Doch jetzt habe ich das Problem das es mir den Wert in Komma anzeigt,
also wie im Bild angezeigt. Wie kann ich es ohne Komma darstellen
lassen?
1
Text {
2
id: myText
3
x: 167
4
y: 139
5
width: 107
6
height: 45
7
text: zeigerRotation.angle
8
font.family: "Helvetica"
9
font.pointSize: 24
10
color: "red"
11
}
@ ich
danke für deine Antwort,
ich bekomme leider keine Fehlermeldung, der mich weiterbringt.
Es öffnet sich wieder ein weißes Fenster, doch es tut sich nichts...
Weisst du vielleicht was noch fehlt oder was ich falsch mache?
Nachtrag:
benutze Math.round(x) anstatt .toPrecision(x).
Zum Ausführen auf einem anderen Rechner:
hast du die .qml Dateien und die verwendeten Bilder auch auf den anderen
Rechner kopiert?
Hi,
Vielen Dank für deine Antwort.
Habe das jetzt das mit der digital Anzeige hinbekommen, indem ich
1
zeiger2Rotation.angle.toFixed()
geschrieben habe.
Kannst du vielleicht noch reinschauen, wie ich das mit dem dynamisch
linken machen muss. Ich stell dir das Projekt hier zur Verfügung.
Der Blinker funktioniert auch nicht so richtig, wollte es eigentlich so
machen das wenn ich auf Links drücke auf der Tastatur das es Links
blinkt, wenn ich nochmal Links drücke soll das blinken aufhören. mit
Rechts das gleiche.
Für Anregungen, Ratschläge und Tipps wäre ich euch sehr dankbar :)
Gruss
Flat
Okey das mit dem Blinker habe ich jetzt hinbekommen es geht.
hier der code :
1
2
3
onArrowChangedChanged:{
4
// console.log("in arrow change");
5
blinkerTimer1.stop();
6
blinkerTimer2.stop();
7
blinkerTimer3.stop();
8
if(arrowChanged==3){
9
leftArrowOn=true;
10
rightArrowOn=false;
11
blinkerTimer3.start();
12
return;
13
}elseif(arrowChanged==2){
14
leftArrowOn=false;
15
rightArrowOn=true;
16
blinkerTimer2.start();
17
return;
18
}elseif(arrowChanged==1){
19
leftArrowOn=true;
20
rightArrowOn=true;
21
blinkerTimer1.start();
22
return;
23
}elseif(arrowChanged==0){
24
leftArrowOn=false;
25
rightArrowOn=false;
26
return;
27
}
28
29
}
30
31
32
Timer{
33
id:blinkerTimer1
34
interval:500;
35
repeat:true
36
onTriggered:{
37
if(leftArrowOn==false||rightArrowOn==false){
38
leftArrowOn=true;
39
rightArrowOn=true;
40
}
41
else{
42
leftArrowOn=false;
43
rightArrowOn=false;
44
}
45
}
46
}
47
48
49
Timer{
50
id:blinkerTimer2
51
interval:500;
52
repeat:true
53
onTriggered:{
54
if(rightArrowOn==false||
55
rightArrowOn==false&&leftArrowOn==true){
56
leftArrowOn=false;
57
rightArrowOn=true;
58
}
59
else{
60
leftArrowOn=false;
61
rightArrowOn=false;
62
}
63
}
64
}
65
66
Timer{
67
id:blinkerTimer3
68
interval:500;
69
repeat:true
70
onTriggered:{
71
if(leftArrowOn==false||
72
rightArrowOn==true&&leftArrowOn==false){
73
leftArrowOn=true;
74
rightArrowOn=false;
75
}
76
else{
77
leftArrowOn=false;
78
rightArrowOn=false;
79
}
80
}
81
}
Einfach in die Blinker.qml Datei rein kopieren
In die Main.qml kommt das rein. Dann muss es funktionieren.
1
Blinker{
2
id:blinker1
3
x:0
4
y:4
5
anchors.verticalCenterOffset:4
6
anchors.horizontalCenterOffset:0
7
anchors.centerIn:parent
8
focus:true
9
10
Keys.onRightPressed:{
11
12
blinker1.arrowChanged=2;
13
14
}
15
Keys.onLeftPressed:{
16
17
blinker1.arrowChanged=3;
18
}
19
Keys.onDownPressed:{
20
blinker1.arrowChanged=0;
21
}
22
Keys.onSpacePressed:{
23
blinker1.arrowChanged=1;
24
}
25
26
}
Vielleicht habe ich es etwas umständlich gemacht aber hauptsache es
funktioniert erst einmal :)
Könnt ihr mir vielleicht noch helfen, wie ich das mit dem dynamisch
linken machen muss. Das Projekt steht zur Verfügung. Ich wäre euch sehr
dankbar dafür.
Gruss
Flat
Dein Problem ist nicht das dynamische linken, sondern vermutlich die
Tatsache das QML eine Interpretersprache ist. Was heißt, dass deine QML
Dateien erst zur Programmlaufzeit interpretiert werden.
Wenn du die kompilierte Programmdatei (*.exe) an einem anderen Ort
ausführen möchtest, hast du nun zwei Möglichkeiten.
Zum einen kannst du deinen QML/ Ordner (*) zusammen mit den DLL Dateien,
in den selben Ordner wie deine Programmdatei kopieren.
Falls du lieber alles in einer Datei hast, kannst du stattdessen auch
das Qt Ressourcen System nutzen, um deinen QML/ Ordner als Binärdaten
mit in deine Programmdatei zu packen (linken).
Eine Anleitung dazu findest du unter:
http://doc.qt.nokia.com/4.7-snapshot/qtbinding.html#managing-resource-files-with-the-qt-resource-system
* Der Ordner welcher die gesamten .qml Dateien sowie die verwendeten
Bilder enthält.
@ ich
Vielen dank für deine ausführliche Antwort.
Ich habe noch ein anderes Problem, was ich nicht gebacken bekomme.
Und zwar möchte ich die Tacho nadel mit einem Mikrocontroller
ansprechen, sprich wenn ich auf ein Taste vom Mikrocontroller drücke
soll die Nadel rotieren, habe bis jetzt immer die Tastatur benutzt.
Über die serielle Schnittstelle RS-232 soll der Mikrocontroller
angesprochen werden.
Die Kommunikation über die Mikrocontroller seite habe ich soweit,
Nun möchte ich die Daten, die vom Mikrocontroller geschickt werden über
den ComPort mit QT lesen. Ich habe einige Programme gefunden, doch ich
bekomme bei jedem Programm, die ich kompiliere eine Fehlermedlung, dass
die include Dateien nicht gefunden werden können, obwohl sie in dem
richtigen Ordner vorhanden sind.
Ich lade euch mal das Programm hier hoch.
Ich bin genau den schritten gefolgt wie im Link. Ich verstehe irgendwie
nicht wie ich das mit dem Build Ordner und qmake und make ausführen
soll.
Nachdem ausführen kommt die Fehlermedlung
Warnung:Unable to find file for inclusion \src\qt4support\serialport.prf
[[http://qt-project.org/wiki/QtSerialPort#b55bbb687c599634cc785869b9167639]]
Vielleicht habt ihr auch andere funktionierende Programme.
Ich hoffe ihr könnt mir weiterhelfen, bin hier am verzweifeln...
Gruss
Flat
Hallo Flat,
bei QT Fragen ist das qtforum.de besser geeignet.
Zur Kommunikation eignet sich anscheinend qextserialport am besten.
Suche mal danach.
In der qextserialport sollte es sogar über Signale und Slots
funktionieren.
Ich bin auch gerade dabei diese zu testen.Ich habe erstmal die Version
1.2
für QT4 benutzt.
Oder:
Irgendwo im Netz gibt es eine Qarduino 2.zip Datei.
Dort ist auch eine Kommunikation mit rs232 eingebaut.
Allerdings wie ich gesehen habe nicht mit Signale und Slots.
Links:
http://docs.qextserialport.googlecode.com/git/1.2/qextserialport.htmlhttp://docs.qextserialport.googlecode.com/git/1.2/index.html
Allerdings mußte ich auch in den .h Dateien etwas herausnehmen,da ich
unter Linux entwickle.
Jogibär
Die Anleitung auf die Du verlinkt hast ist wohl etwas älter und stimmt
nicht mehr ganz.
Erstelle im Ordner mit der serialport.pro einen neuen Ordner mit z.B.
dem Namen build.
Wechsle in den eben erstellten Ordner:
1
cd build
Führe qmake aus:
1
qmake ../serialport.pro
Führe make aus:
1
make
2
make install
unter Windows musst du das ganze eventuell dann nochmal mit Config=
release ausführen. (Den Inhalt des Ordners build vorher löschen.)
Also:
Hi Jogibär,
danke für deine Antwort.
Ich kenne die Seite qtforum.de auch, habe da auch mal da Fragen
reingestellt aber mir wurde nicht bzw. unzureichend geholfen.
Hier wurde mir immer geholfen, auch wenn es keine explizite Seite für QT
ist.
Wir sollten vielleicht die Seite umbenennen, mikrocontroller_QT.net oder
so :)
Spass bei Seite kannst du mir vielleicht dein Programm zukommen lassen,
wenn du es zum laufen bekommen hast.
Werde die Sachen mir mal genau anschauen und hier rein posten wenn es
funktioniert.
Gruss
Flat
Flat schrieb:> Hi Jogibär,>> danke für deine Antwort.> Ich kenne die Seite qtforum.de auch, habe da auch mal da Fragen> reingestellt aber mir wurde nicht bzw. unzureichend geholfen.
Ja,das kann ich leider auch bestätigen.
Die sind dort etwas elitär.
Aber ab es gibt auch Personen, die ausgezeichnet antworten.
> Hier wurde mir immer geholfen, auch wenn es keine explizite Seite für QT> ist.> Wir sollten vielleicht die Seite umbenennen, mikrocontroller_QT.net oder> so :)> Spass bei Seite kannst du mir vielleicht dein Programm zukommen lassen,> wenn du es zum laufen bekommen hast.
Das Projekt ist etwas größeres.
Frag in ein paar Jahren noch mal nach ;-).
> Werde die Sachen mir mal genau anschauen und hier rein posten wenn es> funktioniert.>> Gruss>> Flat
Jogibär
Hi,
ich habe endlich ein funktionierendes Programm gefunden, dass auf die
serielle Schnittstelle zugreifen kann. Habe auch schon mit einem
Mikrocontroller Daten gesendet und mit dem Beispielprogramm die Daten
empfangen.
Nun zu meiner Frage, da ich mich nicht sonderlich mit C++ auskennen und
mich dafür in QML eingearbeitet habe, möchte ich wissen, ob ich nun was
ich in QML erzeugt habe in die c++ datei integrieren kann. Sprich mit
Signals und Slots
Ich möchte wenn ich jetzt vom Mikrocontroller auf die Taste draufdrücke
eine byte verschicken sagen wir mal (1111 1111), der Zeiger soll jetzt
bei diesem code anfangen zu laufen und wenn ich wieder loslasse soll es
wieder runterlaufen (0000 0000).
Ich habe im Programm das Beeispiel mit dem PortListener
herausgeschrieben.
Jetzt möchte ich wenn ich ein Signal von 1111 1111 bekomme den Zeiger,
was ich qml geschrieben habe per Signal und Slot bewegen.
Es hört sich vielleicht trivial an aber für mich der nicht so gute
Kenntnisse in c++ Programmieren hat ist es schon etwas aufwändiger,
daher würde ich mich für eure Tipps und Lösungsvorschläge freuen.
Ich habe das BeispielProgramm mit der Serielle Schnittstelle angehängt.
Das andere Programm womit die Zeiger bewegt werden können sind auch
weiter oben im Thread enthalten.
Hab nun das Problem, dass ich nicht weiß wie ich die Zeiger zum laufen
bringe, da ich alles in qml geschrieben habe und der Serial Port in c++
geschrieben ist.
Könnt ihr mir vielleicht sagen wie ich das mit einander verknüpfen kann.
Habe auch schon danach gegoogelt aber wurde nicht so richtig fündig bzw.
der Lösungsansatz ist mir nicht so richtig klar.
Habe das hier gefunden :
http://doc.qt.nokia.com/4.7-snapshot/qtbinding.html
Das was ich haben möchte ist den root.value Wert in c++ ändern wenn ein
Signal von der Seriellen Schnittstelle kommt.
Hier ist der Qml Code vom Zeiger:
@ ich
du konntest mir bis jetzt immer bei meinen Fragestellungen helfen.
hast du vielleicht ein Tipp wie man das Problem lösen kann.
Wäre dir sehr dankbar.
Freundliche Grüße
Flat
Hallo,
auf QML Properties kannst du z.B. mit QDeclarativeProperty zugreifen.
Beispiel:
Du erstellst in deinem QML root Objekt eine Property und weist diese
dann z.B. deinem Zeiger zu.
z.B. main.qml
1
import QtQuick 1.0
2
//! [imports]
3
4
//! [0]
5
Rectangle {
6
color: "#545454"
7
width: 1280
8
height: 600
9
focus: true
10
property int zeigerVal
11
12
// Dial with a slider to adjust it
13
Zeiger {
14
id: zeiger
15
anchors.centerIn: parent
16
value: zeigerVal
17
18
}
Im C++ Code kannst du nun mit QDeclarativeProperty diesen Wert
verändern:
#z.B. main.cpp
@ ich
Du bist mein Held.
Es funktioniert :)
Danke Vielmals.
Nun habe ich das Problem mit dem Byte senden, da ich später die Blinker
und die Zeiger einzeln ansteuern möchte, brauche ich einen kleinen
Quellcode mit dem ich dies Realisieren kann.
Wie kann ich die Propertys nun ändern wenn ich sagen wir mal ein byte
von 0x01 sende?
Ich hoffe ich habe mich verstandlich ausgedrückt.
Hoffe du kannst mir hierbei auch helfen.
Gruss
Flat
@ ich
danke für deine ausführliche Antwort.
Da ich nicht mich nicht so gut auf C++ basis auskenne, würde es mir sehr
helfen, wenn du mal in mein Programm reinschauen könntest.
Habe es mir ehrlich gesagt etwas einfacher vorgestellt oder ich sehe die
sache zu kompliziert.
Ich habe ein Klasse erstellt, die du vorgeschalgen hast, doch nun weiss
ich nicht genau, wie ich das mit dem Signals and slots verbinden soll
und dann noch die Empfangsroutine anpassen soll.
Für Tipps würde ich mich sehr freuen.
Als Anlage habe ich das gesamte Projekt angehangen, was ich bis jetzt
gemacht habe, lass dich nicht von den vielen qml Dateien irritieren,
habe sie nicht alle benutzt. Die Haupt Qml Datei ist die main.qml
Gruss
Flat
Guten Morgen,
kann mir hier jemand behiflich sein. Habe das Projekt angehangen.
Der Mikrocontroller schickt hier 0x10 für den Zeiger
und 0x20 für den Warnblink.
1
intmain(void)
2
{
3
//##### INIT ########
4
uint8_tstate=0;
5
UART_Init();
6
sei();//Global interrupt ein
7
8
// EMD("\nInitialisiert\n");
9
//##### ENDE INIT ########
10
11
DDRD=0;//Tasten-PORT auf Eingang
12
PORTD=255;//pullup
13
14
DDRB=255;//LED-PORT auf Ausgang
15
PORTB=255;//LED aus
16
17
// Initialisierung wie oben
18
19
while(1){
20
if((PIND&(1<<4))==0){// Schalter gedrückt
21
// state = (state + 1) % 2; // Zustand ändern
22
// PORTB = state?255:0; // und ausgeben (alle Pins)
23
// _delay_ms(1000); // 1 s warten
24
25
UART_sendByte(0x10);// Geschwindigkeitszeiger
26
27
}
28
if((PIND&(1<<7))==0){
29
30
UART_sendByte(0x20);//Warnblink
31
32
}
33
}
34
35
}
Nun möchte ich in der Empfangsroutine die den Code anpassen und die
Signals und Slots einfügen.
Kann mir einer dabei behilflich sein. Das gesamte Projekt habe ich
angehangen.
Gruss
Flat
ich habe den zeiger nun versucht mit dem folgenden Code zu bewegen, hat
leider nicht funktioniert :(
Ich kann den string auslesen mit dem Portlistener, doch der Zeiger
bewegt sich nicht
Mikrocontroller Seite:
while(1) {
if ((PIND & (1<<4)) == 0) { // Schalter gedrückt
UART_sendString("Zeiger");
}
if ((PIND & (1<<7)) == 0) {
UART_sendString("Warnblink");
}
}
Empfang des der main.cpp
QDeclarativeProperty property(view.rootObject(), QString("zeigerVal"));
QByteArray bytes;
if(bytes == "Zeiger" ){
property.write(100);
}
if (bytes == "" ) {
property.write(0);
};
Das Problem liegt wahrscheinlich das ich einen String wert schicke und
QByteArray char Werte weiterverarbeitet.
Wie kann ich jetzt die String Werte in char umwandeln oder char werte in
String.
Lieg ich mit meiner Vermutung richtig oder bin ich auf dem ganz flaschen
Weg??
Flat schrieb:> Empfang des der main.cpp>> QDeclarativeProperty property(view.rootObject(), QString("zeigerVal"));>>> QByteArray bytes;> if(bytes == "Zeiger" ){>
mir erschliesst sich nicht, wie da jetzt der Zusammenhang ist, dass in
'bytes' irgendwie magisch die Werte von der UART auftauchen. Warum
sollen die das tun?
Generell: verzichte darauf, ganze Wörter zu verschicken. Du hast keine
Garantie, dass von einem Leseversuch auf dem PC zum nächsten auch
tatsächlich das ganze Wort schon übertragen wurde. D.h. das ist
zusätzlicher Aufwand sicherzustellen, dass der Empfänger auch weiß, wann
eine Übertragung zu Ende ist und nichts mehr kommt. Der Sender hätte ja
auch "Zeigerlager" schicken können.
Am einfachsten ist es immer noch, wenn du dich auf 1-buchstabige
Kommandos beschränkst. Dann fällt dieses 'Problem' erst mal flach, denn
1 Buchstabe wird immer komplett übertragen, ehe ihn der Empfänger zu
Gesicht bekommt.
PS: Hast du eigentlich schon getestet, ob deine UART Übertragung
grundsätzlich funktioniert? Sprich: In einem Terminal-Progamm
nachgesehen, ob da auch wirklich das ankommt, was ankommen sollte? Das
ist nämlich keineswegs selbstverständlich und wenn die Kommunikation
grundsätzlich nicht funktioniert, dann brauchst du auf höheren Ebenen
erst mal nicht weiter machen, solange dieses Problem nicht gefixt ist.
Auch solltest du schrittweise vorgehen. Nicht gleich die komplette Kette
vom µC zum Zeigerinstrument in Betrieb nehmen und hoffen, das da alles
funktioniert. Und hinterher großes Kopfkratzen, warum nichts
funktioniert. Erst mal mit einem Terminalprogramm nachsehen, ob die
Kommunikationsebene funktioniert. Dann mit einem Programm sich an diese
Kommunikation binden und empfangene Zeichen einfach so wie sie empfangen
wurden ausgeben. Und erst dann mit einem Programm die Werte (sofern die
vorhergehenden Tests erfolgreich waren) an das Zeigerinstrument
weitergeben. Auf die Art baut jede Erweiterung immer auf bereits
getesteten Komponenten auf von denen man weiß, dass sie funktionieren.
Gehts trotzdem nicht, dann muss das Problem irgendwo in dem Teil sein,
der gerade neu dazu gekommen ist. Und je weniger neu dazu kommt, desto
weniger Möglichkeiten für Probleme und Fehler gibt es.
Karl Heinz Buchegger schrieb:> Flat schrieb:>>> Empfang des der main.cpp>>>> QDeclarativeProperty property(view.rootObject(), QString("zeigerVal"));>>>>>> QByteArray bytes;>> if(bytes == "Zeiger" ){>>>> mir erschliesst sich nicht, wie da jetzt der Zusammenhang ist, dass in> 'bytes' irgendwie magisch die Werte von der UART auftauchen. Warum> sollen die das tun?>> ...
Ergänzung:
Du hast in deiner Empfangsroutine ja bereits den passenden Emfangsslot
mit entsprechender Ausgabe.
1
//PortListener.cpp
2
3
voidPortListener::onReadyRead()
4
{
5
QByteArraybytes;
6
inta=port->bytesAvailable();
7
bytes.resize(a);
8
port->read(bytes.data(),bytes.size());
9
qDebug()<<"bytes read:"<<bytes.size();
10
qDebug()<<"bytes:"<<bytes;
11
12
}
13
14
// Wenn du alle vorhandenen Bytes lesen möchtest, ist es allerdings sinnvoller es so zu schreiben:
15
16
voidPortListener::onReadyRead()
17
{
18
QByteArraybytes=port->readAll();
19
qDebug()<<"bytes read:"<<bytes.size();
20
qDebug()<<"bytes:"<<bytes;
21
22
}
Nachdem du also festgestellt hast, dass die Kommunikation mit einem
Terminalprogramm funktioniert, kannst du damit feststellen, ob dein
Programm die korrekten Daten empfängt.
Wenn das dann funktioniert, kannst du die weiter oben beschriebene
Klasse MyQmlInterface auch einfach weglassen und "view" direkt an
PortListener durchreichen. Die Implementierung erfolgt dann entsprechend
wie in MyQmlInterface dargestellt, nur das du die Signal-Slot Verbindung
nicht benötigst.
Allgemein:
Hi,
danke für die Antworten habe das mit den Terminal Programm getestet und
es funktioniert alles einwandfrei.
Ich habe jetzt beim senden eine 500ms delay eingesetzt, da das Programm
sonst mehrere Bytes empfangen hat statt nur "Z" .
hier ist das Beispiel
1
while(1){
2
if((PIND&(1<<4))==0){// Schalter gedrückt
3
4
UART_sendString("Z");
5
_delay_ms(500);
6
}
7
if((PIND&(1<<7))==0){
8
9
10
UART_sendString("W");
11
_delay_ms(500);
12
}
13
}
Im Programm funktioniert die Übertragung auch
also es zeigt mit in bytes read: 1
und bytes: Z an.
Doch ich weiss nicht wie ich die "view" an die den Portlistener
durchreichen soll. Also in main.cpp habe ich das reingeschrieben, doch
die bytes werden dann nicht zur Laufzeit aktualisiert. Ich möchte die
Property in Portlistener verändern können. Ich habe es bis jetzt nicht
hinbekommen.
1
QByteArraybytes;
2
if(bytes=="Zeiger"){
3
4
property.write(100);
5
}
6
if(bytes==""){
7
8
property.write(0);
9
10
};
Würde mich freuen, wenn du mir hierbei auch helfen könntest.
Gruss
Flat
Du kannst es im Prinzip so machen, wie ich es in
Beitrag "Re: Tachoanzeige in Qt programmieren"
für MyQmlInterface beschrieben habe.
Also:
- Du erstellst dir in PortListener entsprechende Membervariablen für
deine QML Properties.
- Du erweiterst den PortListener Konstruktor entsprechend, um dein QML
View zu übergeben.
- Du initialisierst im PortListener Konstruktor deine Property Variablen
entsprechend mit der übergebenen View.
- Nun kannst du in PortListener::onReadyRead, deine Propertys schreiben
und lesen.
Ich habe das "view" in Portlistener eingesetzt , doch ich bekomme keine
Fenster wenn ich in der main.cpp das "view" auskommentiere. Und wenn ich
die view in main einsetze dann klappt es nicht die myProp1 Werte in
Portlistener zu ändern. Ich habe dein Lösungsansatz glaub ich nicht
richtig verstanden. Sorry nochmal wenn ich viele doffe Fragen stelle...
Du kannst für eine Klasse zwar mehrere Konstruktoren definieren, beim
Erstellen des Objekts, wird aber immer nur einer dieser Konstruktoren
ausgeführt. Da du beim Erzeugen eines PortListener Objekts allerdings
sowohl die serielle Schnittstelle, als auch deine QML Properties
initialisieren möchtest, benötigst du einen Konstruktor, welcher sowohl
die serielle Schnittstelle, als auch deine QML Properties initialisiert.
Das Erzeugen und Anzeigen deiner QML view erfolgt also weiterhin in main
und PortListener wird mit dessen Konstruktor nur eine Referenz auf das
view Objekt übergeben, mit welcher er seine QDeclarativeProperty Member
initialisiert.
Alternativ kannst du in PortListener auch eine Initialisierungsmethode
für deine QDeclarativePropertys erstellen, welche genauso als Parameter
eine Referenz auf dein QML view erhält. Allerdings musst du dann
sicherstellen, dass die QDeclarativePropertys in PortListener erst
verwendet werden, nachdem Sie auch initialisiert wurden.
Ja ich hab verstanden das im main.cpp das Object nur von der Qml
initalisiert wurde. Die Frage ist jetzt, wie ich die Serielle
schnittstelle auch in main initialisiere sodass die Werte verändert
werden.
Ich komme nicht mehr weiter.
Kannst du eventuel einen kurzen quellcode schreiben, wäre dir sehr
dankbar.
Main bleibt im Grunde so wie gehabt. Du musst nur dem Konstruktor von
PortListener zusätzlich noch view übergeben und die PortListener Klasse
natürlich noch entsprechend anpassen.
main() sieht dann in etwa so aus:
Ich habe jetzt die main.cpp wie du beschrieben hast erstellt.
Die Portlistener.h habe ich so wie du es beschrieben hast erstellt
Beitrag "Re: Tachoanzeige in Qt programmieren"
Doch die myProp1 kann ich in public nicht so schreiben, wie du es
definiert hast.
die Portlistener.cpp sieht so aus
Ich weiss nicht ob ich es so richtig geschrieben habe.
Kannst du bitte in den Code reinschauen und mich eventuel verbessern.
Ich danke dir schonmal im voraus.
Hallo,
Du meintest das nur ein Konstruktor ausgeführt wird.
Wie kann ich also die view in dem Konstruktor Portname ausführen?
Also wie initaliere ich die Propertys in Portname?
So wie ich es geschrieben habe funktioniert es nicht
Ich komme ehrlich gesagt nicht weiter:(
Kannst du mir bitte helfen ?
Ich habe es jetzt doch hinbekommen.
Danke nochmal vielmals für deine Hilfestellung :)
Ich habe den Zeiger jetzt auf zwei Tasten zugewiesen.
Ich möchte gerne wenn ich auf eine Taste drücke das der Zeiger hoch geht
und wenn ich loslasse, dass es wieder runterläuft.
Hat einer ne Idee wie man es machen könnte?
Hallo,
ich habe noch ne Frage.
Es geht darum das ich die Anwendung jetzt auf meinem Display anzeigen
möchte. Das Display ist ein Chinch display wobei ich die Auflösung
anpassen muss, damit das Rundtacho auch Kreisförmig angezeigt wird. Ich
habe nun das Bild so weit gedämpft das das Rundtacho jetzt auf dem
Display Kreisrund dargstellt wird, doch jetzt habe ich Probleme mit dem
Zeiger, da der Tacho in wirklichkeit Eiförmig ist, laufen die Zeiger aus
dem Tacho raus.
Gibt es ne routine, wo ich den Zeiger entsprechend dem Tacho rotieren
lassen kann. Ich hoffe ihr habt mich richtig verstanden.
Ich wäre sehr dankbar, wenn ihr mir auch hierbei helfen könntet.
Der Code für die Zeiger rotation bei einem Kreisrundem Tacho.
Ich brauch einen Code für für das entsprechende TAcho das eingefügt
worden ist.
Hi,
habe hier in youtube sowas ähnliches
http://www.youtube.com/watch?v=6QZBft8lBOI
Die Nadel läuft nicht über das Rundinstrument.
Es passt sich an die Struktur des Rundinstrumentes an.
Weiss vielleicht einer wie man so etwas realisiert ?
Ich suche schon so lange danach, habe leider nichts gefunden
Gruss
Flat
Hallo,
Habe mein Problem jetzt so gelöst indem ich mein Rundtacho als Ellipse
genommen habe, sodass das es auf dem Display, was ich habe als Kreis
angezeigt wird.
Damit der Zeiger nicht über die Ellipse läuft, habe ich über die
Ellipsengleichung die Zeigerlänge berechnet und es passt sich an das
Rundtacho an.
Ellipsengleichung: (x²/a²) + (y²/b²) = 1
a und b sind die Durchmesser des Rundinstruments, wo der Zeiger entlang
laufen soll.
x = a* cos (Winkel)
y = b* sin (Winkel)
Nun habe ich die Zeigerhöhe ausgerechnet indem ich die Formel auf y
umgestellt habe und durch den Satz des Pythagoras habe ich die
Zeigerhöhe herausgefunden.
z = Wurzel(b² + cos(Winkel)² (a²-b²)) z:Zeigerhöhe
In der Theorie sollte es funktionieren. Doch als ich die Formel versucht
habe zu implementieren, beim drehen des Zeigers, verändert sich zwar die
höhe aber es wird ständig größer und kleiner.
Ich bin mir sicher das der Fehler mit dem Winkel und der cos funktion
was zun tun hat, aber ich weiss nicht was falsch gemacht habe.
Ich wäre euch sehr dankbar wenn ihr reinschauen und mir sagen könntet,
was genau flasch ist?
Danke
Gruss
Flat
Ich habe den Fehler jetzt gefunden, Qt berechnet die Winkel in radiant.
Ich habe den Winkel von von Grad in Radiant umgewandelt und jetzt
funktioniert es.
rad = 90 * pi /180
Gruss
Flat
Hallo,
habe noch ne Frage wegen der Zeigerstellung, die ich digital Anzeigen
lassen möchte.
Ich habe tachoZeigerRotation.angle also den Winkel genommen um die
Zeigerstellung digital Anzeigen zu lassen. Doch der Winkel geht von -160
bis 160 Grad. Ich möchte jetzt die Minima und maxima so wählen das ich
min 0 und max 240 km/h haben möchte.
Hier ist die der Code für die Rotation von -160 bis 160 Grad
Hier der Code für die Anzeige in Digital.
Wie kann ich mit der Funktion Math.min und Math.max die minima und
maxima einstellen so das ich am Ende bei der Zeigerstellung bei -160° =
0 km/h und bei +160°= 240 km/h habe?
Vorweg, ich finde es super mit welcher Geduld und Beharrlichkeit Du
deine Probleme löst. Ich denke Du kommst mit dem folgenden Tips selbst
auf die Lösung: Du möchtest 0..240 nach -160..160 Umrechnen. Das ist
eine relative simple Abbildung, um genau zu sein musst Du dazu einmal
Multiplizieren und einmal subtrahieren. Denkanstoß:
0 * A - B = -160
240 * A - B = 160
Ich danke für deine Antwort,
doch ich habe zur Zeit einen hänger,
weiss ehrlich gesagt nicht wie du das meinst...
Kannst du es mir vielleicht verständlicher erläutern ?
Naja, Du musst deine Geschwindigkeit nehmen, diese mit 'A'
multiplizieren und danach 'B' davon abziehen und schon hast du den
Winkel. 'A' und 'B' sind zwei Zahlen die Du mit den beiden Gleichungen
oben bestimmen kannst.
Ich habe dich schon verstanden aber ich weiss nicht wie man das
implementiert , habe es schon versucht aber meine versuche sind leider
gescheitert. Kannst du vielleicht ein paar Zeilen quellcode hier
anhängen, das wäre super von dir.
Ich danke dir schon mal im Voraus.
Gruss
Flat
Jetzt bin ich etwas verwirrt. Die Zeiger funktionieren also wie
gewünscht? Dein Problem ist die Digitale Ausgabe? Das hat aber erstmal
nichts mit den Minimum- und Maximum-Werten des Zeigerwinkels zu tun.
Diese hängen ja nur von deiner Tachografik ab. Du willst also vom Winkel
auf die Geschwindigkeit umrechnen? Das ist wie oben nur andersherum
gerechnet. Du musst also in deinem Text Element für den Text eintragen:
((Winkel + B) / A).toFixed(0)
Denke daran, A und B sind nur Zahlen.
Ich danke dir es hat jetzt funktioniert jetzt.
Was man alles mit der Mathematik lösen kann :)
Ich habe etwas zu kompliziert gedacht glaube ich:)
Danke vielmals.
Gruss
Flat
Hallo,
habe nochmal eine Frage, wo ich nicht genau weiss, wie ich es machen
soll.
Es geht darum, dass ich jetzt vom Mikrocontroller bytes schicke. Es
zählt von 0-240 hoch und dann wieder runter in einer Schleife, diese
möchte ich in
1
myProp1.write(bytes);
reinschreiben, sodass der GeschwZeiger von 0 bis 240 läuft, doch ich
bekomme wenn ich die bytes Empfange Ascii Code, doch ich möchte es in
Dezimal haben.
In
1
bytes
sind die empfangenen Zahlen drin
Hier ist der Code, wo ich
5 monate = neu? Sorry, aber guck mal in ein Buch oder Tutorial unter dem
Stichwort.
(Ergänzung: ist nicht 100 % perfekt wie mir inzwischen auffällt, da
theoretisch die Codierung nicht ASCII sein muss... aber tuts definitiv)
Ich habe hier ein Beispielprogramm gefunden namens speedo.
http://community.qnx.com/sf/discussion/do/listPosts/projects.qt/discussion.general.topc21389?_pagenum=1
Es ist ein Tachoinstrument programmiert worden.
Ich bekomme leider das Prgramm nicht zum laufen.
Ich habe reingeschaut und habe festgestellt das der Pfad für die qml
Datei
nicht richtig ist habe es entsprechend geändert aber zeigt mir nur ein
weisses Fenster an wenn ich starte.
Kann mir vielleicht jemand sagen, wo der Fehler ist.
Danke im Voraus
Hi ,
habe das Problem, dass die Analog Anzeige nicht mit der Digitalen
Anzeige übereinstimmt da ich den Kreis als Oval dargestellt habe.
Ich habe die Geschwindigkeiten in Excel aufgenommen und habe es in einem
Diagramm dargestellt. Man sieht das die Kennlinie bei 0°,90°,180°,270°
und 360° einen Nulldurchgang hat , also das die Digitale Werte mit dem
analogen Zeigerinstrument bei diesen Winkeln übereinstimmmen.
Nun zu meiner Frage kann ich die Kennlinie linearisieren , wenn ja wie
kann ich den Winkel in Qt Mathematisch so beschreiben das es mit der
digitalen Anzeige passt.
Ich danke für jeden Lösungsvorschlag
hier ist der Code für das Zeigerinstrument