Forum: Mikrocontroller und Digitale Elektronik Paketübertragung per UART


von Uwe H. (mistert)


Lesenswert?

Hallo Forum,

ich hab grad mal ein kleines Problem.
Zwar möchte ich über die Serielle Schnittstelle Pakete senden und 
empfangen.
Diese haben folgenden Aufbau an Nutzdaten:

[1Byte ID][nBytes Wert]

So wie kann ich die Pakete nun am besten verschicken? Also wie erkenn 
ich Anfang und Ende? Klar durch Start/Stoppbyte. Nur was nehm ich da als 
Codierung? Ich brauch ja alle 8Bit für die Übertragung der Werte und 
IDs. Es kann ja jede Bitfolge in einem Wert Byte vorkommen. Wie lös ich 
also das Problem?
Oder hab ich da grad nen Denkfehler?
Mein Überlegung war noch das ich nur 7Bit für den Inhalt, und 1 Bit dann 
für die Erkennung ob Startbit oder nicht. Aber dann brauch ich ja um ein 
8Bit Wert zu übertragen schon 2 Byte...

Gruß
Uwe

von ozo (Gast)


Lesenswert?

Wie wärs mit
[Byte ID][Byte n][Data 0]...[Data n]

von holger (Gast)


Lesenswert?

> So wie kann ich die Pakete nun am besten verschicken?

Wie ozo schon sagte: eins nach dem anderen, aber bitte
nicht wild durcheinander !

von Minetti (Gast)


Lesenswert?

Wenn du 0x00 nicht als End-Byte nehmen kannst, wie wärs mit 
base64-Codierung? Die Anzahl kannst du zusätzlich übertragen, falls ein 
Paket verloren geht kannst das dann feststellen.

von Marko (Gast)


Lesenswert?

oder das neunte Bit für die Adressierung

von rene (Gast)


Lesenswert?

Schau doch mal mein protokoll an :
http://www.ibrtses.com/embedded/shortmsgprotocol.html

rene

von Uwe H. (mistert)


Lesenswert?

Das mit dem 9. Bit war auch schon meine Überlegung. Nur können das die 
meisten Terminal Programme wohl nicht. Die Daten wo ich verschicke 
sollen dann auch per Labview ausgewertet werden, fraglich ob das damit 
klar kommt.


@holger
Da ist nichts wild durcheinander ;)
Ein Paket besteht aus 1 Byte wo die ID drin steht, dahinter kommt eine 
beliebige Anzahl von Bytes wo der dazugehörige Wert steht.
Die Pakete sollten so kompakt wie möglich sein.

@Minetti
Bei der base64 Codierung muss ich ja immer Blöcke mit 3 Bytes 
verarbeiten. Das erzeugt u.U. wieder viel Overflow. Aber ansonsten eine 
gute Idee, werde ich mir mal noch genauer anschauen.

von Sonic (Gast)


Lesenswert?

Was willst du denn übetragen? Wenn's möglich ist das Ganze ASCII zu 
übetragen ist das die einfachste Methode. Einfach Startsequenz (mehrere 
Byte), die Nutzdaten und anschließend eine CRC16-Checksumme schicken. 
Ich habe auf diese Weise Zählerstände Drahtlos übermittelt und bin sehr 
zufrieden mit dem Ergebnis.
Bei Binärdaten ist das Ganze natürlich etwas komplizierter ...

von Uwe H. (mistert)


Lesenswert?

Ich muss Messwerte von 10 Sensoren auswerten und dann per USART 
rausschicken. Um die Messwerte zu unterscheiden soll eben eine ID vorne 
angehängt werden.
Da die Sensoren zum Teil mit 1000Hz abgefragt werden, sollten die Pakete 
nicht unnötig groß sein.

Achja, die Messwerte sind also eigentlich nur integer Werte.

von Sonic (Gast)


Lesenswert?

Na, da ist ASCII doch prädestiniert für! Kannst dich ja mal am NMEA 
(GPS) oder Modem-Protokolle orientieren. Baudrate halt etwas hochsetzen 
(38400 baud oder so), dann klappt das prima!

von Uwe H. (mistert)


Lesenswert?

Ja aber bei ASCII verschwende ich doch pro Zeichen 8Bit, das find ich 
halt schon etwas viel.

von holger (Gast)


Lesenswert?

Vergiss die ganzen Posts oben !

Stell deine Schnitstelle auf 1 Startbit, 8 Datenbits, 1 Stopbit ein.
Um Startbit und Stopbit musst du dich NICHT kümmern. Das macht
die Hardware. Was am Ende rauskommt sind einfach die 8 Datenbits.
Wenn du die vernünftig formatierst kann nichts schief gehen.

1:Byte ID   wahrscheinlich um auszuwerten wofür das Paket gut ist
2:Byte n    gibt an wieviele Datenbytes empfangen/gesendet werden
3:Byte 0    erstes Datenbyte
4:Byte 1    zweites Datenbyte
.
.
.
.           letztes Datenbyte

von Sonic (Gast)


Lesenswert?

