Forum: PC-Programmierung Sensorwerte vom µC an den PC übertragen


von Knotenimhirn (Gast)


Lesenswert?

Hallo,
ich stehe gerade voll auf dem Schlauch und brauche eure Hilfe :-)

Eigentlich ist mein Vorhaben mehr als simpel:
Ein µC erfasst verschiedene Sensorwerte und soll diese nun per USB 
(Serial Port) an den PC übertragen. Dazu würde ich pro Sensor ein Byte 
mit der ID des Sensors schicken (damit der PC die nachfolgenden Daten 
richtig auswerten kann), und dann 4 Bytes mit dem Messwert. Also pro 
Sensor ein Paket aus 5 Bytes.

Doch nun das Problem:
Woher soll das PC Programm wissen welches ankommende Byte welche 
Bedeutung hat? Wenn das Programm erst loslegt während der µC schon 
läuft, hat es ja vermutlich eine beliebige Anzahl an Bytes verpasst. 
Damit kann es nicht mehr wissen was eine ID ist und was Messwerte sind.
Auch einen Wert als "Trennzeichen" festzulegen (z.B. 0xFF) ist keine 
Option, da dieser Wert natürlich auch immer in den Sensordaten vorkommen 
kann.

Was ist das richtige Vorgehen für so einen Fall?

von AmEinfachsten (Gast)


Lesenswert?

ganz simpel ist es ein Telegramm mit ASCII-Zeichen zu schicken, zBsp:
+003069xx#

+   = Startzeichen
003 = ID
069 = Wert
xx  = beliebige Checksumme
#   = Endezeichen

von AmEinfachsten (Gast)


Lesenswert?

....darauf kann das PC-programm wunderbar "triggern".

von Knotenimhirn (Gast)


Lesenswert?

AmEinfachsten schrieb:
> ganz simpel ist es ein Telegramm mit ASCII-Zeichen zu schicken, zBsp:
> +003069xx#

Klar, mit ASCII kann ich einfach Start/Endzeichen definieren. Ich suche 
aber nach einer Binary-Lösung, einerseits wegen der besseren 
Performance, andererseits aus Neugierde ;-)

von MaWin (Gast)


Lesenswert?

Knotenimhirn schrieb:
> soll diese nun per USB (Serial Port) an den PC übertragen. Dazu würde
> ich pro Sensor ein Byte mit der ID des Sensors schicken (damit der PC
> die nachfolgenden Daten richtig auswerten kann), und dann 4 Bytes mit
> dem Messwert. Also pro Sensor ein Paket aus 5 Bytes.
>
> Doch nun das Problem:
> Woher soll das PC Programm wissen welches ankommende Byte welche
> Bedeutung hat?

USB funktioniert so nicht.
Bei USB fragt immer der PC, ob es neue Daten gibt.

USB/Seriell Wandler werden also dauernd nach neuen eintreffenden 
Datenbytes gefragt, so wie deine Tastatur nach Tastendrücken und die 
Maus nach Bewegungen.

Wie kommen mehrere Sensordaten auf einen USB Anschluss ? Selbst seriell 
RS232 ist nur 1 Kabel, da passen nicht mehrere rumfunkende Sensoren per 
Verteiler gleichzeitig dran.

Entweder gibt es nur einen seriellen Sender (uC der die Daten von allen 
Sensoren sammelt und dann seriell an den USB Adapter schickt) oder du 
brauchst ein Kollisionsvermeidungsprotokoll wie RS485.

Oder pro Sensor einen USB Stecker im USB Hub und es wird pro Sensor eine 
virtuelle serielle Schnittstelle geöffnet.

Auch beliebt: Sensor 1 an uC a sendet seriell an den uC b der Sensior 2 
auswertet, der bringt die Daten in Reihenfolge und sendet ein 
Gesamtpaket mit Daten von 1 und 2 an uC c der Sensor 3 auswertet und 
zeitlich synchronisiert um ein Gesamtpaket aus den Daten von 1, 2 und 3 
an den seriell-nach-USB Wandler schicken zu können der am PC hängt auf 
dem ein Programm eine virtuelle serielle Schnittstelle öffnet um das 
Gesamtdatenpaket abholen zu können.

