Hallo! Ich möchte über die serielle Schnittstelle (eigentlich USB CDC) Sensordaten an den PC übertragen. Damit die Daten auch den entsprechenden Sensoren zugeordnet und die einzelnen Messwerte voneinander unterschieden werden können, brauche ich ein kleines "Protkoll". Der PC initiiert das Senden der Daten, ab da werden kontinuerlich mehrere Pakete mit Messwerten hintereinander geschickt. Dazu habe ich mir folgende Überlegungen gemacht: * Der Beginn einer Übertragung muss durch ein spezielles Byte gekennzeichnet werden (ich habe mich willkürlich für STX = 0x2 entschieden) * Die Messwerte selbst müssen durch ein spezielles Byte voneinander getrennt werden werden (z.B. ';' = 0x3B) * Und jetzt das große Aber: Die Daten müssen aus Leistungsgründen binär und nicht ASCII-codiert übertragen werden Dabei ergibt sich jetzt natürlich ein Problem: Was passiert wenn die beiden Steuerungsbytes STX und ';' in den Nutzdaten selbst vorkommen? Ein anscheinend gängiger Ansatz ist es, die Steuerungsbytes zu wiederholen, falls sie in den Daten selbst stehen, also bspw.: ...';'0x02';'... wird zu ...';'0x02 0x02';'... Sobald also 0x02 gelesen wird, kannn es sich entweder um den Anfang einer Übertragung handeln oder um Nutzdaten. Das wird dann durch das nächste Byte entschieden. Habe ich jetzt aber ';'0x3B';' wird daraus ein ';'0x3B 0x3B';', d.h. effektiv habe ich dann viermal 0x3B hintereinander stehen und so langsam kann nichts mehr voneinander unterschieden werden. Außerdem kommt hinzu, dass jeweils ein Messwert aus 16 Bit besteht, d.h. im worst case Fall würde ich ein 0x3B 0x3B 0x3B 0x3B 0x3B 03xB empfangen, aus dem nun wirklich nur sehr schwer etwas zu extrahieren ist. Ich habe selbst wenig Erfahrung mit serieller Datenübertragung (bisher nur als ASCII), daher frage ich hier im Forum: Welche Möglichkeiten gibt es, Binärdaten per serieller Schnittstelle sauber zu übertragen? Oder ist mein Ansatz nicht völlig verkehrt und braucht nur ein paar Änderungen? Vielen Dank an die Experten ;)
du nummerierst die sensoren, sendest 0x02 Nummer. Sensor Antwortet Nummer Daten1 Daten2 CRC. Da du eine feste länge hast kannst du auf das 0x3B verzichten.
Hi
Wie ist es mit fester Blocklänge der Daten ? Und nun die rein
provokatorische Frage: meinst du, wenn du ASCII-Daten überträgst, am
Empfänger entsprechend 30h abziehst dund dann die so ermittelte Zahl der
Stelle zuordnest, das dies soviel Zeit erfordert? Zumindest ist alles
>47 und kleiner 58 eine Zahl (2Fh und 3Ah).
Gruß oldmax
Was Du meinst nennt sich "maskieren" oder englisch "escaping". http://en.wikipedia.org/wiki/Escape_character Das kannst Du eigentlich mit beliebigen Zeichen machen, es muss nur in beide Richtungen funktionieren. Man kann mit dem Escape Zeichen nur eines maskieren oder beliebige Steuerzeichen. Du kannst auch den Backslash verwenden, wie es gerne gemacht wird. Man benutzt immer ein bestimmtes Zeichen um die Maskierung einzuleiten. Kommt danach nochmal dieses Zeichen, dann ist dieses gemeint (\\ = \ oder wie bei Dir 0x3B0x3B = 0x3B). Jedes andere Zeichen danach ist ein Steuerzeichen. Also: 0x02 = Steuerzeichen Anfang \0x02 = Daten 0x3B = Trennzeichen \0x3B = Daten \\ = \ Es ist egal wie oft hintereinander das in den Daten dann vorkommt. Bei der Dekodierung geht es einfach immer rückwärts nach diesem Prinzip. Schau dir mal diese Software und dieses Protokoll zur Übertragung der Messwerte an: http://www.serialcominstruments.com/SerialComInstruments%20Doku.pdf Beitrag "Projekt: Virtuelle Instrumente an serielle Schnittstelle"
Andi K. schrieb: > kann nichts mehr voneinander unterschieden werden. Außerdem kommt hinzu, > dass jeweils ein Messwert aus 16 Bit besteht ... was aber auch der Empfänger weiss. D.h. du weisst, dass nach einem 0x02 jeweils 2 Bytes (mit dem Sonderfall eines 0x02 Datenbytes) zusammengehören. Wodurch die Notwendigkeit eines Trenn-'Zeichens' nicht mehr gegeben ist. Du brauchst es schlicht und ergreifend nicht.
Andi K. schrieb: > * Und jetzt das große Aber: Die Daten müssen aus Leistungsgründen binär > und nicht ASCII-codiert übertragen werden Von welcher Hochleistungsanwendung redest du hier, wenn du an dieser Stelle... Andi K. schrieb: > dass jeweils ein Messwert aus 16 Bit besteht ...nicht 4 statt 2 Bytes übertragen kannst? Du kanst deine Messwerte aber auch im Block übertragen: Preambel MW0 MW1 ... MWn Postambel Dann ergibt sich aus der Reihenfolge die Zuordnung. Sodass die Zusatzzeichen nicht vor und nach jedem Messwert gesendet werden müssen. Zwischen den Ambeln kannst du auch Binärdaten senden, musst dem PC aber beibringen, dass er dann nicht darauf triggern darf. Wenn jetzt allerdings einer das Kabel zieht, hängt die Kiste. Einem sicheren Protokoll darf das aber nichts ausmachen. mfg.
oldmax schrieb: > Hi > Wie ist es mit fester Blocklänge der Daten ? Und nun die rein > provokatorische Frage: meinst du, wenn du ASCII-Daten überträgst, am > Empfänger entsprechend 30h abziehst dund dann die so ermittelte Zahl der > Stelle zuordnest, das dies soviel Zeit erfordert? Zumindest ist alles >>47 und kleiner 58 eine Zahl (2Fh und 3Ah). > Gruß oldmax Ich sende pro "Paket" netto (also ohne Kontrollbytes) sechs 16 Bit Werte. Wenn ich jetzt bspw. sechs mal 65536 schicken muss, bekomme ich bei ASCII 6 * 5 = 30 bytes anstatt 12 bytes. Das fällt dann bei vielen Sensoren (> 50) durchaus etwas ins Gewicht. dummschwaetzer schrieb: > du nummerierst die sensoren, > sendest 0x02 Nummer. > Sensor Antwortet > Nummer Daten1 Daten2 CRC. > Da du eine feste länge hast kannst du auf das 0x3B verzichten. Okay, also ist in diesem Fall ein "richtiges" Protokoll besser geeignet als meine recht einseitige Lösung. Eine feste Blocklänge wäre wohl wirklich am Besten.
Start- oder Endbyte(s), das nicht im Datenstrom vorkommt, Dahinter ev. Checksumme Dh. nur 255 statt 256 Werte möglich je Daten-Byte, das sollte selten nicht verkraftbar sein Statt Messwerte per Separator zu trennen, ein Header-Byte spendieren, wenn sich die Anzahl der Sensoren denn unbedingt ändern können muss.
Andi K. schrieb: > Ich sende pro "Paket" netto (also ohne Kontrollbytes) sechs 16 Bit > Werte. Wenn ich jetzt bspw. sechs mal 65536 schicken muss, bekomme ich > bei ASCII 6 * 5 = 30 bytes anstatt 12 bytes. Das fällt dann bei vielen > Sensoren (> 50) durchaus etwas ins Gewicht. Die Frage ist aber: Stört dich das technisch gesehen? Welche Update-Rate kriegst du damit hin und reicht diese Rate oder ist es zu wenig? Das ist der entscheidende Punkt. Es gibt da einen 'Sager': man muss nicht maximal schnell sein. Man muss nur schnell genug sein.
Karl Heinz schrieb: > Andi K. schrieb: > >> Ich sende pro "Paket" netto (also ohne Kontrollbytes) sechs 16 Bit >> Werte. Wenn ich jetzt bspw. sechs mal 65536 schicken muss, bekomme ich >> bei ASCII 6 * 5 = 30 bytes anstatt 12 bytes. Das fällt dann bei vielen >> Sensoren (> 50) durchaus etwas ins Gewicht. > > Die Frage ist aber: Stört dich das technisch gesehen? > Welche Update-Rate kriegst du damit hin und reicht diese Rate oder ist > es zu wenig? > > Das ist der entscheidende Punkt. Es gibt da einen 'Sager': man muss > nicht maximal schnell sein. Man muss nur schnell genug sein. Leider komm ich da schnell an eine Grenze. Geplant sind 64 Sensoren, die alle 2 ms Messwerte ausspucken. Da komme ich dann auf netto 937,5 kbyte/s. Der Controller hat USB Full Speed (12 Mbit/s), aber davon bleiben (gemessen) maximal 960 kbyte/s übrig.
Andi K. schrieb: > Ich sende pro "Paket" netto (also ohne Kontrollbytes) sechs 16 Bit > Werte. Wenn ich jetzt bspw. sechs mal 65536 schicken muss Der höchste Wert bei 16 Bit 65535, 65336 sind schon 17 Bit. Zweitens sendet man keine Dezimal- sondern Hexadezimalzahlen. mfg.
Thomas Eckmann schrieb: > Zweitens sendet man keine Dezimal- sondern Hexadezimalzahlen. Da war ich gerade auf dem falschen Dampfer, sorry. Du meinst, dass man beispielsweise 9247 = 0x241F als 0x2 0x4 0x1 0xF sendet und dadurch zwar die doppelte Byte-Zahl hat, aber nur 16 ASCII Zeichen belegt sind und andere als Steuerungsbytes verwendet werden können? Habe ich das richtig verstanden?
Andi K. schrieb: > Welche Möglichkeiten gibt es, Binärdaten per serieller Schnittstelle > sauber zu übertragen? Keine. In einem Datenstrom der mit möglichst hoher Geschwindigkeit laufen soll und in dem alle Bits irgendwann mal vorkommen hast du keine Möglichkeit Anfang und Ende zu synchronisieren. Bei USB CDC kannst du auch kein Zeittelegramm erstellen da die Übertragung zeitlich von der USB Konfiguration abhängt (z.B. welche und wie viele USB Geräte am Bus hängen). Da hast aber Messwerte. Da würde ich jetzt einfach einen verbieten (z.B. das Sync Muster hex 5A = 01011010) und als Start Byte nehmen. Kommt das dann 2 mal hintereinander ist es eben ein Datenbyte. Es gibt dann natürlich den Fall das in den Daten das Sync Muster mehrmals vorkommt (oder nur noch mit der chance von 1/255). Das fängst du ab indem du vereinbarst das mehr als zwei Syncs hintereinander gültige Daten sind und Sync jetzt $A5 ist. So lange bis wieder nur ein einzelnes (oder eine ungerade Anzahl) $5A kommt. Eine Prüfsumme kann man da auch noch dranhängen. Die ID des Datenkanals ist die Position des Wertes im Datenstrom zwischen den Syncs. Wie viele Datenpaare bis zu einem Sync übertragen werden legst du selbst fest.
Andi K. schrieb: >> Das ist der entscheidende Punkt. Es gibt da einen 'Sager': man muss >> nicht maximal schnell sein. Man muss nur schnell genug sein. > > Leider komm ich da schnell an eine Grenze. Geplant sind 64 Sensoren, die > alle 2 ms Messwerte ausspucken. ok. das ist der Plan. Die nächste Frage lautet: gibt es für die 2ms einen bestimmten Grund oder sind die per Bauchegfühl festgelegt worden? (Nicht lachen: Kommt häufiger vor als man denkt). Lautet die Antwort: die 2ms sind recht willkürlich festgelegt worden, weil der Designer immer erst mal 2 Millisekunden nimmt. dann kann man die 2ms ja auch mal in Frage stellen. Ein Mensch wird sicherlich nicht 500 Messwerte pro Sekunde mit seinem Gehirn verarbeiten können. Temperaturen ändern sich im Regelfall nicht so schnell, dass es eine Rolle spielt, ob man Temperaturwerte 500 mal pro Sekunde updated, oder doch nur 100 mal. Ein Motor (überhaupt wenn er ein Schwungrad hat) ändert seine Drehzahl nicht wesentlich in 2ms. Überhaupt haben mechanische Systeme eine gewisse Trägheit inne, die oft eine hohe Updaterate zur reinen Zahlenakrobatik degradieren. Sind die 2ms aber unabdingbar, weil zb eine Regelschleife die so braucht, dann geht da logischerweise nichts mehr.
Andi K. schrieb: > Leider komm ich da schnell an eine Grenze. Geplant sind 64 Sensoren, die > alle 2 ms Messwerte ausspucken. Dann nimm doch einfach 2 Controller. Das kannst du später auch beliebig erweitern oder mit der Datenrate runter gehen.
Andi K. schrieb: > Habe ich das richtig > verstanden? Ja. Andi K. schrieb: > Leider komm ich da schnell an eine Grenze. Geplant sind 64 Sensoren, die > alle 2 ms Messwerte ausspucken. Da komme ich dann auf netto 937,5 > kbyte/s. Der Controller hat USB Full Speed (12 Mbit/s), aber davon > bleiben (gemessen) maximal 960 kbyte/s übrig. Das ist mir aber nicht ganz klar. 16 Bit Messwert = 4 ASCII-Zeichen. 64 * 4 / 2ms = 128K/s Karl Heinz schrieb: > Sind die 2ms aber unabdingbar, weil zb eine Regelschleife die so > braucht, dann geht da logischerweise nichts mehr. Damit wäre das Unechtzeitsystem PC aber ohnehin überfordert. mfg.
Thomas Eckmann schrieb: > 64 * 4 / 2ms = 128K/s 64 Sensoren * 4 Byte / 2ms = 128K/s?? Es sind nicht 128K sondern 128 kB(yte) RS232 hat aber incl. Start und Stop 10 bit pro Byte.
Thomas Eckmann schrieb: > Andi K. schrieb: >> Leider komm ich da schnell an eine Grenze. Geplant sind 64 Sensoren, die >> alle 2 ms Messwerte ausspucken. Da komme ich dann auf netto 937,5 >> kbyte/s. Der Controller hat USB Full Speed (12 Mbit/s), aber davon >> bleiben (gemessen) maximal 960 kbyte/s übrig. > > Das ist mir aber nicht ganz klar. Der Post war ja auch vor meiner Nachricht, dass ich das missverstanden habe ;) Wie gesagt, es sind sechs Messwerte, deswegen nochmal neu gerechnet: (64 Sensoren*6 Messwerte*4 Byte) / 2 ms = 750 kbyte/s Netto-Datenrate. Ich werd mir den Ansatz mal genauer anschauen, vielen Dank schon mal!
Der Rächer der Transistormorde schrieb: > Es sind nicht 128K sondern 128 kB(yte) Nein, nein. Bei 128 Kelvin geht der UART in Supraleitung und schafft die Übertragung schneller. Der Rächer der Transistormorde schrieb: > RS232 hat aber incl. Start und Stop 10 bit pro Byte. Hat, nicht hat aber. mfg.
Andi K. schrieb: > Wie gesagt, es sind sechs Messwerte, deswegen nochmal neu gerechnet: > (64 Sensoren*6 Messwerte*4 Byte) / 2 ms = 750 kbyte/s Netto-Datenrate. Alles klar. 6 Messwerte vom Sensor. Das war mit entgangen. mfg.
Ohne mich in eure Zeitberechnungen einmischen zu wollen: Das Problem der Unterscheidung Steuerung/Daten kenne ich auch. Ich löse es gerne indem ich mich an CAN "anlehne". Die Werte 00h bis 1Fh sind auf dem Bus immer Steuerbytes. Das Steuerzeichen 0Ah übernimmt dann die "Shift"-Funktion. Wenn ein Messwert kleiner 20h ist, wird ihm der Shift-Befehl vorangestellt und der Wert selbst dann um 20h erhöht. Der Empfänger kann es dann wieder "on-the-fly" entsprechend zurücknehmen. Also z.B. aus Messwert "05h" wird "0Ah 25h". Der Empfänger weiss dann, dem nächsten Zeichen werden die entsprechenden MSB maskiert und als Data gewertet. Ein Nachteil bleibt natürlich bei vielen kleinen Werten...
Andi K. schrieb: > 750 kbyte/s Netto-Datenrate 1 Byte sind 8 bit. USB ist ein serieller Bus der nur ein Bit zur Zeit überträgt. Deshalb ist die Datenrate auch in Bit angegeben, Bei USB high speed 12 Mbit. Das ist aber die Bruttorate eher Marketing. Es gibt jede Menge Protokoll Overhead, Prüfsummen und auch noch Latenzzeiten. Davon kann CDC wieder nur einen Teil, hab aber selber nie mehr als 115k gemacht. USB ist auch nicht echtzeitfähig, da wg. der wechselnden hierarchische Topologie nun mal keine garantierten Antwortzeiten ermittelt werden können. Thomas Eckmann schrieb: > Nein, nein. Bei 128 Kelvin geht der UART in Supraleitung und schafft die > Übertragung schneller. > > Der Rächer der Transistormorde schrieb: >> RS232 hat aber incl. Start und Stop 10 bit pro Byte. > Hat, nicht hat aber. Verstehe ich nicht.
Der Rächer der Transistormorde schrieb: > 1 Byte sind 8 bit. USB ist ein serieller Bus der nur ein Bit zur Zeit > überträgt. Deshalb ist die Datenrate auch in Bit angegeben, Bei USB high > speed 12 Mbit. > > Das ist aber die Bruttorate eher Marketing. Es gibt jede Menge Protokoll > Overhead, Prüfsummen und auch noch Latenzzeiten. > > Davon kann CDC wieder nur einen Teil, hab aber selber nie mehr als 115k > gemacht. Das ist alles schön und gut, aber ich habe mit dem Controller die maximal mögliche Datenrate über USB CDC mehrfach gemessen und komme auf 960kbyte/s, also dürften 750kbyte/s vielleicht drin sein. Das hat sich auch mit den Aussagen auf anderen Websites gedeckt, dass 6-8 Mbit/s bei USB Full Speed (High Speed ist wieder etwas anderes) mit CDC durchaus möglich sind. Statler schrieb: > Ohne mich in eure Zeitberechnungen einmischen zu wollen: Das Problem der > Unterscheidung Steuerung/Daten kenne ich auch. Ich löse es gerne indem > ich mich an CAN "anlehne". Die Werte 00h bis 1Fh sind auf dem Bus immer > Steuerbytes. Das Steuerzeichen 0Ah übernimmt dann die "Shift"-Funktion. > Wenn ein Messwert kleiner 20h ist, wird ihm der Shift-Befehl > vorangestellt und der Wert selbst dann um 20h erhöht. Der Empfänger kann > es dann wieder "on-the-fly" entsprechend zurücknehmen. > > Also z.B. aus Messwert "05h" wird "0Ah 25h". Der Empfänger weiss dann, > dem nächsten Zeichen werden die entsprechenden MSB maskiert und als Data > gewertet. Ein Nachteil bleibt natürlich bei vielen kleinen Werten... Danke für deine Antwort, dein Ansatz hört sich auch nicht schlecht an! Wie gehst du dann mit der variablen Länge der Übertragungspakete um?
Die Paketlänge ist damit ganz egal, da Control (00h bis 1Fh) und Data sauber auseinander gehalten werden kann. Ich arbeite aber dann auch gerne mit den definierten ASCII-Steuerzeichen, also SOH, STX, EOT etc. Also in deinem Fall z.B.: STX-[addr]-[data_0..n]-ETX Wenn Adresse>63 dann vielleicht: STX-[addr_0]-[addr_1]-[data_0..n]-ETX oder: SOH-[addr_0..n]-STX-[data_0..n]-EOT Um den "Shift"-Fall zu reduzieren, könnte man auch die Controlbytes auf 00h bis 0Fh reduzieren und dann die Daten nur mit 01h shiften. Aber für mich war's mit 32 optionalen Befehlen immer optimal.
Hi Einmal meld ich mich noch: Wenn du dein Programm auf eine feste Übertragungslänge einstellst, hast du immer 50 Werte bzw. 100 Byte Nutzdaten. Wenn du ASCII überträgst, kannst du den Transfer einleiten, wenn eine Änderung eintritt. Ich weiß nicht, wie dynamisch deine Werte sind, aberes ist alles eine Frage der Anwendung. Natürlich sind 100 Byte weniger wie 250, aberes kann genau so sein, das 36 Werte eigentlich ohne Änderung mitgeliefert werden. Dann ist das auch "Zeitverschwendung". Das du ein Telegramm mit fester Länge schicken kannst hab ich auch gleich als erstes genannt. Gruß oldmax
Hallo Andi, ich möchte mich in die Diskussion über das geeignetste Protokoll nicht einmischen, aber ein paar Worte zur Performence von USB beitragen, welche ich bislang nicht gelesen habe. Bei USB werden Daten in Packeten fester Länge übertragen. Die Länge der Packete wird von der Länge des Puffers eines Endpoints bestimmt und in einem Konfigurator festgelegt. Typische Packetlängen sind 8, 16, 32 oder 64-Byte, für mehr Daten werden dann mehrere Packete verschickt. Benutzt du nun ein Gerät mit einer Packetlänge von 32-Byte zum Transfer von 33-Byte, werden zwei Packete geschnürt. Im ersten Packet liegen 32-Datenbyte, im zweiten Packet liegt 1-Datenbyte und 31-Füllbytes. Ob dies bei CDC auch so ist, habe ich nicht überprüft, gehe aber davon aus. Die verwendete Packetgröße läßt sich mit einem USB-Sniffer feststellen, dann kannst du die Packetgröße deines Protokolls, ähnlich wie von oldmax bereits vorgeschlagen, an die Größe der USB-Packete anpassen. Gruß. Tom
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.