LabVIEWForum.de - RS232 Daten empfangen zu langsam (Anfänger)

LabVIEWForum.de

Normale Version: RS232 Daten empfangen zu langsam (Anfänger)
Du siehst gerade eine vereinfachte Darstellung unserer Inhalte. Normale Ansicht mit richtiger Formatierung.
Seiten: 1 2
Hi, ich bin gerade dabei mein erstes etwas größeres Programm in LabVIEW zu schreiben.

Es geht darum, einem Mikrocontroller über RS232 Befehle zu schicken und welche von ihm zu empfangen.
Ich übertrage die Werte aber nicht in Klartext, also als ASCII Zeichen, sondern als wirkliches Byte (z.B. 65 ist nicht "65" sondern 'A'Wink, damit die Übertragung schneller ist.

Ein Befehl sieht etwa so aus: (Die einzelnen Bytes sind als Dezimalzahl 0...255 geschrieben)

000......die ersten 4 Byte sind die Start-Sequenz. Sie zeigen an dass ein "Datenpaket" beginnt
255
255
255
1.........Befehl, z.B. Position von Servo 1, Geschwindigkeit von Motor 3, ...
22.......high-Byte
156......low-Byte
2.........nächster Befehl
34.......wieder ein high Byte
21.......wieder ein low Byte
6.........nächster Befehl
... usw

Im 50ms werden diese Befehle von LabVIEW an den Mikrocontroller gesendet, der Mikrocontroller sendet gleichzeitig im 35ms-Rythmus die Sensordaten an LabVIEW (sieht genauso aus, nur werden statt Steuerbefehlen Sensordaten, z.B. "Bodenabstand vorne" gesendet).
Die Sequenz 000 255 255 255 wird verwendet, um anzuzeigen, dass ein neues "Datenpaket" beginnt. Befehl darf nicht 255 sein, sondern nur 0...254. Dann ist sichergestellt, dass die Sequenz 000 255 255 255 nie im normalen Datenfluss vorkommt, sondern eben nur wenn eine neues Datenpaket beginnt.

Auf der Mikrocontroller-Seite funktioniert alles, aber LabVIEW macht mir Probleme, ich kenn mich da leider noch nicht so gut aus...
Das senden funktioniert soweit recht gut, und schnell. Das Servo das ich bewegen will bewegt sich fast in Echtzeit mit.
Als ich aber dann das lesen dazuprogrammiert habe, hat das die ganze Kommunikation ausgebremst... Je größer ich den Buffer eingestellt habe, desto langsamer wurde alles. Während gelesen wurde, konnte das Servo nur noch ruckartig bewegt werden, obwohl ich am Code zum Schreiben nichts verändert habe.

Ich vermute das liegt daran, dass der Lesebuffer ständig voll ist. Ich glaube da muss man irgendwie eine Queue einbauen, aber ich habe mir schon die LabVIEW Hilfe durchgelesen und das Terminal Beispiel heruntergeladen und angeschaut, aber ich habe keine Ahnung wie ich das in mein Programm einbauen soll.

Wenn man in ASCII Zeichen sendet, kann man ja bei dem VI für die Initialisierung von VISA einen Termination Char angeben, z.B. n
Für meine Anwendung reicht aber ein Termination Char nicht aus, weil für die Variablenwerte jeder Char auftreten kann. Ich müsst irgendwie einen Termination String angeben, nämlich 000 255 255 255.
Gibt es eine Möglichkeit so einen Termination String anzugeben?

Wenn nicht, wie sollte ich mein Programm verbessern, damit ordentliches Empfangen möglich ist? Ist eine Queue ein guter Ansatz?

lg Christoph


PS: Im Anhang ist mein VI, es ist von LabVIEW Version 8.6 (englisch).
Hallo Christoph,

"wie sollte ich mein Programm verbessern"

Indem du die ganzen lokalen Variablen weglässt. Was soll es bitte bringen, gleichzeitig den gleichen Wert ins Terminal und in eine lokale Variable zu schreiben? Willst du sicherstellen, das der Wert wirklich (so richtig wirklich und 100%ig) in der Anzeige ankommt? LabVIEW ist datenfluß-orientiert und nicht an "Variablennamen" interessiert... Schleifen endlos laufen zu lassen ohne Abbruchbedingung ist auch nicht die hohe Programmierkunst - dein VISAClose wäre dann nämlich nicht nötig, es wird ja eh nicht ausgeführt.

Ich hab mal bis auf eine alle locals entfernt. Das Programm sollte weiterhin funktionieren...
Du verwendest eine Baudrate von 19200. Das macht 0.5ms pro Byte oder mindestens 3.5ms pro Datenpaket. Alles über eine Leitung, alle 50ms vom Rechner und konkurrierend alle 35ms vom Gerät. Meinst du nicht auch, dass es da zu Überschneidungen und recht schnell zum "Verstopfen" kommt? Außerdem hast du in der "Rechnerschleife" statt 50ms nur eine Wartezeit von 20ms eingegeben.

Lv86_img
Hi, danke für die Verbesserungen!

Das mit der variable hab ich dann nicht so richtig verstanden Rolleyes
Ich hab geglaubt dass man irgendwo in eine Variable schreiben muss, und wo anders kann man die Variable dann auslesen. Hab nicht gewusst dass mit dem Indicator gleichzeitig in die Variable geschrieben wird.

Zu Überschneidungen sollte es nicht kommen oder? Die Signale werden ja auf getrennten Leitungen übertragen (eine RX und eine TX Leitung).

Aber ich glaube ich habe einen Grund für die Verzögerungen gefunden:
Je größer ich den Buffer mache, desto größer sind auch die Verzögerungen. Der Visa Read Buffer wird ja von rechts nach links aufgebaut, und es werden wie bei einem Schieberegister die neuesten empfangenen Bytes von rechts nach links eingeschoben.
Die Auswertung funktioniert aber von links nach rechts. Es wird von links beginnend die erste Start-Sequenz gesucht, und von dieser aus die nächste. Der Teil dazwischen ist der Potiwert.
Je größer der Buffer ist, desto länger dauert es bis der aktuelle Wert von rechts nach links "durchgeschoben" wurde. Daher kommen die Verzögerungen...

Ein Lösungsansatz der mir gerade einfällt ist den die Reihenfolge der Stringelemente mit "String reverse" umzukehren. Das funktioniert aber leider nicht, in diese String-Reverse Funktion schicke ich einen String mit 30 Zeichen rein und es kommt einer mit 10 Zeichen raus...
Ich werde mich morgen weiter damit beschäftigen...

lg Christoph


Im Anhang ist die aktuelle Version von meinem Programm

[attachment=27449]
Lv86_img
Bitte jedes Mal VI-Version angeben, auch wenn sich seit Deinem letzten Post nichts geändert hat. (vgl. LVF-RegelnRulez)

Gruß Markus
Hallo Christoph,

LabVIEW ist datenfluß-orientiert, die Drähte sind die "Variablen". Alles andere sind Ein- und Ausgabeelemente. Es gibt aber auch kostenlose Kurse bei NI.com...

"String-Reverse Funktion schicke ich einen String mit 30 Zeichen rein und es kommt einer mit 10 Zeichen raus"
Das will ich sehen. Beweis/Beispiel-VI?

"Visa Read Buffer wird ja von rechts nach links aufgebaut"
Ich dachte bisher, der wird von oben nach unten aufgebaut.Smile
Ist schon sehr bildlich dargestellt. Es ist ein Buffer, bei dem neue Daten angehangen werden. Ob das nun links, rechts, oben oder unten ist - egal. Wenn du deine VISA-Antworten richtig auswertest, bildet sich da auch keine große Warteschlange...
Hi,

sorry dass ich mich so lange nicht gemeldet habe, ich konnte einige Zeit nicht an meinem Projekt weiterarbeiten...

Da die Übertragung umso langsamer war, je länger ich den read-buffer eingestellt habe, habe ich mir einen neuen Lösungsansatz überlegt. Ich hab es jetzt so gemacht wie am Mikrocontroller. Dort hab ich es ich C geschrieben, das war nicht so schwer, irgendwie komm ich mit Labview nicht so richtig klar...

Im Anhang ist das VI, für meine Frage interessant ist die Schleife die mit "VISA READ" beschriftet ist.

Der Buffer ist auf 3 Byte eingestellt, somit kann maximal ein Befehl im Buffer stehen.
Es wird jetzt immer überprüft, ob die 3 Byte im Buffer die "Start-Sequenz" von einem Befehlssatz ist. Das ist der Fall wenn alle 3 Byte 255 sind.

Ist dies der Fall, wird die aktuelle Anzahl an ausgelesenen Bytes in einem Schieberegister gespeichert. Dieser gespeicherte Wert wird dann von der Anzahl der ausgelesenen Bytes abgezogen. Man erhält also eine Art Zähler, der die nach der Start-Sequenz empfangenen Bytes durchnummeriert.

Diesen Zähler nehme ich dann als Index-Wert für die Funktion "Insert Into Array", und das Byte das gerade an Position [0] im Buffer ist nehme ich als Wert der ins Array geschrieben werden soll.

Leider funktioniert das ganze aber nicht so wie es soll...

Im Array steht immer nur auf Position [0] etwas, und dort nichtmal das richtige :-(
Es springt immer zwischen 0, 255 und dem Wert der empfangen werden soll hin und her...
Aber prinzipiell sollte es doch funktioniert glaube ich.

Mein Problem ist glaube ich, dass ich nicht genau verstehe wie der Visa Read Buffer und der "return count" funktioniert.
Ich habe das bis jetzt so aufgefasst:
z.B. Buffergröße 3, die Bytes die empfangen werden: 255 64 23 89 121 90 22
Read Buffer wird so aufgebaut:
Buffer | return count
[] [] [255] 1
[] [255] [064] 2
[255] [064] [023] 3
[064] [023] [089] 4
[023] [089] [121] 5
[089] [121] [090] 6
[121] [090] [022] 7
usw...

Dass der "return count" nicht so aufgebaut wird habe ich jetzt schon herausgefunden, der steht nämlich bei mir immer konstant auf 3. Aber so verstehe ich nicht was der bringen soll... ich bräuchte eigentlich genau so eine fortlaufende Nummer wie ichs beim Beispiel aufgeschrieben habe, dann würde mein Konzept denke ich mal funktionieren.
Stimmt das so wie ich denke dass der Read Buffer aufgebaut wird? Das meinte ich übrigens in meinem letzten Post mit "von rechts nach links".

lg Christoph

Anhang ist LabVIEW Version 8.6 Englisch.
[attachment=28147]
VISA. Empfang von µC:
Die Startsequnz (- die gleichzeitig, wegen variabler Datenlänge, die Stopsequenz ist -) sollte am besten online, d.h. sofort, erkannt werden. Dazu muß VISA Read auf byteweises einlesen konfiguriert sein, die Pufferng der Daten erfolgt dann im VI und nicht im VISA-Puffer. Ich sehe hier Auffüllen das Visa-Puffers und dann 50 bytes auf einmal auslesen - das wird nie etwas Gescheites, das muß ich gar nicht genauer hinschauen.
Hier Bespiel für Lesen, es müßte funktionieren, ist aber noch nichts Professionelles. Hinzukommen muß noch Fehlerbehandlung, denn mit Übertragungsfehlern ist immer zu rechnen.
Gründe: Wenn man plötzlich in die µC-Übertragung hineinlauscht, dann liegt der Beginn womöglich mitten in einem Datensatz. Oder es kann sogar passieren, daß der Beginn mitten in einem Byte liegt, VISA meldet dann einen "Rahmen-Synchronisationsfeher". Aber das passiert nur am Anfang der Datenübertragung, bzw. überhaupt nicht, wenn erst auf Empfang geschalten wird und dann wird erst der µC gestartet.

Lv86_img[attachment=28149]

(Falls es sich um bidirektionale Sensorwerte handelt, müßte die Konvertierung geändert werden.)
Hi,

danke danke danke ur super das hat auf Anhieb funktioniert!!

Am Anfang kommt eine Fehlermeldung, aber wie du gesagt hast nur nach dem Verbindungsaufbau, danach funktioniert alles super.
Ich werde das uC Programm eh bald umschreiben, sodass der uC nach dem Einschalten noch nicht sendet, sondern nur empfängt und darauf wartet, dass LabView den Befehl zum "Senden einschalten" schickt.

Es ist aber ur professionell programmiert da wär ich nie drauf gekommen... ich hänge jetzt schon seit 2 Stunden an einer kleinen Modifikation.

Ich hätte gerne am Ausgang ein 1D-U16-Array mit 255 indexes, jeder steht für einen Befehl. Um die empfangenen Werte in das Array zu bekommen habe ich die Funktion "Replace Array Subset" verwendet.
Zur Verfügung habe ich ja ein Array mit den Befehlen und ein Array mit den Werten. In der for-Schleife wird durch das "indexing" immer jeweils ein Element aus den beiden Arrays genommen, und als Eingangswerte für die "Replace Array Subset" Funktion verwendet.

So... und nun die Frage: Wieso funktioniert das nicht? Das Array wird nie beschrieben...

lg Christoph

Anhang: LabVIEW Version 8.6 Englisch
[attachment=28156]
Wie heißt es so schön, die Daten in LabVIEW liegen in den Verbindungen. Also bei Case-Strukturen Vorsicht mit dem "Use Default if unwired":
[attachment=28157]
Gruß, Jens
Hallo Christoph,

du hast in deiner Case-Struktur einige "default if unwired"-Tunnelausgänge. Diese stören dich sicherlich beim Aufbau deiner Arrays, da immer mal wieder ein Default-Array (d.h. leeres Array) ins Shiftregister geschrieben wird. Versuche die mal vernünftig zu verdrahten...
Seiten: 1 2
Referenz-URLs