Da kann man auch gleich Synchronisationsbytes "Zeilenende" einfügen die 
als 1. byte nicht vorkommen können.

von AmEinfachsten (Gast)


Lesenswert?

ok, kam so nicht direkt rüber.
Es werden ja zwei bestimmte Werte als Start und als Ende festgelegt.
Die Telegramm-Länge steht ja auch fest.
Vielleicht so, ist nur 'ne Idee:
Immer auf das Startbyte triggern, bis zu einem Endebyte einlesen und
dann das empfangene Telegramm auf plausibilität prüfen.
Da stellt sich aber auch die Frage wie schnell wird gesendet und wie 
schnell
kann die Empfangsstelle auswerten und triggern. nicht das gar nix als
plausibel erscheint, weil Bytes verloren gehen.

von MeierKurt (Gast)


Lesenswert?

Knotenimhirn schrieb:
> AmEinfachsten schrieb:
>> ganz simpel ist es ein Telegramm mit ASCII-Zeichen zu schicken, zBsp:
>> +003069xx#
>
> Klar, mit ASCII kann ich einfach Start/Endzeichen definieren. Ich suche
> aber nach einer Binary-Lösung, einerseits wegen der besseren
> Performance, andererseits aus Neugierde ;-)

Eine eindeutige Synchronsequenz senden...
Zwischen den Paketen eine Anzahl Paketlänge+1  gleicher Zeichen, was 
keine ID sein kann, senden.

von MeierKurt (Gast)


Lesenswert?

AmEinfachsten schrieb:
> ok, kam so nicht direkt rüber.
> Es werden ja zwei bestimmte Werte als Start und als Ende festgelegt.

Nein, am Anfang steht die ID, dann kommen 4 Byte Messwert. Es ist nur 
sicher, in welchen Bereich sich die ID bewegt. Und dass diese nach 4 
Zeichen wiederholt wird. Alles andere ist frei.

> Die Telegramm-Länge steht ja auch fest.
> Vielleicht so, ist nur 'ne Idee:
> Immer auf das Startbyte triggern, bis zu einem Endebyte einlesen und
> dann das empfangene Telegramm auf plausibilität prüfen.
Hat ein gewisses Restrisiko...

> Da stellt sich aber auch die Frage wie schnell wird gesendet und wie
> schnell
> kann die Empfangsstelle auswerten und triggern. nicht das gar nix als
> plausibel erscheint, weil Bytes verloren gehen.

Von Geschwindigkeit war nie die Rede - es wurden Performancegründe 
genannt, um die Umsetzung in ASCII umgehen zu können.
Dabei würde es aber schon genügen, die 4Byte Meßwert zu 8 Bit auf 5x7bit 
umzusetzen, dann könnte man nämlich FF als eindeutiges Trennzeichen 
verwenden, um hurtig syncen zu können.

von Mellopock (Gast)


Lesenswert?

MeierKurt schrieb:
> Eine eindeutige Synchronsequenz senden...
> Zwischen den Paketen eine Anzahl Paketlänge+1  gleicher Zeichen, was
> keine ID sein kann, senden.

Das halbiert dann aber natürlich die zur Verfügung stehende Datenrate.
Aber funktionieren sollte es...

MaWin schrieb:
> Wie kommen mehrere Sensordaten auf einen USB Anschluss ? Selbst seriell
> RS232 ist nur 1 Kabel, da passen nicht mehrere rumfunkende Sensoren per
> Verteiler gleichzeitig dran.

Hä? Ich habe die Sache anders verstanden: ein µC hängt per USB 
(virtueller COM Port) am PC, und kann darüber Daten an ein Programm auf 
dem PC schicken ("Serial.write(0xFF)"). Am µC hängen mehrere Sensoren, 
die von diesem ausgelesen werden.

von Peter D. (peda)


Lesenswert?

Knotenimhirn schrieb:
> Woher soll das PC Programm wissen welches ankommende Byte welche
> Bedeutung hat?

Dafür gibt es Protokolle. Entweder einen Standard nehmen (SCPI) oder was 
selber erfinden.
Textprotokolle haben den Charme, daß man sie beim Debuggen mitlesen 
kann.
Binärprotokolle benutzen ein Escape-Zeichen, um Daten von Steuercodes zu 
unterscheiden. Dieses sollte möglichst selten in den Daten enthalten 
sein, z.B. 0xA5.