Natürlich kannst du das Gaze auch binär übertragen, wie du das codierst 
bleibt dir überlassen. Am Ende eine CRC-Prüfung, dann klappt das auch. 
Aber grade wegen der Starterkennung ud IDs ist ASCII eben einfacher.

von Uwe H. (mistert)


Lesenswert?

ja so hatte ich das bisher, nur ohne ein Byte mit der länge.
Dann konnte ich aber halt nie unterscheiden wann ein Paket zu ende war. 
Aber auf die Idee einfach ein Byte mit der Anzahl der Bytes zu senden 
bin ich nicht gekommen :-(
Ich werde mal testen ob das so funktioniert. Und ob Labview das dann 
korrekt entschlüsseln kann.
Kennt jemand sonst noch ne Software die so etwas visualisieren kann?

von Sonic (Gast)


Lesenswert?

>1:Byte ID   wahrscheinlich um auszuwerten wofür das Paket gut ist
Und wenn ein Datenbyte diesen Wert hat und der Empfänger in diesem 
Moment zugeschaltet wird ???

von Rahul D. (rahul)


Lesenswert?

>1000Hz
Und an welche Baudrate hast du gedacht?

Wie wäre es denn, wenn du ein Paket "schnürst", das die Werte der 
Sensoren der Reihe nach überträgt.
Interessant ist auch, Temperaturen mit 1kHz abzufragen (vermutlich 
irgendein Verbrennungsprozess, da sich die Raumtemperatur in längeren 
Intervallen ändert...).

von Uwe H. (mistert)


Lesenswert?

Baudrate? Was der Controller so bringt :D Momentan läufts mit 38400, 
aber da ist nach oben ja noch etwas Luft.
Wie meinst du der Reihe nach? Da gibts das Problem das manche Sensoren 
eben mit 1kHz (wobei dies noch nicht sicher ist) und manche nur mit 10Hz 
oder weniger abgetastet werden. Also sollten diese schon sobald ein Wert 
anliegt verschickt werden.

@Sonic
Der Empfänger läuft eigentlich bevor der Sender sendet, das sollte 
erstmal nicht so schlimm sein. Oder hast du grad nen Lösungsvorschlag 
parat?

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Bei der Paketierung muss man nicht ein Bit pro Byte verschwenden, siehe 
Beitrag "Re: Befehlsschnittstelle erstellen".

von Sonic (Gast)


Lesenswert?

Ich habe das bei einem Drahtlossystem so gemacht: EIN Master der alle 
Slaves nacheinander abfragt. Als Start eine Präambel 0x55 (ist ein 
Rechtecksignal), danach 2x 0xFF (High-Signal bekannter Länge), hierauf 
wird der Start der Daten eingeleitet, danach kommen Daten. Am Ende 
CRC16-Checksumme. Alles was dazwischen kommt kannst du dir einteilen wie 
du willst.
Wenn die Messstellen natürlich willkürlich senden wird's komplizierter.

von holger (Gast)


Lesenswert?

>Ich muss Messwerte von 10 Sensoren auswerten und dann per USART
>rausschicken. Um die Messwerte zu unterscheiden soll eben eine ID vorne
>angehängt werden.
>Da die Sensoren zum Teil mit 1000Hz abgefragt werden, sollten die Pakete
>nicht unnötig groß sein.

Autsch !

10 Sensoren a 2 Bytes plus eine ID.
Also sagen wir mal 3 Bytes * 10 mit 1kHz.
Das sind 30000 Bytes/s. Bei 8 Datenbits mit 1 Start/Stop Bit
sind das 300000 Bits /s. Das macht deine serielle Schnittstelle
sicher nicht mehr mit !


von holger (Gast)


Lesenswert?

Scheiße schon wieder zu spät ;)
Könnte er endlich mal eine KOMPLETTE Anforderung rüberreichen ?

von Uwe H. (mistert)


Lesenswert?

@sonic
Die Sensoren werden ja vom AVR abgefragt und die Daten auch von dort aus 
verschickt.

@holger
Deine Rechnung geht nicht auf ;) Nicht alle 10 Sensoren werden mit 1kHz 
abgefragt.

von Dirk H. (arm-dran)


Lesenswert?

Bei der Übertragung von Datenstrings über die serielle Schnittstelle 
gibt es eine primäre Gefahrenquelle!

Und die heisst Synchronisationsverlust.

Das heisst, es gibt keine eindeutige Identifikation, an welcher Stelle 
des Datenstrings man sich gerade befindet.
Da in einem binären Datenstring jedes Datenbyte das andere in seinem 
Wert ersetzen kann, ist es möglich, daß das Protokoll sozusagen außer 
Tritt gerät.

1. Möglichkeit:
Trennung von binären Datenstrings durch eine Zeitlücke, wobei 
gewährleistet sein muß, daß die Abstände zwischen den Datenbytes im 
String immer kleiner als die Austastzeitlücke ist.
Im Binären Datenstring können Startbyte, Zählbyte, Datenbytes den 
gleichen Wert annehmen. Sollte im Protokoll ein Fehler auftreten, kann 
der Anfang des Strings nicht mehr eindeutig identifiziert werden.

