Wenn dein Problem oder deine Frage geklärt worden ist, markiere den Beitrag als "Lösung",
indem du auf den "Lösung" Button rechts unter dem entsprechenden Beitrag klickst. Vielen Dank!
Ich versuche Daten, die mit dem AD-Wandler eines µC aufgenommen wurden, an den PC zu senden.
4 Kanäle á 12 Bit, wobei ich 8 Bytes Daten pro Wandlung an den PC sende.
Nun brauche ich ein gutes Konzept dafür.
Bisher habe ich zwei Versuche unternommen:
1. Der µC wartet auf ein Zeichen des PCs ('#') und sendet dann die Daten aus.
Das funktioniert prima, aber die Zeit bis der PC wieder eine '#' sendet ist viel zu lang. (Warum auch immer?!)
2. Der µC sendet permanent die Daten aus. Zur Erkennung des Datenbeginn sendet er zwei mal den Wert 255 hintereinander. Das sollte in den Nutzdaten nicht vorkommen, da das High byte nie 255 erreicht.
Die Daten werden wie folgt gesendet: 255, 255, Lowbyte ADC1, Highbyte ADC1, Lowbyte ADC2, Highbyte ADC2, Lowbyte ADC3, Highbyte ADC3, Lowbyte ADC4, Highbyte ADC4.
Hierbei ist das Problem, dass der Buffer vollläuft, wenn ich die Baudrate erhöhe.
Ich habe beide VIs angehängt. Da gibt es sicher noch sehr viel zu optimieren und wenn jemand ein paar Tipps oder Lektüre für mich hat, wäre ich sehr dankbar.
Weiter versuche ich die Daten dann in einem Array zu sammeln, damit ich sie anschließend in eine Datei schreiben kann. Ausserdem sollen sie auch noch angezeigt werden.
Daran arbeite ich aber noch...
Anzeige
11.06.2014, 15:12 (Dieser Beitrag wurde zuletzt bearbeitet: 11.06.2014 15:15 von jg.)
Natürlich ist kontinuierliches Streamen immer schneller als eine Frage-Antwort-Abarbeitung, gerade per RS-232/VISA. Da hängen unter Windows einige API-Schichten dazwischen, bevor mal wieder von Lesen auf Schreiben umgeschaltet wird.
Dann einige allgemeine Kritikpunkte:
- einmal baust du die beiden Bytes per Plus zusammen, einmal per Join, aber beide Male am Ende in einem Zieldatentyp U8. Meinst du, da passt das im jeden deiner Fälle rein? Bei Plus kannst du einen Überlauf bekommen und beim korrekten Join ist der Zieldatentyp automatisch U16.
- Wozu ein 2D-Array der Größe 4x1000 vorinitialisieren (eigentlich gut), wenn du dann doch wieder per "Insert Into Array" das Array nur vergrößerst?
- Und wo wir schon bei "Insert Into Array" sind, IMHO eine der meist missbrauchten Funktionen in LabVIEW, sie lässt sich fast immer durch ein einfach zu verstehenden "Build Array" ersetzen. Was soll das, mit Initialize Array ein 0x0-Array initialisieren, um dann 4 Werte anzuhängen?
- Sei konsequent und verwende das Vergrößern der Funktion Index Array immer!
Die Hauptverbesserung bei Version 2: Wenn du erst einmal die beiden "Trennbytes" erkannt hast, dann musst du das nicht nochmals machen. Ab jetzt einfach immer einen (oder auch mehrere Blocks) aus dem VISA-Buffer auslesen und verarbeiten.
Und geh nochmal zurück ans Zeichenbrett, 100% Fail-Safe ist das mit deinen beiden 0xFF Bytes nicht. Könnte ja sein, dass das erste Zeichen in VISA-Read das zweite 0xFF Byte ist und das erste Low-Byte ebenfalls 0xFF ist. So etwas hatten wir schon.
Danke erstmal für die Antwort. Ich habe mich weiter mit dem Thema beschäftigt und bin auf die Producer-Consumer-Programmstruktur gestoßen.
Damit werde ich den nächsten Versuch unternehmen. Dann habe ich mir überlegt, ein Steuerzeichen vom PC zu senden und dann mit 4000 (oder 4096) Bytes zu antworten, das könnte den Overhead doch erheblich verringern.
Das mit dem Join habe ich erst später entdeckt. Das ist natürlich besser, da direkt ein U16 aus den zwei Bytes erzeugt wird. Hätte ich in meinem ersten Entwurf anpassen müssen.
Mit den Arrays habe ich wohl noch ein paar Probleme, aber ich sehe wo das Problem ist.
Zum Thema Sync Bytes. Das ist leider wirkilich nicht failsafe. Also sollte der mögliche Fehlerfall durch eine Abfrage (wie bei der Wegmessung) abgefangen werden.
Hm, bin mir immernoch nicht sicher, ob streaming oder polling. Aber vermutlich bekomme ich beim streaming den höchsten Datendurchsatzt, auch wenn ich nur alle 4096 Bytes abfrage.
Naja das lässt sich ja ausrechnen. Ich werde erstmal eine nacht darüber schlafen.
Danke und viele Grüße!
11.06.2014, 23:47 (Dieser Beitrag wurde zuletzt bearbeitet: 12.06.2014 09:11 von Lucki.)
Wenn es so schnell wie möglich sein soll, dann sollten auch unkonventionelle Lösungen mit ins Auge gefasst werden. Am schnellsten dürfte das sein:
Der µC sendet kontinuierlich, Länge eines Datensatzes 8 Zeichen. Die 12bit Daten werden aufgeteilt in 2 Bytes zu je 6 bits. An das letzte Byte des Datensatzes wird zur Endeerkennung bit7=1 gesetzt. Da das 8. bit nie gesetzt ist, recht zur Datenübertragung ein 7bit Code.
Habe mal ein VI zur Daten-Codierung/Dekodierung gemacht. Bei ernsthaften Interesse helfe ich auch gern bei der seriellen Übertragung selbst.
Zunächst habe ich den µC umprogrammiert, sodass die Daten nun 6 Bit pro Byte ausfüllen. Ich habe es erstmal bei 8 Bit belassen und das MSB zur Kodierung genommen.
Das kann später noch auf 7 Bit gekürzt werden, aber erstmal ist es vielleicht einfacher mit ganzen Bytes.
Bei dem ersten Byte ist das MSB nun gesetzt.
So ganz verstehe ich die Dekodierung noch nicht. Du machst als erstes eine UND Verknüpfung, um das MSB zu löschen, richtig?
Dann Teilst du die Daten im Array auf, so dass je zwei Bytes in einer Spalte sind und insgesamt vier Zeilen entstehen.
Anschließend werden die Daten wieder so zusammengefügt, dass die Wertigkeit stimmt.
Es fehlt aber komplett die Erkennung des Datenbeginns oder seh ich das nur nicht?
Ich arbeite weiter an dem VI und lade es hoch, wenn ich soweit bin...
Der Stand bis jetzt:
Der µC Sendet nach Aufforderung ein Byte, bei dem das MSB gesetzt ist. Anschließend sendet er 4000 Datenbytes.
Das VI fängt nach Empfangen der # an zu arbeiten und prüft das MSB auf Datenbeginn. (# nur zu debugzwecken)
Wenn 4000 Bytes im Puffer sind, werden sie an das Queue übergeben.
In der Verarbeitungsschleife wird aus dem String ein Bytestream. Die Messwerte werden wieder zu einem Wort zusammengesetzt.
Probleme:
- Ich kann das MSB nicht prüfen und dennoch weiterverarbeiten. Daher wird einmal der Datenbeginn gesendet und nicht bei jedem Datensatz, wie es eigentlich sein sollte.
- Das 1D Byte Array mit 4000 Bytes muss verarbeitet werden, wie es in der Verbraucherschleife geschieht. Allerdings kann ich das so, wie es für die 1. 8 Bytes gemacht wird, für 4000 machen
PS: Sorry für den Doppelpost, aber ich konnte nicht mehr editieren
12.06.2014, 14:26 (Dieser Beitrag wurde zuletzt bearbeitet: 12.06.2014 14:32 von Lucki.)
(12.06.2014 09:41 )Steffen.S schrieb: So ganz verstehe ich die Dekodierung noch nicht. Du machst als erstes eine UND Verknüpfung, um das MSB zu löschen, richtig?
Dann Teilst du die Daten im Array auf, so dass je zwei Bytes in einer Spalte sind und insgesamt vier Zeilen entstehen.
Anschließend werden die Daten wieder so zusammengefügt, dass die Wertigkeit stimmt.
Es fehlt aber komplett die Erkennung des Datenbeginns oder seh ich das nur nicht?
Der Erkennen des Datenbegins fehlt tatsächlich. Statt dessen ist das Datenende markiert. Das ist prakischer, weill genau zu diesem Zeitpunkt mit der Auswertung der Daten begonnen werden kann.
Habe mal ein VI angehängt, wie ich mir das Lesen der Daten etwa vorstelle. Es ist aber noch nicht professionell, z.B. fehlt die Timout-Behandlung.
Es wird angenommen, dass der µC vorher eingeschalten ist. (Andernfalls wäre eine Timeout-Behandlung fällig, mit Meldung wie z.B: "µC einschalten, Du vergessliches A..loch").
Wenn dann das VI gestartet wird, dann hört der PC gewöhnlich mitten in ein Byte hinein und es kommt zum Rahmen-Synchronisationfehler. Der wird mit der ersten Schleife abgefangen.
Wenn das ausgestanden ist, dann hört der PC wahrscheinlich immer noch mitten in den Datensatz hinein, so dass dieser unvollstandg ist. Dieser erste Datensatzt sollte also weggeschmissen werden. Dazu dient die zweite Schleife.
Damit ist die Synchronisation hergestellt.
In der inneren rechten schleife wird jeweils ein Datensatz gelesen,und zwar byteweise. Wenn ein eintreffendes Byte >63 ist, so handest es sich um das letzte Byte des Datensatzes. Die Schleife wird verlassen und die Auswertung kann beginnen. (das ab jetzt nur noch störende Datenerkennung-Bit 5 wird gleich in diesser Schleife entfernt.)
Dekodierung:
Das Low-Byte wird geshiftet und linksbündig in die U8-Zahl gesetzt, d.h. der Inhalt wird um 2 bit nach links verschoben. Dann wird aus High- und low-Byte eine U16-Zahl gebildet. In dieser Zahl befindet sich der eigentliche 10-bit Inhalt zwischen den Bits 2 und 13. Diese 12 bits müssen jetzt noch rechtbündig platziert werden, d.h der Zahl ist um 2 bit nach rechts zu shiften.
Ich habe das VI jetzt weiterentwickelt und es funktioniert auch.
Allerdings treten Probleme mit der Rahmen Synchronisierung auf.
Ab und zu scheint sich die Biterkennung zu verschieben und es kommt nur noch Murks an. 2 Stoppbits haben das ganze schon verbessert, aber es läuft noch nicht perfekt.
Besonders beim Starten des VIs braucht man meherere Versuche, bis korrekte Werte angezeigt werden.