Die Minimalanforderung an ein Protokoll ist, daß es sich auf Paketebene 
neu synchronisiert. Ist also eine Seite asynchron, dann ist maximal ein 
Paket gestört. Daraus leitet sich automatisch ab, daß Störungen erkannt 
werden müssen (CRC) und korrigiert werden können (Retry).

von Danilo (Gast)


Lesenswert?

Hi, kannst ja auch zwischen dem Datenstrom eine Lücke einbauen. Dieser 
Timeout ist dann das "Startzeichen".

von Joachim B. (jar)


Lesenswert?

Knotenimhirn schrieb:
> Klar, mit ASCII kann ich einfach Start/Endzeichen definieren. Ich suche
> aber nach einer Binary-Lösung,

dann sende doch immer die gleiche Menge an Bytes und zum Schluß 10 oder 
nach Belieben 0 Bytes.
Wenn der PC startet muss er halt mitzählen, hat er nicht die bekannte 
Menge Bytes gesammelt bis die ENDE Nullbytes kommen müssen die Daten eh 
verworfen werden.

Ob du nun ASCII sendest und das auseinenander nimmst und mitliest oder 
ob du kryptische Bytes in bekannter Menge sammeln willst ist doch egal.
Du musst nur sicherstellen das deine Endekennung nie im Telegramm 
auftreten kann!

Knotenimhirn schrieb:
> Ich suche..... andererseits aus Neugierde ;-)

ich suche auch einfach aus Neugierde den selber fahrbaren Porsche Turbo 
neu für 100,-€ zum Kauf.

: Bearbeitet durch User
von Weasel P. (philipp_s576)


Lesenswert?

Also ich mache es meistens so wie die anderen schon gesagt haben.
Startzeichen, Daten, Endzeichen
Alles dazwischen musst du definieren.

Aber alles in ASCII zu machen währe vor zu ziehen.
ASCII hat aber nicht nur den Vorteil dass es lesbar ist, sondern du 
kannst auch einfacher Dinge definieren wie zb. Trennung von Daten.

So könnte wenn du nur von einem uC Daten überträgst das so aussehen:
:A12.4;B3.6;C96.3;CRC;\r\n


Warum willst du dir das Leben schwer machen und keine ASCII Zeichen 
übetragen?
Ich kann mir jetzt keine (Mess) anwendung vorstellen wo es einen 
unterschied machen würde für einen Messwert jetzt 3 oder 9 bytes zu 
verschicken. Bzw. ein paar µs für die Umwandlung zu investieren.

: Bearbeitet durch User
von Sebastian S. (amateur)


Lesenswert?

Für das Problem gibt es viele Lösungen!

Du schaust Dir die Daten an, und siehst nach ob nicht irgendwelche 
Bitmuster "frei" sind. Hast Du z.B. Messwerte, so gehen die bestimmt 
nicht alle, lückenlos, von 0 bis F...F. A/D-Wandler haben selten 16 Bit 
oder sogar 32 Stück und somit bleibt genug zum "Schauen".

Du kannst die Werte auch in Pakete packen (wie bereits gesagt) und 
zwischen den Paketen eine definierte (zeitliche) Pause lassen.

Du kannst die Daten auch "verstümmeln", indem Du z.B. aus 4 x 8 Bit 5 
Pakete machst. Dadurch bekommst Du - jederzeit - das letzte/erste Bit 
frei zum Fummeln. Da die serielle Datenübertragung sowieso etwas 
gemächlicher ist, sollte die "Aufblähung" des Volumens auch kein Problem 
bereiten.

Du kannst komplett auf das ASCII-Format umsteigen und Dich von 
Zeilenumbruch zu Zeilenumbruch hangeln.

Die meisten Geräte können nicht nur quatschen, sondern auch zuhören. 
Also nicht einfach drauflosquatschen, sondern warten bis Dir jemand das 
Wort erteilt. Das kostet 1 Zeichen.
Ist das eine Zeichen schon zu viel, so sende halt ein Paket von 994 
Werten und warte erst dann auf die nächste Aufforderung.

