Hi zusammen, Ich möchte mit Hilfe des QT Creators Daten auslesen, die von einem Atmega88 via myavr Board MK2 über die RS232-Schnittstelle gesendet worden sind. Habe mir ein Beispiel aus dem Netz geladen, wo ein Temperatursensor mit einem Arduino Uno ausgelesen wird. Nun ist mein Problem folgendes: Ich bin mittlerweile so weit, dass die Schnittstelle vom QT-Programm erkannt wird. Das heißt, ist das myavr Board angeschlossen, so wird eine OK- Meldung ausgegeben. Ziehe ich das Board vom USB-Anschluss ab, so erhalte ich von QT eine Fehlermeldung. Allerdings kann ich die Daten nicht sehen, die der Atmega sendet. Hat also jemand Erfahrung mit Avr und QT und kann Tipps geben? Danke schon mal. Daniel
:
Verschoben durch User
Daniel L. schrieb: > Ich möchte mit Hilfe des QT Creators Daten auslesen, die von einem > Atmega88 via myavr Board MK2 über die RS232-Schnittstelle gesendet > worden sind. Ich lese aus dem folgenden Text, dass du die Daten nicht mit Qt Creator auslesen willst, sondern mit einem selbst geschriebenen Qt-Programm. Qt Creator ist eine IDE. > Nun ist mein Problem folgendes: Ich bin mittlerweile so weit, dass die > Schnittstelle vom QT-Programm erkannt wird. Das heißt, ist das myavr > Board angeschlossen, so wird eine OK- Meldung ausgegeben. Von wem? Deinem Qt-Programm? > Ziehe ich das Board vom USB-Anschluss ab, so erhalte ich von QT eine > Fehlermeldung. > Allerdings kann ich die Daten nicht sehen, die der Atmega sendet. Wie versuchst du denn, sie zu lesen? > Hat also jemand Erfahrung mit Avr und QT und kann Tipps geben? Ohne eine einzige Zeile deines Programms zu sehen, wird's etwas schwierig, zu erkennen, wo der Fehler darin liegt.
Teste die Kommunikation erst einmal manuell mit einem Terminalprogamm. Damit kannst du eingrenzen, an welchem Ende des Kabel die Fehlerursache hängt.
Danke erstmal Rolf für die schnelle Antwort. Genau, das Beispielprogramm enthält eine Routine, die sagt: Schnittstelle vorhanden oder Schnittstelle nicht vorhanden. Ich stelle den Code, bzw. das Projekt gerne ein, sobald ich zu Hause bin. Der Laptop, auf dem ich meine Versuche mache, hat leider keine Internetanbindung. Die Programmroutine nennt sich übrigens QSerialPort, aber irgendwas läuft da noch schief. Das Programm wurde ja ursprünglich zur Kommunikation mit einem Arduino Uno geschrieben. Vendor ID und Product ID habe ich korrigieren können. Bin wie gesagt für jeden Tipp dankbar. Daniel
@Stefan: Das Terminalprogramm von myavr empfängt die Daten problemlos, schaltet aber auch den Modus des Programmers automatisch um. QT tut dies nicht innerhalb des Programms, das ich vorliegen habe. Ich habe schon via Dip-Schalter den Programmer manuell in den Datentransfermodus versetzt. Aber auch in diesem Fall sehe ich keine Daten in QT.
:
Bearbeitet durch User
Habe es gerade eben nochmals probiert... Dip-Schalter am Programmer auf Datentransfermodus... Jetzt funktioniert es scheinbar...
> Die Programmroutine nennt sich übrigens QSerialPort Du meinst die Klasse QSerialPort. http://doc.qt.io/qt-5/qserialport.html Ich kann auch nicht hellsehen, aber aus Erfahrung kann ich Dir wenigstens bestätigen, dass QSerialPort mit allen üblichen USB-UART Adaptern einwandfrei funktioniert.
Ich weiß auch nicht genau, woran es vorhin gelegen hat. Werde nachher trotzdem mal den Code hochladen, wenn ich zu Hause bin. Vielleicht kann mal jemand drüberschauen und mir ein paar Tipps geben. Denn nun müssen die Datenpakete ja für die Anzeige aufbereitet werden.
So, hier mal als Anhang der Quelltext. Ich musste einiges als Kommentar deklarieren und habe zunächst eine Routune eingefügt, um zu sehen, ob ich Daten bekomme. Das ist ja nun jetzt der Fall. Jetzt geht es daran, die Daten, die ich bekomme zurechtzulegen. P.S.: Ich habe im Programm auf der Mikrocontrollerseite erstmal nur ein char gesendet. Wahrscheinlich muss ich den Ausdruck erst einmal als string senden, richtig?
Bevor wir hier eine Reverse-Engineering Orgie beginnen, beschriebe doch erst einmal dein Kommunikationsprotokoll und das konkrete Problem. Momentan sind wir ungefähr bei einer so präzisen Aussage wie "geht nicht". > so erhalte ich von QT eine Fehlermeldung Und die ist konkret welche? > Jetzt geht es daran, die Daten, die ich bekomme zurecht zu legen. Was soll das bedeuten? > Wahrscheinlich muss ich den Ausdruck erst einmal als string senden Welcher Ausdruck? Wo wird was gedruckt? Und was hat das mit der Fehlermeldung von Qt zu tun? Es wäre hilfreich, das ganze Projekt in compilierbarer Form zu posten, damit man dein Problem ohne großartige Klimmzüge nachvollziehen kann. Du willst Hilfe bekommen, dann mache es uns so einfach wie möglich.
Guten Morgen zusammen, um die anfängliche Fehlermeldung von QT geht es gar nicht mehr, denn mittlerweile sehe ich ja Datenfluss. Die Aufgabenstellung ist nun folgende (losgelöst vom ganzen Rest, der bis jetzt hier so geschrieben wurde): 1. Es soll eine GUI mit Hilfe von QT erstellt werden (ist bereits passiert). 2. Nach Mausklick auf eine entsprechende Schaltfläche sollen Daten via RS232 an den Mikrocontroller gesendet werden. 3. Der Mikrocontroller verarbeitet die Daten in Form einer Rechnung und sendet das Ergebnis zurück über RS232 an QT. 4. QT zeigt das Ergebnis des Mikrocontrollers in einem Schriftfeld an. Die eben genannte Aufgabenstellung hat wenig mit den bisher geschilderten Problemen zu tun. Da ich jedoch mit QT noch keine Erfahrungen habe, habe ich mir ein Beispiel aus dem Internet gesucht, an dem ich die Abläufe nachvollziehen und damit später eine Teilaufgabe lösen kann. Die für mich definierten Probleme sehen also folgendermaßen aus: 1. Ich weiß noch nicht, wie ich die Daten mit QT zum Mikrocontroller bekomme. 2. Ich weiß noch nicht, wie ich die Daten vom Mikrocontroller zu QT bekomme, um diese nachher in einem Schriftfeld anzeigen zu können (um dieses Problem ging es in der bisherigen Diskussion.) Ich hoffe, das ganze ist nun verständlich beschrieben.
> Ich weiß noch nicht, wie ich die Daten mit QT zum Mikrocontroller bekomme. Ich würde sie mit der QSerialPort Klasse senden. > Ich weiß noch nicht, wie ich die Daten vom Mikrocontroller zu QT bekomme. Ich würde sie mit der QSerialPort klasse empfangen. Was mich nun total irritiert ist, dass du geschrieben hast, die Kommunikation würde bereits funktionieren. Wo ist dann dein Problem? Eventuell magst du von diesem minimalistischem Projekt abgucken, das ist sehr nahe an deiner Aufgabe: http://stefanfrings.de/net_io/ioModule-src.zip Da wird auf Knopfdruck ein Kommando an den µC gesendet und die Antwort als text angezeigt. Außerdem wird der Status des "Schalters" entsprechend aktualisiert. Da ich den Screenshot unter Linux gemacht habe, heißt der serielle Port dort ttyUSB0. Unter Windows würde er COMx heißen.
Stefan U. schrieb: > Was mich nun total irritiert ist, dass du geschrieben hast, die > Kommunikation würde bereits funktionieren. Wo ist dann dein Problem? Ich beschäftige mich ja zwischendurch auch mit dem Problem und versuche, Lösungen zu finden. Das die Kommunikation funktioniert, weiß ich ja nun und momentan habe ich folgendes Problem: Ich muss 4 Werte (diese werden aus Eingabefeldern gelesen) in einen String verpacken und diesen zum Mikrocontroller senden, der hinterher die Berechnungen ausführt. Dazu folgender Quellcode: void Dialog::on_Berechnen_clicked(bool checked) { int value=60; int value2=70; Dialog::updateRGB(QString("a%1b%2").arg(value).arg(value2)); qDebug() << value; } void Dialog::updateRGB(QString command) { if(arduino->isWritable()){ arduino->write(command.toStdString().c_str()); }else{ qDebug() << "Couldn't write to serial!"; } } Zur Erklärung: Nachdem auf eine Schaltfläche (Berechnen) geklickt wurde, sollen die vier obene genannten Werte eingesammelt und gesendet werden. Dazu habe ich testweise die Variablen value und value2 erzeugt. Diese sollen später durch die Werte aus den einzulesenden Feldern ersetzt werden. Frage: Wie sieht nun (laut Quellcodebeispiel) der String aus, der zum Mikrocontroller gesendet wird?
> Wie sieht nun der String aus
Probiere das doch einfach aus. Du kannst es ja mit qDebug() ausgeben
oder im Debugger anschauen.
Stefan U. schrieb: > Probiere das doch einfach aus. Du kannst es ja mit qDebug() ausgeben > oder im Debugger anschauen. Wenn ich qDebug() << value; eingebe, so wird ja der Wert in "value" ausgegeben und nicht der String, der gesendet wird. Wie der Debugger funktioniert, weiß ich noch nicht genau. Kurzum: Was muss ich eingeben, damit ich mittels qDebug() den String so sehe, wie er gerade gesendet wird?
Du musst den String ausgeben, nicht den Value. Quick&Dirty wäre so:
1 | Dialog::updateRGB(QString("a%1b%2").arg(value).arg(value2)); |
2 | qDebug() << QString("a%1b%2").arg(value).arg(value2); |
Ich glaube, du musst noch ein bisschen mehr über die Programmiersprache lernen, bevor du dich an Kommunikationsschnittstellen wagen kannst.
Warum gehst du bei deinen Strings eigentlich immer den Umweg über std::string?
1 | QByteArray serialData = arduino->readAll(); |
2 | QString temp = QString::fromStdString(serialData.toStdString()); |
Einfacher wäre:
1 | QString temp = serialData; |
Daniel L. schrieb:
1 | arduino->write(command.toStdString().c_str()); |
Es reicht auch:
1 | arduino->write(command.toLocal8Bit()); |
Stefan U. schrieb: > Probiere das doch einfach aus. Genau. Einfach am Anfang von updateRGB() einfügen:
1 | qDebug() << "Sending command:" << command; |
Entsprechend deinem Code würde ich erwarten:
1 | a60b70 |
Wusstest du, dass man qDebug auch wie printf() benutzen kann?
1 | qDebug("Hello World!"); |
2 | int number=123; |
3 | qDebug("The number is %i", number); |
Stefan U. schrieb: > Wusstest du, dass man qDebug auch wie printf() benutzen kann? Allerdings nicht mit Klassen. Einen QString muss man dann erst aufwändig konvertierten:
1 | qDebug("%s", myString.local8Bit().data()); |
Da ist das doch einfacher:
1 | qDebug() << myString; |
Danke... Und natürlich muss ich noch einiges in Bezug auf C++ lernen. Habe öfter mal was mit C im Bereich der Mikrocontrollertechnik zu tun gehabt, aber diese ganzen neuen Klassen und generell der Aufbau ist Neuland für mich. Der Aufbau des Strings hat wie vorhergesagt die Form a60b70, was mir etwas Unsicherheit nimmt. Schließlich möchte ich einen festen Telegrammaufbau erreichen, sodass dieser auf der Seite des Mikrocontrollers wieder zerlegt werden kann. Rolf M. schrieb: > Warum gehst du bei deinen Strings eigentlich immer den Umweg über > std::string? Das habe ich so aus dem Beispiel heraus und möchte das natürlich auch verstehen.
> Schließlich möchte ich einen festen > Telegrammaufbau erreichen, sodass dieser auf der Seite des > Mikrocontrollers wieder zerlegt werden kann. Dann würde ich die Zahlen nicht dezimal übermitteln, sondern Hexadezimal. Dann haben sie nämlich eine feste Länge, was auf Seite des µC viel einfacher zu zerlegen ist.
Die Zahlenbasis hat doch nichts damit zu tun, ob die Länge immer gleich ist. Ich würde ein CSV-Format vorschlagen. Die einzelnen Werte werden einfach durch Komma getrennt, und ein Datensatz wird mit einem Newline abgeschlossen.
> Die Zahlenbasis hat doch nichts damit zu tun, ob die Länge immer > gleich ist. Doch, denn ein byte kann Dezimal drei unterschiedliche Längen haben: 0 .. 255. Während es in Hexadezimal die Werte 00 bis FF sind, also zwei Zeichen Länge. natürlich kann man auch dezimalen Zahlen eine 0 voran stellen, aber das macht kaum jemand und stiftet Verwirrung, weil einige Menschen (und Programme) das dann als Oktal Zahl interpretieren.
Stefan U. schrieb: >> Die Zahlenbasis hat doch nichts damit zu tun, ob die Länge immer >> gleich ist. > > Doch, denn ein byte kann Dezimal drei unterschiedliche Längen haben: 0 > .. 255. Während es in Hexadezimal die Werte 00 bis FF sind, also zwei > Zeichen Länge. Wenn ich bei Hex-Ausgabe nicht explizit angebe, dass Nullen vorangestellt werden sollen, passiert das genausowenig, wie bei Dezimal. > natürlich kann man auch dezimalen Zahlen eine 0 voran stellen, aber das > macht kaum jemand und stiftet Verwirrung, weil einige Menschen (und > Programme) das dann als Oktal Zahl interpretieren. Ok, was du also meinst ist, dass konventionell Hex-Zahlen in der Regel mit Nullen aufgefüllt werden, Dezimalzahlen aber nicht. Das ist aber eben eine Konvention und keine inhärente Eigenschaft der Zahlenbasis selbst. Und mit dem Interpretieren ist das so eine Sache. Wenn da die Werte stehen:
1 | 20 25 48 |
dann würde ich die auch erstmal als dezimal interpretieren. Könnten aber genauso gut hexadezimal sein.
:
Bearbeitet durch User
So, ich bin nun so weit, dass mein QT-Programm Daten sendet und empfängt. Ich habe allerdings noch ein Problem mit Variablen, die in einer Unterfunktion erzeugt wurden. Diese sind ja normalerweise im main nicht verfügbar. Beispiel: void Dialog::readSerial() { QByteArray serialData = arduino->readAll(); QString temp = QString::fromStdString(serialData.toStdString()); qDebug() << temp; ui->Ergebnis->setText(temp); } Die Variable temp wird nach dem Auslesen der seriellen Schnittstelle in das Feld "Ergebnis" geschrieben. Dies soll aber erst der Fall sein, wenn eine Schaltfläche in einer anderen Funktion betätigt wurde. Also muss der Wert von temp übergeben werden. Ich habe schon einiges probiert, aber QT ließ sich nicht überreden, den Wert zu übergeben.
Dein Problem ist also, dass der Wert sofort nach dem Auslesen in der GUI angezeigt wird? Wenn das nicht der Fall sein soll, mußt du den Wert irgendwo global, statisch, oder als Member eines Objektes zwischenspeichern. Denn die Variable temp existiert ja nur solange, wie die Funktion readSerial durchlaufen wird. Mit dem Verlassen der Funktion fliegt auch die lokale Variable wieder vom Stapel.
Hallo nochmal, die Lösung ist nun mittlerweile in greifbare Nähe gerückt. Jetzt habe ich nur noch eine Frage. Und zwar erwartet der Mikrocontroller drei Telegramme in Form einer Dezimalzahl. Ich sende jedoch momentan einen Qstring, der wie folgt aussieht (Beispiel für eine Zeile): Dialog::updateRGB(QString("%1").arg(Gewicht)); void Dialog::updateRGB(QString command) { if(arduino->isWritable()){ arduino->write(command.toStdString().c_str()); qDebug() << "Sending command:" << command; Das heißt, ich müsste jetzt noch eine Wandlung in Integer vornehmen, richtig?
Das kommt ganz drauf an, in welchem Format der Mikrocontroller die Daten erwartet. Dein Code wandelt das Gewicht bereits in einen String um, der eine Dezimalzahl enthält. Die Zahl 123 wird zum String "123".
Hier mal die Empfangsseite, alsoder Programmschnipsel aus dem uC-Programm. char rData[4]; ISR(USART_RXC_vect) { rData[uart_rx_cnt] = UDR; uart_Tchar(rData[uart_rx_cnt]); //neu fuer Testzwecke uart_rx_cnt ++; if ( uart_rx_cnt >=3 ){ uart_rx_cnt = 0; calc(); } } Der Empfänger erwartet also ein Array aus 3 chars. Ich müsste also den string in einzelne chars umwandeln, damit es funktioniert?
:
Bearbeitet durch User
Ja. Und dafür sorgen, dass kleinere Zahlen auf drei Stellen erweitert werden, indem eine "0" voran gestellt wird. Es ist allerdings keine gute Idee, die calc() Methode aus dem Interrupt heraus aufzurufen. Setze besser ein "habe fertig" Flag und warte dann in der Hauptschleife, bis das Flag gesetzt ist. Dann kannst du dort das Array verwursten. Tip: Das Flag sollte eine 8bit volatile Variable sein. Google mal nach "volatile" und "atomare operation".
Lässt sich der QString command innerhalb folgender Zeile zu einem char konvertieren oder wie macht man das am besten? arduino->write(command.toStdString().c_str());
Lies doch die Doku! http://doc.qt.io/qt-5/qstring.html#operator-5b-5d Aber warum sendest du nicht einfach den String am Stück? Hat irgendjemand bestimmt, dass du ihn zerlegen musst um die Zeichen einzeln zu senden?
Stefan U. schrieb: > Aber warum sendest du nicht einfach den String am Stück? Hat > irgendjemand bestimmt, dass du ihn zerlegen musst um die Zeichen einzeln > zu senden? Die Seite des Mikrocontrollers hat das erst einmal so festgelegt. Ich war so weit und hatte ja den string - getrennt durch Kommata - an den uC gesendet. Was ist denn prinzipiell einfacher? Ich hänge halt mittlerweile Stunden an dieser Konvertierung von QString nach char, weil ich immer noch das Gefühl habe, nicht verstanden zu haben, wie C++ geht. C empfand ich persönlich als deutlich einfacher, zumindest wenn es um Standardfunktionen geht.
> Was ist denn prinzipiell einfacher? Am Stück senden. Ob du drei Zeichen nacheinander oder den ganzen String am Stück sendest, macht beim Empfänger keinen Unterschied. > Ich hänge halt mittlerweile Stunden an dieser Konvertierung von > QString nach char Ist doch ganz einfach:
1 | for (int i=0; i<command.length(); i++) |
2 | {
|
3 | QCharRef oneCharacter=command[i]; |
4 | }
|
Das ist jetzt nicht viel anders, als in C. Du solltest besser erst einmal die Programmiersprache C++ lernen, und dann QT, bevor du dich an Maschinen-Kommunikation heran wagst.
Was ist denn hier oneCharacter? Eine Variable? oneCharacter wird vom Compiler als Fehler dargestellt. "was not declared"
> QCharRef oneCharacter
Deklariert eine Variable. Du hör mal: Es geht hier echt zu weit, Dir die
ganze Programmiersprache zu erklären. Lies besser ein Buch und stelle
danach deine Fragen.
Danke vorab schon mal für Deine Hilfe Stefan. Ich weiß, ich bin nicht der Supercrack, was C bzw. C++ angeht. Das Buch lese ich gerne, nur meine Aufgabe muss bis morgen fertig sein, DAS ist gerade mein Problem.
Stefan U. schrieb: > Oha. Dann nutze die Zeit lieber , um eine gute Ausrede zu finden. Ich denke gar nicht daran. Und wenn ich die ganze Nacht an dem Scheiss sitze! Dieser Baustein sendet einen QString (command) über die serielle Schnittstelle zum uC. Ich weiß, dass Daten beim uC ankommen und ich weiß, dass Daten vom uC zurückgesendet werden. Ebenso weiß ich, dass das Programm auf dem uC funktioniert (Test mit Hyperterm). Die Wandlung von QString -> Char ist also der letzte Baustein, der noch fehlt. Der Wertebereich der Zahlen ist im Bereich bis ca. 120. void Dialog::updateRGB(QString command) { if(arduino->isWritable()){ arduino->write(command.toStdString().c_str()); qDebug() << "Sending command:" << command; }else{ qDebug() << "Couldn't write to serial!"; } }
Ich verstehe immer noch nicht, warum du du den String in irgendwelche Chars zerlegen willst. Daniel L. schrieb: > Stefan U. schrieb: >> Aber warum sendest du nicht einfach den String am Stück? Hat >> irgendjemand bestimmt, dass du ihn zerlegen musst um die Zeichen einzeln >> zu senden? > > Die Seite des Mikrocontrollers hat das erst einmal so festgelegt. Dem µC ist das doch wurscht, ob du deinen String selber in Chars zerlegst, oder ob das die write()-Funktion von QSerialPort tut. Die werden so oder so einer nach dem anderen an den µC gesendet. > Ich war so weit und hatte ja den string - getrennt durch Kommata - an den > uC gesendet. Und das hat nicht funktioniert? Oder wo ist dein Problem damit gewesen? > Ich hänge halt mittlerweile Stunden an dieser Konvertierung von QString > nach char, weil ich immer noch das Gefühl habe, nicht verstanden zu > haben, wie C++ geht. Das Gefühl trügt nicht. Das ganze wirkt wie planloses Gestocher im Nebel.
Den string in einem Rutsch zu senden hat leider nicht geklappt. Grund ist folgender: Die Eingangsvariable im uC ist als char deklariert. Dort werden einfach drei einzelne Zeichen erwartet. Eine Zählervariable zählt so lange hoch, bis im Empfangspuffer drei Zeichen vorhanden sind. Die Zeichen selbst werden auch erkannt, das haben wir anhand einer Testvariable gesehen. Danach wird aber als erstes Zeichen die Zahl 1,2,3 oder 4 erwartet. Dieser Vergleich funktioniert nicht, weil scheinbar nicht das Format beim uC ankommt, wie es erwartet wird. Daher lag die Vermutung nahe, dass es ein Unterschied geben muss zwischen dem vom QT gesendeten Qstring und dem erwarteten char auf der Seite des uC.
Du vermutest und probierst zu viel. Messen und Debuggen würde viel schneller zum Erfolg führen.
Es ist aber so. Ich sehe, dass jedes Zeichen einzeln zum uC kommt. Das Problem dort ist, dass DREI Zeichen erwartet werden. Und zwar repräsentiert JEDES der drei Zeichen EINEN Wert, der später eine andere Variable füllt. Beispiel: Ich sende abc So wird hinterher a in eine Variable sortiert, b in eine Variable sortiert und c auch. Nun habe ich aber in QT zB den Wert "10" für a. Die "10" würde also a und b abdecken, was ja nicht passieren darf. So ist der JETZIGE Stand! Nun habe ich zwei Möglichkeiten. Entweder ich versuche auf der QT-Seite das Telegramm so aufzubereiten, dass eben auch eine "10" in a hineinpasst (die 10 müsste demnach durch ein einzelnes Zeichen repräsentiert werden). ODER ich muss wie Stefan schon sagte einen String mit einer festen Telegrammlänge definieren und Zahlen, die meinetwegen kleiner als 3 Stellen sind mit Nullen auffüllen: Für die 10 wäre das also dann der Wert 010.
Daniel L. schrieb: > Den string in einem Rutsch zu senden hat leider nicht geklappt. Grund > ist folgender: Die Eingangsvariable im uC ist als char deklariert. Dort > werden einfach drei einzelne Zeichen erwartet. OMG Es spielt überhaupt keine Rolle, ob ein String der Länge 3 oder drei einzelne Zeichen versendet werden, weil in beiden Fällen drei Zeichen über die Leitung gehen. Merke: ein String ist nix anderes als eine Folge von Zeichen. Also: wenn dein Empfänger drei Zeichen erwartet, dann mußt du einfach nur dafür sorgen, dass dein String eben drei Zeichen lang ist. Und wenn der Inhalt des Strings eine Dezimalzahl sein soll, ist die einfachste Methode dafür, den string linksbündig mit "0"en zu padden, weil halt "009" denselben Wert darstellt wie "9", aber eben freundlicherweise genau die drei erwarteten Zeichen lang ist. Das kann doch nicht so schwer zu begreifen sein?
Das weiß ich doch und das will ich doch die ganze Zeit damit sagen. Doch nur deshalb wollte ich den QString in das ASCII-Format bzw. in ein Char umwandeln. Andernfalls muss das komplette Programm auf dem uC angepasst werden.
Daniel L. schrieb: > Nun habe ich zwei Möglichkeiten. Entweder ich versuche auf der QT-Seite > das Telegramm so aufzubereiten, dass eben auch eine "10" in a > hineinpasst (die 10 müsste demnach durch ein einzelnes Zeichen > repräsentiert werden). Das geht nicht. Ein einzelnes Zeichen ist genau das: Ein Zeichen. "10" sind zwei Zeichen - da kannst du dich auf den Kopf stellen, zwei Zeichen passen nicht in ein Zeichen. Du könntest natürlich deine Werte auch binär übertragen. Dann kannst du dir den String komplett schenken, und in ein Byte passt ein Wert im Bereich 0 bis 255. > ODER > > ich muss wie Stefan schon sagte einen String mit einer festen > Telegrammlänge definieren und Zahlen, die meinetwegen kleiner als 3 > Stellen sind mit Nullen auffüllen: > Für die 10 wäre das also dann der Wert 010. Auch hier hilft die Doku von Qt. Schau dir mal an, was QString::arg() noch an weiteren Parametern hat.
So, ich habe es zumindest hinbekommen, einzelne Werte mit Nullen aufzufüllen, was einen festen Telegrammaufbau möglich macht. Habe eben schon einiges zur Stringverarbeitung in C gelesen und mache mich dann nachher an die Aufgabe, den String auszuwerten. Dieser wird dann in etwa so aussehen: 1,100,50 1-> Typ (zulässiger Wertebereich: 1-4), 100 -> Gewicht (zulässiger Wertebereich: 0-150), 50 -> Menge (zulässiger Wertebereich: 0-99). Mein Plan wäre es nun, die drei Teilstrings auf der uC-Seite in Integervariablen zu schreiben und diese somit weiterverarbeiten zu können.
Mach mal eine längere Pause (mindestens 12 Stunden). Du ärmster kannst unter so viel Stress ja kaum noch einen klaren Gedanken fassen. Du musst hier dringend zwischen Bytes und Strings unterscheiden. Das ist ein Byte: uint8_t zahl=123 Wenn du das seriell sendest, wird ein Byte (8 Bit) gesendet. Aber wenn du das in einen String umwandelst, dann werden daraus 3 Zeichen, nämlich "123". Und das entspricht drei Bytes (24 Bit). Wenn du diesen String wiederum in Zeichen zerlegst, erhälst du drei einzelne Zeichen, also immer noch 3 Bytes, 24 Bits. Wenn der Mikrocontroller die 123 in einem einzigen Byte empfangen soll, dann musst du das auch so senden (also weder als String noch als mehrere Char). Ich würde es allerdings nicht machen, denn dann kannst du die Kommunikation nicht mehr manuell mit einem Terminalprogramm testen. Terminalprogramme sind nämlich zur Ein-/Ausgabe vom Zeichen und Strings gemacht worden. Der Ansatz, die Strings auf eine feste Breite zu erweitern ist sinnvoller: 0 -> "000" 12 -> "012" 123 -> "123" Das lässt sich auf µC Seite ziemlich einfach mit atoi() parsen und es ist außerdem Menschen-lesbar (also für Terminal Programme geeignet). Bedenke, dass Terminalprogramme für ordentliche Darstellung auch Zeilenumbrüche benötigen. So wie auch die Enter Taste bei der Eingabe in der Regel einen Zeilenumbruch sendet.
Danke erstmal. Ich habe jetzt folgendes getestet: Und zwar ruft das Programm eine Rechenfunktion auf, wenn es drei Zeichen erkennt. Wird dieser Zustand erreicht, so habe ich zur Probe eine LED eingeschaltet. Das heißt, ich sehe sobald im Puffer mindestens drei Zeichen vorhanden sind. 1. Ich habe mit HTerm getestet und jeweils drei Zahlen abgesendet("001", dann "020", dann "080". Erst nach der dritten mit Return bestätigten Zahl wird die LED eingeschaltet. 2. Ich habe das gleiche mit QT getestet und bereits nach dem ersten Ausdruck ("001"), den ich ja als string sende, leuchtet die LED. Das ist doch der Fall, den Du meintest, oder Stefan? Das heißt, über QT würden nun 3x acht Bit gesendet? 0 -> 00000000 0 -> 00000000 1 -> 00000001 Interpretiere ich das jetzt richtig?
Daniel L. schrieb: > Das heißt, über QT würden nun 3x acht Bit gesendet? > 0 -> 00000000 > 0 -> 00000000 > 1 -> 00000001 > > Interpretiere ich das jetzt richtig? Fast. Die Werte, die für 0 und 1 gesendet werden, sehen anders aus. Das sind die Zeichen '0' und '1', die dezimal 48 und 49 (0x30 bzw. 0x31) sind, d.h. es werden die Bitfolgen 00110000 und 00110001 gesendet. Du solltest Dich wirklich dringend auf Deinen Hosenboden setzen und in Deinem C-Buch die Grundlagen von Datentypen und Zeichenrepräsentation lesen.
Daniel L. schrieb: > Mein Plan wäre es nun, die drei Teilstrings auf der uC-Seite in > Integervariablen zu schreiben und diese somit weiterverarbeiten zu > können. Guter Plan, das wird funktionieren. Du brauchst ihn also bloß noch korrekt umzusetzen... Ja, das erfordert wohl die Kenntnis der Grundlagen der verwendeten Programmiersprache. Also Lernen. Also: Lerne!
Ich kann Dir an dieser Stelle nicht weiter helfen. Dir fehlen zu viele Grundlagen.
So, habe das ganze wie von Stefan vorgeschlagen mit atoi probiert und bekomme mittlerweile auch Ergebnisse zurück. Beispiel für folgende Zahlenwerte, die ich übermittle: Send1 -> 001 Send2 -> 020 Send3 -> 080 Dann erfolgt die Rechnung im Programm: (44*Send3)/Send2. Send 1 würde eine andere Rechnung aufrufen. Als Ergebnis bekomme ich ein hex-Wert in QT zurück, der wie folgt aussieht: \0xB0. In dezimal umgerechnet ist das die 176. Die Rechnung stimmt also somit. Jetzt wäre der letzte Schritt, entweder das ganze mit itoa() auf der uC-Seite umzuwandeln oder aber auf der QT-Seite zu versuchen, den Ausdruck wieder in eine lesbare Zahl umzusetzen. Dabei müsste sicher das \0x abgeschnitten werden, oder?
Wie gesagt: Übertrage besser Text statt Binärzahlen, sonst kannst du das
nicht mehr mit dem Terminalprogramm manuell testen.
> Dabei müsste sicher das \0x abgeschnitten werden, oder?
Das steht in der Dokumentation der Funktion, die du dabei nutzen willst.
itoa() erwartet als Eingabe einen Integer, also eine Zahl im binärem
Format. Da kann unmöglich ein "0x" drin vorkommen.
Mit "0x" beginnen zahlen, die bereits als Zeichenkette im hexadezimalen
Format umgewandelt wurden. An der Stelle, wo du das gemacht hast, muss
sich auch der Code befinden, wo du das "0x" Präfix voran gestellt hast.
Denn die C Library macht das nicht von selbst.
Ich habe aber das Gefühl, das du hier immer noch Bytes und Strings
durcheinander wirfst und dir immer noch nicht darüber im Klaren bist,
was über die serielle Leitung gesendet bzw. empfangen wird. Dabei wäre
das mit einem Terminalprogramm kinderleicht, herauszufinden, wenn man
schon seinen eigenen Code nicht verstanden hat. Doch ich fürchte, du
hast auch nicht verstanden, wie du dein Terminalprogramm bedienen sollst
bzw. wie dessen Anzeige zu interpretieren ist.
Wie gesagt: Es fehlen zu viele Grundlagen. Zu viele Baustellen auf
einmal.
Stefan U. schrieb: > Ich habe aber das Gefühl, das du hier immer noch Bytes und Strings > durcheinander wirfst und dir immer noch nicht darüber im Klaren bist, > was über die serielle Leitung gesendet bzw. empfangen wird. Das ist der springende Punkt. Ich weiß immer noch nicht, was da genau abläuft und die Tatsache, dass HyperTerm und QT in diesem Fall etwas total unterschiedliches machen, verwirrt mich nur mehr. Der Hex-Ausdruck kann meiner Meinung nach nur zwei Gründe haben: a) Die Berechnung wird mit einer Integervariable durchgeführt und (Achtung) an eine Char-Variable übergeben, die das ganze dann an die serielle Schnittstelle sendet. ODER b) Das ist die Empfangsseite von QT: QByteArray serialData = arduino->readAll(); QString temp = QString::fromStdString(serialData.toStdString()); qDebug() << serialData; ui->Ergebnis->setText(serialData); Alte Leier. Ich weiß nicht hundertprozentig, was hier abläuft.
Ich versuche den Code unter b) mal mit meinen eigenen Worten zu interpretieren: Zeile 1: Alle Daten der seriellen Schnittstelle werden in ein QByteArray des Namens serialData geschrieben. Zeile 2: Es wird ein QString mit dem Namen temp erzeugt. Der QString wird zu einem StdString konvertiert (Unterschied zwischen QString und StdString goggle ich gleich). Zeile 3: Der Inhalt von QByteArray wird im Debugfenster ausgegeben. Zeile 4: Der Inhalt aus dem QByteArray serialData wird im Textfeld Ergbenis angezeigt.
> die Tatsache, dass HyperTerm und QT in diesem Fall etwas > total unterschiedliches machen, verwirrt mich nur mehr. Ich glaube dass du einfach nur die Bildschirmanzeigen falsch interpretierst.
Das heißt, dass ich hierdurch möglicherweise meinen Hex-Wert erhalte? b) Das ist die Empfangsseite von QT: QByteArray serialData = arduino->readAll(); QString temp = QString::fromStdString(serialData.toStdString()); qDebug() << serialData; ui->Ergebnis->setText(serialData);
Daniel L. schrieb: > Ich versuche den Code unter b) mal mit meinen eigenen Worten zu > interpretieren: > > Zeile 1: Alle Daten der seriellen Schnittstelle werden in ein QByteArray > des Namens serialData geschrieben. Ja. > Zeile 2: Es wird ein QString mit dem Namen temp erzeugt. Der QString > wird zu einem StdString konvertiert (Unterschied zwischen QString und > StdString goggle ich gleich). Nein. Das QByteArray wird in einen neu erzeugten std::string kopiert, dann wird der std::string in einen neu erzeugten QString mit Namen temp kopiert, dann wird der std::string wieder zerstört. Der QString wird im folgenden nicht benutzt, ist also eigentlich überflüssig. > Zeile 3: Der Inhalt von QByteArray wird im Debugfenster ausgegeben. Ja. > Zeile 4: Der Inhalt aus dem QByteArray serialData wird im Textfeld > Ergbenis angezeigt. Ja. Dazu wird es abermals in einen neuen QString kopiert (nur diesmal ohne Umweg über std::string), da das Textfeld einen solchen haben will und es eine implizite Konvertierung von QByteArray nach QString gibt. Daniel L. schrieb: > Das heißt, dass ich hierdurch möglicherweise meinen Hex-Wert erhalte? Du musst dich entscheiden (wie bei 1, 2 oder 3). Entweder überträgst du die Werte als Text oder du überträgst Binärdaten. Und du musst dann auf beiden Seiten die gleiche Interpretation nutzen. Wenn du auf deinem µC Binärdaten, also direkt Integer ohne Konvertierung nach Text sendest, dann bringt es natürlich nichts, das auf Qt-Seite als String zu interpretieren. Wenn du Text willst (was sinnvoll für Tests mit dem Terminalprogramm ist), dann musst du natürlich auch dafür sorgen, dass auch Text gesendet wird, damit du es auf der anderen Seite als Text empfangen kannst. Klingt trivial, aber du scheinst mit der Unterscheidung noch Schwierigkeiten zu haben.
:
Bearbeitet durch User
Ich würde ja am liebsten die Wandlung über itoa() auf der uC-Seite vornehmen, dann die Teilstrings wieder zusammensetzen und an QT senden. Funktioniert das? Ich habe bereits das Rechenergebnis (Integerwert) in ein Char-Array geschrieben. Nun müsste ich das ganze mit strcat? aneinanderreihen und als Komplettpaket absenden?
> Ich würde ja am liebsten die Wandlung über itoa() auf der > uC-Seite vornehmen Ja, tu das! Wie oft soll ich noch dazu raten? > dann die Teilstrings wieder zusammensetzen Nicht nötig. Sende sie einfach nacheinander. Ob du drei Teil-Strings sendest, oder einen zusammenhängenden mach am anderen Ende des kabel keinen Unterschied. > Ich habe bereits das Rechenergebnis (Integerwert) in ein > Char-Array geschrieben. Ein char-array Speichert Textzeichen, nicht Zahlen. Das Ergebnis einer Rechnung ist zunächst in einer numerischen Variable (z.B. uint16_t oder uint8_t oder so ähnlich). Diese wandelst du dann mit itoa() in eine Zeichenkette um. Und dann sendest du sie. Das machst du nach und nach für jede zahl, die du senden möchtest. Wenn du willst, kannst du dazwischen auch einzelne Trennzeichen (Komma, Zeilenumbruch oder was auch immer) senden.
Das hat ja auch schon funktioniert und ich sehe jede einzelne Zahl bei QT als Ergebnis. Mein Problem ist nun nur noch, diese in QT irgendwie aneinanderzuhängen, damit ich diese im Ergebnisfeld anzeigen kann. Im Moment steht nämlich immer nur eine Zahl im Ergebnisfeld und das ist die letzte aus dem Empfangspuffer. Um das ganze mal darzustellen, wie es im qDebug-Fenster angezeigt wird: "1" "7" "6" Somit erscheint nur die 6 in meinem Ergebnisfeld.
:
Bearbeitet durch User
Von welchem Typ ist denn dein Ergebnisfeld? Wenn das z.B. ein QTextBrowser oder QTextEdit ist, gibt's dort die Funktion append().
Rolf M. schrieb: > Von welchem Typ ist denn dein Ergebnisfeld? Wenn das z.B. ein Das Ergebnisfeld ist vom Typ QLineEdit.
Naja, in ein QLineEdit ist, wie der Name schon sagt, eine Zeile. Mehrzeilig geht dort nicht. Du musst also alles in eine Zeile schreiben oder mehrere QLineEdits benutzen. Oder du nimmst ein mehrzeiliges Widget.
Ich möchte ja auch nichts mehrzeiliges. Es kommen nun vom uC nacheinander drei chars, die ja zuvor mit itoa() umgewandelt wurden: "1" "7" "6" Dise möchte ich in QLineEdit SO darstellen: "176". Es muss doch in QT möglich sein, abzufragen, wie viele Telegramme angekommen sind und diese in eine Zeile zu schreiben, oder?
Ich zittiere aus der Doku von QLineEdit:
You can change the text with setText() or insert().
> Mein Problem ist nun nur noch, diese in QT irgendwie aneinanderzuhängen,
Das ist nicht nötig. Du kannst die Teile mit insert() an Ende einfügen.
Daniel L. schrieb: > Ich möchte ja auch nichts mehrzeiliges. So hatte ich es oben verstanden. > Es muss doch in QT möglich sein, abzufragen, wie viele Telegramme > angekommen sind und diese in eine Zeile zu schreiben, oder? Man kann sowohl QByteArrays, als auch QStrings einfach mit + aneinanderhängen. Also merk dir in einem QByteArray deine Werte, und wenn was neues kommt, füge es einfach mit + an. Wenn du alles hast, sende es an dein QLineEdit.
:
Bearbeitet durch User
Sieht so aus, als wäre das ganze doch noch fertig geworden. Es sind sicher noch Anpassungen an beiden Programmen vorzunehmen, aber nach ersten Tests scheint das Programm zu laufen. An dieser Stelle nochmal GANZ GANZ HERZLICHEN DANK für jeden guten Tipp und für all die Unterstützung!!! Da das ganze ein Hau-Ruck-Projekt war, ist es sicherlich nicht besonders professionell von der Umsetzung her. Dennoch werde ich mir das alles nochmal genauer anschauen und fuer zukünftige Aufgaben ein Buch besorgen. Vielleicht hat ja jemand einen guten Tipp bezueglich QT und avr, aber ich werde natürlich auch googlen. Ich wünsche allen hier einen guten Rutsch ins Jahr 2018 und hoffe, dass ich Eure Nerven nicht allzu sehr strapaziert habe. Daniel P.S.: Wenn die Bewertung erfolgt ist, kann ich das Projekt natürlich gerne zur Verfügung stellen.
Wichtig sind die Grundlagen. Hier hilft ein gutes C oder C++ Buch. Ich würde Dir C++ empfehlen (Da du ja eh Qt lernen möchtest). Die Grundlagen wie Datentypen, Umwandlungen, Operatoren,... sind ohnehin gleich. Wenn du C++ beherscht, kriegst du auch C für einen MC ohne Probleme hin. Hier könnte das AVR Gcc Tutorial aus dem Forum helfen. Für Qt lohnt eun Buch kaum. Arbeite die Examples durch und ansonsten ist der Assistant mit der Doku dein Freund.
QT ist komplett auf der Webseite von QT beschrieben, inclusive einer Menge Tutorials. Anleitungen für AVR findest du mit Google. Vielleicht gefällt Dir meine: http://stefanfrings.de/mikrocontroller_buch/index.html Wegen C++ würde ich Dir empfehlen, mal in einen größeren Buchhandel zu gehen oder in die Bibliothek. Das schnuckelige Buch mit dem ich gelernt hatte gibt es leider nicht mehr zu kaufen. Ich wollte gerade nachschauen wie es hieß, aber der Platz im Regal ist leer. Ich glaube, ich habe es verliehen oder verschenkt und dann vergessen. Dumm gelaufen. > Für Qt lohnt eun Buch kaum Kann ich bestätgen. Ich habe eins gekauft, aber letztendlich steht da nicht mehr drin, als in der Online Doku.
Stefan U. schrieb: > QT ist komplett auf der Webseite von QT beschrieben, inclusive einer > Menge Tutorials. Ist aber alles auch bei Qt schon dabei. > Anleitungen für AVR findest du mit Google. Und direkt hier im Wiki findet sich ja auch schon einiges. >> Für Qt lohnt eun Buch kaum > > Kann ich bestätgen. Ich habe eins gekauft, aber letztendlich steht da > nicht mehr drin, als in der Online Doku. Außerdem veraltet es zu schnell. Mein letztes Qt-Buch hat von 1.4 gehandelt, mit einem Ausblick auf Qt 2. ;-)
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.