Hallo
Ich habe schon ein wenig hier im Forum gestöbert und war immer sehr
beeindruckt von der Hilfeleistung die hier auf die Beine gestellt wird.
Ich habe auch schon gelesen, dass einige von euch mit QT Erfahrung
haben, ebenso wie mit dem Arduino. Ich brauche von beidem etwas.
Mir geht es darum, dass ich Daten vom Arduino nach QT bekommen will.
Genauer gesagt habe ich eine ganze Reihe von Sensoren die Temperaturen
messen, diese wiederum lese ich momentan vom Display ab und trage sie in
Tabellen ein, diese verwandle ich mit QT und dem QT plotting widget in
eine Grafik. Nun würde ich gerne das Auslesen automatisieren.
Dazu habe ich mir das QextSerialPort Projekt versucht zu eigen zu
machen. Ich habe mir also das latest stable 1.2 runtergeladen
(http://docs.qextserialport.googlecode.com/git/1.2/index.html) und
versuchte es so wie im Unterpunkt: Usage(1): Source Code Only
einzubauen. Das hat aber glaube ich nicht ganz so gut hingehaut wie die
Seite das dort so sagt ...
So sieht meine *.proj Datei aus:
Ich wollte das mal kompilieren, aber das macht der Compiler nicht mit.
Der Forenbeitrag hier: Beitrag "Daten mittels QextSerialPort senden"
hat außerdem noch die ganzen Einstellungen für Baudrate usw mit drinnen
unter port Einstellungen. Dahin komme ich aber gar nicht, mein Kompiler
sagt:
1
..\sensor_auslesen\mainwindow.cpp: In member function 'void MainWindow::button_WERT_pressed()':
2
..\sensor_auslesen\mainwindow.cpp:27:40: error: 'myClass' was not declared in this scope
3
..\sensor_auslesen\mainwindow.cpp:28:16: error: no matching function for call to 'QextSerialPort::open()'
4
..\sensor_auslesen\mainwindow.cpp:28:16: note: candidate is:
5
In file included from ..\sensor_auslesen\mainwindow.cpp:3:0:
> connect(port, SIGNAL(readyRead()), myClass, SLOT(onDataAvailable()));
wer oder was ist 'myclass'?
Üblicherweise connected eine Member Funktion die Signale an
Member-Funktionen derselben Klasse (also MainWidow). Du willst dann
daher das Signal an einen Slot von this geroutet haben
connect(port, SIGNAL(readyRead()), this, SLOT(onDataAvailable()));
> void MyClass::onDataAvailable()
Diese Funktion ist daher dann ein Member von MainWindow. Und sie ist
nicht einfach irgendeine Member-Funktion sondern muss bei den Slots in
der Klassendeklaration aufgeführt sein, damit sie von connect gefunden
werden kann.
> QextSerialPort *port = new QextSerialPort("COM3");> ...> void MainWindow::onDataAvailable()> {> QByteArray data = port->readAll();
Allerdings wird sich diese Funktion dann schwer tun, auf eine Variable
(port) zuzugreifen, die als lokale Variable in einer anderen Member
Funktion definiert wurde. port muss schon als Member-Variablen der
Klasse definiert sein, damit sie aus mehreren Funktionen heraus
benutzbar ist.
> Habe ich das aus dem Example mit dem Code falsch verstanden eventuell?
Ohne jetzt frech sein zu wollen. Aber das Problem scheint nicht beim
Beispiel zu liegen. Das Problem scheint eher so geartet, dass dir
elementare Grundlagen der C++ Programmierung fehlen. Da helfen dann auch
ein paar QT-Beispiele nicht weiter.
Das habe ich gestern in meiner Müdigkeit nicht mehr richtig gecheckt :)
Danke jedenfalls für die Hilfe - ich habe leider nur Basics in C++,
arbeite hauptsächlich mit Fortran (noch lange vor Klassen und Signalen
...).
Ich habe das nun so gelöst, und das funktioniert auch:
Jetzt kann ich am Port lauschen und krieg auch Daten rein. Soweit so
gut. Allerdings habe ich nun ein anderes Problem gefunden:
Ich schicke an das GSM Modul das am Arduino ist ein AT - mittels
Funktioniert alles auch so weit ganz gut, nur bin ich beim Hantieren mit
Terminal (https://sites.google.com/site/terminalbpp/) draufgekommen,
dass man unbedingt ein Carriage Return mitschicken muss, damit man zb
auf AT ein OK bekommt.
Ich habe vermutlich zu naiv gedacht, als ich mir dachte dass ich anfangs
einfach mein QPlainTextEdit Elemt hernehme und in die erste Zeile das AT
schreibe und dann mit Enter in die zweite Springe und das dann an das
GSM Modul schicke. Leuchtet auch irgendwie ein, vermutlich liest der
einfach eine Zeile und will alles da drin haben ... Ich habe so schwach
im Hinterkopf, dass ich da ein \r\n unter Windows brauche. Das habe ich
auch versucht, allerdings habe ich das auch eins zu eins dann so in der
Ausgabe stehen gehabt. Ich hab nun ein wenig angefangen rumzuprobieren
und habe es mit QByteArray::fromHex und ähnlichem versucht, bin aber
nicht zum richtigen Ergebnis gelangt. Wie geht das am einfachsten?
Raphael schrieb:> nicht zum richtigen Ergebnis gelangt. Wie geht das am einfachsten?
port->write(ui->sendEdit->toPlainText().toLatin1())
port->write( "\n" );
zu einfach?
Klingt so einfach, dass es stimmen muss :)
Allerdings habe ich das Problem, dass meine Konsole keine Kommandos
empfängt scheinbar. Ich tue mir da ein wenig schwer mit dem debuggen,
weil ich vom GSM Modul ja nur dann eine Antwort kriege, wenn alles
geklappt hat...
So versuche ich zeichen an meinen COM Port zu schicken (kann ich davon
ausgehen, dass die Verbindung gut funktioniert, wenn ich die Daten vom
COM lesen kann, oder kann es sein, dass trotz gutes Lesens die
Verbindung nicht alle Parameter erfüllt um Schreiben zu können?) -
schreiben kann ich damit aber nicht :(
Raphael schrieb:> Achja, warum eigentlich nur ein \n und kein \r\n ?
Wenns mit \n alleine nicht geht, kannst du ja immer noch ein \r\n
ausprobieren.
Leider gibt es da historisch gesehen einen Wildwuchs, ob CR alleine
reicht, oder ob es CR+LF sein muss.
Noch ein Tip:
Es gibt für den PC Programme, die sich "Port Monitor" nennen.
Die protokollieren alles mit, was über die Schnittstelle rein/raus geht.
D.h. da kannst du dir ganz einfach live ansehen, wie andere Software das
Modem ansteuert, welche Bytes hin und her gehen bzw. was dein Programm
im Gegensatz dazu tatsächlich macht.
http://www.google.at/#hl=de&gs_rn=4&gs_ri=psy-ab&cp=8&gs_id=u&xhr=t&q=port+monitor&es_nrs=true&pf=p&sclient=psy-ab&oq=port+mon&gs_l=&pbx=1&bav=on.2,or.r_gc.r_pw.r_qf.&bvm=bv.42661473,d.d2k&fp=f5c6d5bbbc0cbbba&biw=1253&bih=642
ist recht nützlich, um Probleme mit Übertragungen auf der seriellen
Schnittstelle schnell und einfach auf den Grund zu gehen. Denn wie immer
gilt: Was du programmieren willst und was du programmiert hast, das sind
oft 2 verschiedene Paar Schuhe :-)
Ich habe nun mit Serial Port Monitor 4.0 den COM Port überwacht und so
die Ausgaben zwischen Terminal und meinem Code verglichen. Dabei ist mir
dann aufgefallen, dass das CR von Terminal einem \r entspricht, nicht
einem \n (nur nebenbei zu erwähnen, falls jemand mal mit google das
Problem hier findet ...). Nun antwortet mein GSM Modul auch schon brav.
Ihr seid hier super!
Ein hoffentlich kleineres Problem habe ich nun aber doch noch
aufgetrieben :(
Ich habe nun zum Senden einer SMS auch das Problem, dass ich ein STRG-Z
senden muss. Das habe ich mir einfacher vorgestellt, als es nun
scheinbar ist... ich versuche es wie folgt, dabei stürzt aber einfach
nur das GSM Modul ab und beginnt wieder mit
+SIND: 1
+SIND: 10,"SM",1,"FD",1,"LD",1,"MC",1,"RC",1,"ME",1
> wo liegt hier mein Gedankenmurks?
Ich hätt mal gesagt, dass du
zuerst den Ctrl-Z anhängen willst
dann den \r anhängen willst
und du erst dann von diesem Gesamtergebnis ein toLatin1 machen willst.
Reihenfolge!
Enteder du arbeitest mit Bytes, die einen ASCII COde haben
Oder du arbeitest mit den QT String Funktionen.
Aber wildes mischen ist ganz schlecht.
Es spricht doch nichts dagegen, dass du 3 Ausgaben anstelle von einer
machst
Das ist einfach, übersichtlich und man kann mit einem Blick erkennen,
was eigentlich ausgegeben wird. Und langsamer ist es ganz sicher auch
nicht. Das ist sowieso I/O begrenzt.
Zu banal?
Karl Heinz Buchegger schrieb:> Raphael schrieb:>>>> if(port->isOpen() && !ui->sendEdit->toPlainText().isEmpty()) {>> port->write(ui->sendEdit->toPlainText().toLatin1().append(QChar(0x001a))
.append("\r"));
>> > wo liegt hier mein Gedankenmurks?>>> Ich hätt mal gesagt, dass du> zuerst den Ctrl-Z anhängen willst> dann den \r anhängen willst> und du erst dann von diesem Gesamtergebnis ein toLatin1 machen willst.
Das tue ich doch? Zuerst kommt das append(STRGZ), dann das append(\r)?
Oder sehe ich das falsch?
Raphael schrieb:> Das tue ich doch? Zuerst kommt das append(STRGZ), dann das append(\r)?> Oder sehe ich das falsch?
Argh.
Jetzt bin ich reingefallen.
Die append gehen ja auf das QByteArray welches von toLatin geliefert
wird. Ich war irgendwie der Meinung, dass sich das alles wieder auf
einen QString zurückübersetzt.
Ich würde mal den QChar da rauswerfen. Nicht dass der dafür sorgt, dass
da ein \0 Byte in die Bytesequenz reinkommt (was fatal wäre, weil write
da sonst das C-String Ende Zeichen sehen würde)
Ok, es funktioniert manchmal. Aber nicht immer. Das dürfte schon vorher
das Problem gewesen sein. Zwischenfrage nun: ist es wichtig in welcher
Reihenfolge ich die +SIND Codes retour bekomme? Zb muss 11 der letzte
sein? Die sind bei mir nicht immer in der selben Reihenfolge, oft habe
ich 11 als letzten, manchmal auch 4.