Ich bin der Meinung, dass ein bidirektionales Verfahren sowieso das 
sicherste ist, weil auf diese Weise, vor allem in gestörter Umgebung, 
Prüfwerte hinzugefügt werden können und Wiederholungen, im Fehlerfalle, 
kein Problem sind. Manchmal sind die Werte nämlich wichtig und der 
Befehl: "Hä?" muss unbedingt zur Verfügung stehen.

Etwas hakelig!
Bei vielen Empfangsroutinen kann man zwar das Paritätsbit setzen, es 
erfolgt aber meist kein Abbruch, wenn es nicht stimmt. Man kann es aber 
abfragen. Also wartest Du einfach auf das erste Paket, mit fehlerhafter 
Parität und freust Dich ab diesem Zeitpunkt. Du kannst auf diese Weise 
das Paritätsbit sozusagen als Marke bzw. neuntes Bit betrachten.

: Bearbeitet durch User
von c-hater (Gast)


Lesenswert?

Knotenimhirn schrieb:

> Klar, mit ASCII kann ich einfach Start/Endzeichen definieren. Ich suche
> aber nach einer Binary-Lösung, einerseits wegen der besseren
> Performance, andererseits aus Neugierde ;-)

Dafür gibt es viele Lösungen, jede mit ganz spezifischen Vor- und 
Nachteilen.

Grundsätzlich ist es aber so, dass die Information über den Beginn des 
Informationsframes eine ZUSÄTZLICHE Information ist und 
dementsprechend in jedem Fall Bandbreite im Übertragungskanal kostet, 
ganz egal wie man sie codiert.

Am billigsten ist wohl ein simpler Timeout, also eine absichtlich 
eingefügte Pause im gesendeten Datenstrom. Damit sie aber wirklich 
"billig" sein kann, braucht man i.A. echtzeitfähige Empfänger. Ein PC 
mit den üblichen OS ist aber keiner, was dazu führt, dass die Pause so 
lang gewählt werden muss, dass sie dann halt doch recht teuer wird. 
Dieses Problem (also der Verlust an Bandbreite) schlägt umso härter zu, 
je weniger Nutzdaten ein Frame umfaßt.

Also: für kleine Frames und PCs als Empfänger eher nicht zu empfehlen, 
bei großen Frames aber durchaus brauchbar, auch für PCs als Empfänger. 
Und natürlich auch immer dann, wenn die benötigte Bandbreite garnicht 
das Problem ist, sondern reichlich Luft läßt. Dann nutzt man eben diese 
"Luft" einfach als Pausenzeit zur Markierung der Framegrenzen.
In so einem Fall könnte man aber auch komplett auf ASCII ausweichen...

So ungefähr das andere Ende der möglichen Maßnahmen ist, zum Frame 
einfach nur eine "gute" Prüfsumme hinzuzufügen, also eine CRC. Dann muß 
der Empfänger aber ordentlich Rechenleistung bereitstellen, denn er muß 
die Empfangshistorie in Framegröße vorhalten und für jedes eingehende 
Byte erneut berechnen, ob die Prüfsumme für die Historie paßt. Die 
Framesynchronisation ist erreicht, wenn sie paßt. Danach kann dann aber 
geschludert werden, dann muß man nur noch für jedes Frame die CRC 
prüfen. Jedenfalls bis man auf den Fall trifft, dass sie nicht paßt. 
Dann wirds wieder teuer, denn dann steht eine Neusynchronisation an.
Da PCs heute über ziemlich viel Rechenleistung verfügen, würde ich 
dieses Verfahren immer dann bevorzugen, wenn auch der Sender über genug 
Rechenleistung verfügt, um einmal pro Frame eine CRC zu berechnen.

von Vorschlag (Gast)


Lesenswert?

Viele Vorschläge aber nix konkretes..

Es gibt z.B. so was: https://gitlab.com/PaniR/rero_stm32
Inklusive Python package zum empfangen.

Da kein µC gesetzt ist kann ja einer verwendet werden der ausreichend 
Leistung hat.

von Bastler_HV (Gast)


Lesenswert?

Ich glaube ComVisu wurde noch nicht erwähnt, da gibt es schon alles 
fertig:

Beitrag "Serielle Visualisierung mit Comvisu"

und für die Linuxfans
Beitrag "Comvisu für Linux"

von Sebastian S. (amateur)