2. Möglichkeit:
Wie von Sonic schon beschrieben, die Daten als ASCII Werte übertragen.
Daher 1 Byte als 2 Zeichen. Dafür brauchst Du dann zwar die doppelte 
Übertragungsrate, hast aber ein Ultra-felxibles Protokoll. Zeitlücke 
kannst Du Dir sparen.
Wie hoch ist denn Dein Datenaufkommen???


von Sonic (Gast)


Lesenswert?

Also die Sensoren werden vom µC abgefragt und aud einen PC (oder 
ähnlich) per USART übertragen? Dann sammle die Messergebnisse bis der 
letzte Sensor abgefragt ist und schicke das Ganze in einem festgelegten 
Protokoll 'raus.
Ob da jetzt ein Sensor 10x abgefragt wird ist gegenstandslos, der 
langsamste gibt den Übertragungsrhytmus vor.

von Uwe H. (mistert)


Lesenswert?

@sonic
und gerade das will ich nicht! Die Sensoren sollen schon mit 
Unterschiedlicher Frequenz abgetastet werden und verschickt werden.

Das Datenaufkommen kann ich noch nicht genau bestimme. Zur Test und 
Kalibrierungsphase sollen die Sensoren so oft abgefragt werden wie der 
Sensor es her gibt. Dabei müssen nicht alle 10 Sensoren unbedingt 
übertragen werden.
Im späteren Flugbetrieb reicht es sicher wenn man die Abtastrate runter 
setzt. Nur um das zu beurteilen sollen am Anfang alle Sensorwerte 
übertragen werden.

von Gast (Gast)


Lesenswert?

Noch ein Vorschlag nach dem gar nicht gefragt wurde. Wenn es nur 10 
Sensoren sind, dann würden ja 4 Bit reichen, um die Sensoren zu 
identifizieren. Bleiben von einem Byte noch 4 Bit übrig (angenommen man 
sendet 8Bit pro Byte) um die länge zu definieren. Man könnte also noch 
zwischen 0 und 15 oder 1 bis 16 Datenbyte senden, falls das reicht. So 
reicht ein Byte für Identifikation und Anzahl der Bytes (Problem ist, 
dass dann in diesem Byte auch fast jede Information auftauchen kann und 
ein ausgelassenes Byte die gesamte Kommunikaiton total aus dem Tritt 
bringt...

Gast.

von holger (Gast)


Lesenswert?

@holger
>Deine Rechnung geht nicht auf ;) Nicht alle 10 Sensoren werden mit 1kHz
>abgefragt.

Danke für die fehlenden Informationen. Ich geh jetzt schlafen
und morgen interessierts mich einfach nicht mehr ;)

von A.K. (Gast)


Lesenswert?

Andere Variante, ungefähr orientiert an PPP(async): 0xFF trennt Pakete. 
Kommen im Paket die Codes 0xFE oder 0xFF vor, wird zuerst 0xFE 
übertragen, danach das ursprüngliche Byte XOR 0x20.

Ergibt eindeutige Trennung der Pakete, und kostet anders als Base64 oder 
andere Recodierungen webder nennenswert Bandbreite (~1%) noch 
Rechenleistung.

von Uwe H. (mistert)


Lesenswert?

@holger

da stehts ;)
> Wie meinst du der Reihe nach? Da gibts das Problem das manche Sensoren
> eben mit 1kHz (wobei dies noch nicht sicher ist) und manche nur mit 10Hz
> oder weniger abgetastet werden.

@gast
nein das geht leider auch nicht. Ich brauch noch platz für mehrere IDs. 
Also 6 Bit bräucht ich mindestens.

von Sonic (Gast)


Lesenswert?

>Die Sensoren sollen schon mit Unterschiedlicher Frequenz abgetastet werden und 
verschickt werden.
Da kriegst du ja jede Menge Kollisionen 'rein, wie soll denn das gehen?
Was für einen BUS benutzt du da? Mit CAN geht das meises Wissens, mit 
I²C auch. Aber mit RS232 wird das nicht funktionieren!

von Uwe H. (mistert)


Lesenswert?

@A.K.
Also so eine Art ByteStuffing?

@sonic
Ich versteh das Problem nicht ganz. Die Sensoren sind an den I/O Ports 
des AVRs angeschlossen. Oder am ADC.

von A.K. (Gast)


Lesenswert?

Ja.

von Sonic (Gast)


Lesenswert?

Wohin gehen denn die Daten? Zum PC?

von Uwe H. (mistert)


Lesenswert?

ja genau, der AVR dient im Prinzip nur dazu die Sensoren auszuwerten und 
die Daten an den PC zu schicken.

von mng (Gast)


Lesenswert?

Google mal nach "Consistent Overhead Byte Stuffing"... Eine ziemlich
einfache und dennoch geniale Lösung, um sämtliche 0x00-Bytes aus den
Nutzdaten herauszufiltern um die 0x00 dann als Trennzeichen verwenden zu
können; und das bei annähernd garkeinem Overhead.

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.