Lesenswert?

@Vorschlag
>Viele Vorschläge aber nix konkretes..
Hättest Du mal die Beiträge gelesen.

Im Übrigen: Der TO hat nicht gefragt: "Suche Bibliothek zum Versenden 
von Daten über die serielle Schnittstelle". Prozessor mit beliebig 
großem Speicher wird gestellt.

Deine Einlassung interpretiere ich so: Was Lacostet die Welt ich zahle 
Bar.

von Martin V. (oldmax)


Lesenswert?

Hi
Nun, ich weiß nicht, ob du schon eine Lösung gefunden hast, mir ist das 
Problem klar. Du brauchst eine Synchronisierung auf den Anfang der 
Datenübertragung. Ein einfaches Zeichen ist bei einer Übertragung von 
Binärdaten nicht sicher und selbst meine Telegrammstruktur hat auch 
gewisse Unsicherheiten, aber bisher hat es immer funktioniert. Meine 
Telegramme bestehen aus einem Kopf von ein paar ASCII Zeichen, die der 
Empfänger auswertet. Je höher die Anzahl, um so sicherer ist der Anfang 
zu erkennen. Es du da vorweg sendest, ist eigentlich egal, und auch 
wenns einfach das Wort "Post" ist. Ich hab im PC einen kleinen 
Ringspeicher eingerichtet, wo ankommende Daten abgelegt werden. Dann 
wird ein leerer String mit den Daten gefüllt, solange die eingehenden 
Bytes mit einem Vergleichstext übereinstimmen. Wenn nicht, leere ich den 
String und Fang von vorn an. Ist der Vergleich komplett, hab ich den 
Anfang der Daten. Wenn du mehr wissen willst, ich glaub ich hab diese 
Vorgehensweise in meinem Buch beschrieben. Es ist schon mehrfach 
erwähnt, kostet nix und liegt im Forum von makerconect.de
Gruß oldmax

von Frank K. (fchk)


Lesenswert?

Knotenimhirn schrieb:
> AmEinfachsten schrieb:
>> ganz simpel ist es ein Telegramm mit ASCII-Zeichen zu schicken, zBsp:
>> +003069xx#
>
> Klar, mit ASCII kann ich einfach Start/Endzeichen definieren. Ich suche
> aber nach einer Binary-Lösung, einerseits wegen der besseren
> Performance, andererseits aus Neugierde ;-)

Schau Dir an, wie eine serielle Maus das gemacht hat: Das erste Byte 
hatte Bit 7 gesetzt, alle anderen Bytes hatten Bit 7 gelöscht.

Oder bei PPP: Definiere einen Start-Zeichen, das nicht im Datenstrom 
vorkommt, und ein Escapezeichen, das auch nicht im Datenstrom vorkommt. 
Das Start-Zeichen definiert den Anfang eines Blocks eindeutig.

Wenn das Startzeichen in den zu sendenden Daten auftaucht, ersetzt Du es 
durch Escapezeichen + 0-Byte, wenn das Escapezeichen selber auftaucht, 
ersetzt Du das durch Escapezeichen + 1.

Manche UARTs können auch einen 9-Bit Modus. Da kannst Du das 9. Bit als 
Blockindikator verwenden.

fchk

von Schlaumaier (Gast)


Lesenswert?

Weasel P. schrieb:
> Also ich mache es meistens so wie die anderen schon gesagt haben.
> Startzeichen, Daten, Endzeichen
> Alles dazwischen musst du definieren.

Ich auch. Und zwar über USB-als-seriall. Das einzige Problem ist das 
dein Programm den Port (Pufferchip eigentlich) am PC abfragen muss damit 
der nicht überläuft.

Ich hab schon 2 x hier ein VB-Programm zu den Thema gepostet.

Und wieso unbedingt Binär. Das musst du im PC auch mühevoll unter 
Kontrolle halten. Und das ist viel schwerer als Ascii. Lass doch die 
Programme die Arbeit machen. ;)

Du liest in einer Schleife die Zeichen EINZELN ein und zählst sie sobald 
das Startzeichen kommt. Je nach Zahl weißt du sie einer Variable zu, die 
du dann weiter verarbeitest. Kommt das Endzeichen setzt du den Zähler 
wieder auf 0.

Danach prüfst du die Variablen auf gültige Werte und das war's.

Das ist Coden für Anfänger. ;)

von dummschwaetzer (Gast)


Lesenswert?

Mach doch Frage Antwort, also MC-seitig nicht dauersenden sondern erst 
auf Trigger vom Host

von Sascha W. (sascha-w)


Lesenswert?

Frank K. schrieb:
> Manche UARTs können auch einen 9-Bit Modus. Da kannst Du das 9. Bit als
> Blockindikator verwenden.
Die meisten μC können das. Aber ich wüsste kein OS auf dem PC das 9 
Datenbits unterstützt was auch dazu führt das Seriell-2-USB Wandler das 
nicht können. Das geht allenfalls noch mit einer Krücke die dazu das 
Paritätsbit missbraucht.

Sascha

von N. M. (mani)


Lesenswert?

Sascha W. schrieb:
> Aber ich wüsste kein OS auf dem PC das 9 Datenbits unterstützt

Ich hab sowas Mal gemacht mit den DS2XX Treiben (FTDI) bei 4MBit. Das 
ging ohne Probleme.
Mit den VCP Treibern hatte ich allerdings damals auch keinen Weg 
gefunden gehabt.

Eine andere Möglichkeit die ich auch schon genutzt habe:
Frame mit fester Länge.
Am Ende eine CRC (bei mir war es eine 32er).
Der uC sendet ständig Frames ohne spezielle Startkennung.
Der PC kann zu jeder Zeit einsteigen, muss dann aber aus dem Stream den 
ersten Frame erst Mal durch die CRC suchen. Ob man einen gültigen 
Frameanfang gefunden hat sieht man an der gültigen CRC.
Ist das nicht der Fall wirft man das erste Zeichen weg, bis man einen 
Frame gefunden hat (Framesuche).
Hat man erst Mal den Anfang gefunden, kann man mit der festen Framelänge 
zum nächsten Frame springen. Wenn es Übertragungsfehler gibt (CRC 
ungültig), muss man wieder zurück zur Framesuche.

: Bearbeitet durch User
von Johannes S. (Gast)


Lesenswert?

Wenn binär, dann das gute alte Siemens DUST Protokoll. Arbeitet mit 
STX/ETX als Anfang/Ende Kennung und Prüfsumme. Ist transparent, wenn die 
Steuerzeichen in den Daten vorkommen dann wird das Zeichen verdoppelt. 
Gibt es mit Sicherheit als fertige Lib für μC weil es ein Standard seit 
den 70zigern ist.
Bei der Power die μC heute haben würde ich es auch eher so machen wie 
gleich in der ersten Antwort, zusätzlich die Daten JSON formatieren.

https://de.m.wikipedia.org/wiki/3964R

von Experte (Gast)


Lesenswert?

Wenn's unbedingt Binär sein muss, mach's doch simpel. Startzeichen, 
Stopzeichen, etc. alles schön und gut, aber nicht notwendig.

Du hast:

  - Byte 1: ID. Definiere gültige IDs von 1 bis 255
  - Byte 2-5: Daten. Beliebig.

Das ist Dein "Frame". Was Du nun brauchst, ist ein 
Synchronisations-Frame das Du z.b. alle xxx Sekunden oder alle xxx 
normale Frames dazwischen schiebst.

Das Synchronisations-Frame wäre bei Dir 5 Null-Bytes. Die können nach 
obiger Definition nicht im Datenstrom vorkommen.

Ist der Empfänger nicht synchronisiert muss er nun einfach den 
Datenstrom auf 5 Null-Bytes absuchen. Danach kommen die normalen Frames. 
Ab und zu kommt wieder ein Synchronisations-Frame. Das kann der 
Empfänger dazu verwenden, um zu prüfen ob er noch synchron ist oder 
nicht, und im Falle neu synchronisieren.

von Wolfgang (Gast)


Lesenswert?

Knotenimhirn schrieb:
> Damit kann es nicht mehr wissen was eine ID ist und was Messwerte sind.

Du kannst ein Bit für die Synchronisation verwenden. Wenn du das oberste 
Bit in den übertragenen Bytes dafür reservierst und du mit 127 IDs 
auskommst, wird beim ID-Byte das oberste Bit gesetzt und die Messwerte 
werden in Paketen von 7 Bit pro Byte mit gelöschtem obersten Bit 
übertragen.
Ob sich das gegen separate Synchronisationsmechanismen rechnet, hängt 
von der Größe deiner Messwertblöcke ab.

Danilo schrieb:
> Hi, kannst ja auch zwischen dem Datenstrom eine Lücke einbauen. Dieser
> Timeout ist dann das "Startzeichen".

Pause machen ist manchmal nicht gut für die Performance ;-)
(Abgesehen davon macht ein UART das sowieso schon automatisch für die 
Bitsynchronisation)

von fop (Gast)


Lesenswert?

Man könnte ja auch vereinbaren :
- für jedes 0xaf in den Daten wird 0xfa 0x11 gesendet
- für jedes 0xfa in den Daten wird 0xfa 0x22 gesendet
- jeder Block beginnt mit 0xaf

Dann sollte die Sache klar sein. Und das bei minimalem Overhead, wenn 
man die im Beispiel benutzten Werte gegen recht selten in den Daten 
vorkommende Werte tauscht.

von Brt (Gast)


Lesenswert?

Hallo Kollegen,

wenn die Bandbreite knapp ist und man geizig sein muß:

Die effizienteste Variante beliebige Daten mit Werten zwischen 0 und 255 
in ein Framing zu packen ist COBS:

https://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing

Der encodierte Datensatz ist immer nur 1 Byte größer als das Original, 
im Gegensatz zu dem einfachen 'Escapen', bei dem jedes Vorkommen des 
Trennzeichens 2 zusätzliche Bytes hinzufügt (wegen der Escaperei).

Was vor mir schon von anderen geschrieben wurde gilt natürlich trotzdem:
Man muß genau prüfen ob sich der Aufwand für die binäre Übertragung 
lohnt. ASCII ist wirklich einfacher und praktischer zum Mitlesen und 
Debuggen. Verschwendet aber auch Bandbreite.


Grüße, Brt

von Brt (Gast)


Lesenswert?

Sorry, muß mich korrigieren:

Der encodierte Datensatz ist inclusive dem Trennzeichen immer 2 Bytes 
größer als der Netto-Datensatz.

Also 50 Bytes beliebige Werte zwischen 0..255 können mit genau 52 Bytes 
incl. Trennzeichen übertragen werden.

Grüße, Bert

von cppbert3 (Gast)


Lesenswert?

Brt schrieb:
> Man muß genau prüfen ob sich der Aufwand für die binäre Übertragung
> lohnt. ASCII ist wirklich einfacher und praktischer zum Mitlesen und
> Debuggen. Verschwendet aber auch Bandbreite.

ASCII und binär unterscheiden sich hier echt nur ganz minimal, Mitlesen 
ist ein Argument der Rest einfach nur persöhnlicher Geschmack, ich würde 
nie auf die Idee kommen ein ASCII Protokoll zu machen, spätestens wenn 
er Floating points oder doch irgendwelche Blobs uebertrage will ist 
ASCII zunehmende unsauber, mehr parsen, konvertieren und 
Abbildungsprobleme, das bisschen Endianess usw sind auch nur ein paar 
microzeilen Code

von MosFeratu (Gast)


Lesenswert?

Knotenimhirn schrieb:
> Dazu würde ich pro Sensor ein Byte
> mit der ID des Sensors schicken (damit der PC die nachfolgenden Daten
> richtig auswerten kann), und dann 4 Bytes mit dem Messwert. Also pro
> Sensor ein Paket aus 5 Bytes.

Einfach den höchsten möglichen Sensorwert $FFFF weglassen und den als 
Sync senden. Dann braucht du auch keine ID pro byte sondern sendest alle 
Daten hintereinander, dann wieder $FFFF. Die mögliche Ungenauigkeit 
beträgt 1 / 2^16, so genau ist kein Sensor.

von max123 (Gast)


Lesenswert?

Hallo,
ich schlage eine andere Methode vor. Der Empfänger, der PC schickt
zuerst eine Zahl zum Controller. Dieser Wert n bewirkt, dass n Bytes
vom Controller zum PC geschickt werden.
Ähnlich TCP/IP.

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
Noch kein Account? Hier anmelden.