Forum: Mikrocontroller und Digitale Elektronik UART Protokoll für µC


von Robert S. (bimbo385)


Lesenswert?

Hallo an alle,

ich suche schon ziemlich lange nach einer Lib oder einem Standard für
die serielle (UART) Kommunikation zwischen µC und PC bzw. µC und µC.

Anwendungsfall wäre üblicherweise folgender: Ich hab irgendein Gerät mit
einem (relativ kleinen) µC (Atmega o.Ä.) der per UART (+ FTDI, CP2102)
an einem PC hängt.
Jetzt möchte ich Datensätze (z.B. aus C Strukturen) an ein
Computerprogramm übertragen und dort nutzen und natürlich auch wieder
zurück übertragen.

Jetzt kann man sich natürlich selbst irgendein Übertragungsprotokoll
ausdenken und das ständig anpassen. Ist fehlerträchtig, aufwendig und
unflexibel.

Hat das jemand schon mal intelligenter und universell gelöst? Diese
Problemstellung kann ich ja kaum alleine haben...

Ich hab mir schon mal Protobuf bzw. nanopb angeschaut.
Zum Verpacken von Strukturen in Arrays OK, aber das löst ja noch nicht
die serielle Übertragung. Also ich muss ja auch noch wissen wo ein
Datenpaket anfängt und aufhört usw.
Die point to point Protokolle aus dem Ethernet Bereich sind irgendwie
viel zu mächtig und groß für den kleinen µC.

Btw. ich hab jetzt nicht das Problem ein Array per UART zu übertragen
oder so. Da gibt es ja je nach µC Libs zu.

Wie löst ihr sowas?

Gruß!

: Verschoben durch Moderator
von Georg G. (df2au)


Lesenswert?

KISS ist klein und hat wenig Overhead. Wenn du dazu noch ein CRC16 
spendierst, ist es fast 100% wasserdicht.

von Purzel H. (hacky)


Lesenswert?

> Jetzt kann man sich natürlich selbst irgendein Übertragungsprotokoll
ausdenken und das ständig anpassen. Ist fehlerträchtig, aufwendig und
unflexibel.
>
>Hat das jemand schon mal intelligenter und universell gelöst? Diese
Problemstellung kann ich ja kaum alleine haben...


Man kann sich selbst ein universelles Uebertragunsgprotokoll ausdenken. 
Weshalb sollten das irgendwelche Anderen besser koennen ? Du kennst die 
Anwendungsfaelle, du kennst die Resourcen. Man hat nicht immer alle 
Moeglichkeiten, auch mit fast unlimitiertem Aufwand.

Ist es :
-Punkt zu punkt, Master-Slave, oder Multimaster
-konstante oder variable Paketlaengen
-soll man am Terminal mitlesen koennen(ASCII), oder Binaer
-wie hoch kann die Ausfallrate sein
-muessen die Daten ankommen, oder ist das eher nicht so wichtig
-sind Retries moeglich, oder eher nicht.

Man kann ein Protokoll an diese Anforderungen anpassen. Die Punkte sind 
kein witz, existieren alle als Implementationen, resp 
Implementationsdetails.

: Bearbeitet durch User
von Strubi (Gast)


Lesenswert?

Bimbo 3. schrieb:
> Hat das jemand schon mal intelligenter und universell gelöst? Diese
> Problemstellung kann ich ja kaum alleine haben...

Schon. Benötigt aber doch etwas mehr Framework und ist ev. zu 
schwergewichtig für deinen Zweck, obwohl's auch auf einem Atmel 32U4 bei 
mir über UART läuft. Nennt sich intern "network property protocol". Die 
Geräte beschreibst du dabei in einer XML-Sprache. Source&Demo findest du 
hier zur Inspiration:

http://section5.ch/index.php/2017/09/12/netpp-for-windows-quick-start/

Was damit nicht geht, sind Bulk-Übertragungen von struct-Containern, das 
musst du in der Version noch mit BUFFER-Datentypen machen.
Lohnt sich alles aber erst, wenn du eine Menge Gerätetypen, die sich 
auch noch ändern können, mit einem Protokoll erschlagen willst.

von Olaf (Gast)


Lesenswert?

In der Industrie gibt es natuerlich viele Protokolle. Ein relativ 
verbreitetes und auch offenes (du findest Dokus) ist Modbus.
Der Vorteil, neben der vorhandenen Doku, besteht darin das du auch 
Diagnosetools auf dem PC nutzen kannst.

Eine andere Moeglichkeit waere natuerlich CAN-Bus, setzt aber in der 
Regel einen Microcontroller vorraus der das unterstuetzt.

Und selbst wenn man was komplett eigenes macht, es empfiehlt sich die 
Doku von so einem Industriekram mal zu lesen weil man dann einige kluge 
Ideen uebernehmen kann. (Pruefsummen, Blockcounter, Laengen usw)

Olaf

von Purzel H. (hacky)


Lesenswert?

Bevor man sich in Details wie CAN, RS485, usw verheddert sollte man sich 
vergewaertigen was mit Paketverlusten geschehen soll.

-Sind egal, Retries genuegen
-Sind egal, weitermachen, verlorene Daten sind nicht so wichtig.
-Paketverluste sollten minimiert werden

Denn je nachdem haben sie Einfluss auf die Uebertragunsgrate und 
Reaktionszeit.

Weiter : gibt es Kriterien an die Reaktionszeit, resp Brutto 
Uebertragunsgrate. Die Loesung ist nicht immer die Baudrate.

: Bearbeitet durch User
von Curby23523 N. (Gast)


Lesenswert?

Bimbo 3. schrieb:
> ich suche schon ziemlich lange nach einer Lib

Oder hast du einfach nur keine Lust dir was eigenes auszudenken? 
Generation "LIB" und Generation "Arduino".

Du könntest dir - gerade für RS232, RS485 und UART - eine Modbus LIB 
schreiben. Ja, die gibt es auch für AVR garantiert irgendwo schon frei 
zum downloaden - oder du schreibst sie an einem Tag selber und weißt 
dafür, wie sie funktioniert.

von Daniel V. (danvet)


Lesenswert?

Ich verwende gerne
http://www.ibrtses.com/embedded/shortmsgprotocol.html
oder für größere Datenmengen
http://www.ibrtses.com/embedded/longmsgprotocol.html
Das hat man realativ schnell umgesetzt und funktioniert gut.
Achtung, er beschreibt seine Funktionsrümpfe in Pascal ;-)

von W.S. (Gast)


Lesenswert?

Bimbo 3. schrieb:
> Jetzt möchte ich Datensätze (z.B. aus C Strukturen) an ein
> Computerprogramm übertragen und dort nutzen und natürlich auch wieder
> zurück übertragen.

Datensätze?

Für sowas gibt es nirgendwo ein allumfassendes Protokoll, was allen 
Ansprüchen genügt. Also ist der Entwurf für was Eigenes wohl immer 
nötig.

Laß mal die Vorstellung von Datensätzen beiseite und beschränke dich auf 
das Übertragen von Daten - und zwar soweit möglich im Klartext (ASCII), 
weil du damit fast automatisch einige Sicherheiten eingebaut hast: Du 
hast die Möglichkeit, z.B. zeilenweise zu senden und zu empfangen, womit 
du schon mal die Synchronisierung hast, dazu Trennzeichen zwischen 
Daten-Teilen, eigentlich beliebige Datenformate und so.

Denkbar ist aber auch eine Art UPN, also Zahl zuerst (in ASCII), dann 
ein Buchstabe als Trenner und Kommando zugleich.

Denkbar ist ebenfalls, den Zahlenbereich 0..255 von übertragenen Bytes 
in passable Gruppen zu unterteilen. Ich hatte das für meine 
Alternativ-Software für den FA-NWT so gemacht, um zugleich Wobbeldaten 
vom Gerät zum PC sowie Kommando- und Statusverkehr zwischen Gerät und PC 
zu übertragen.

W.S.

von Ruediger A. (Firma: keine) (rac)


Lesenswert?

Hallo,

für das, was Du möchstest, hat sich im Embedded Bereich JSON als 
Applikationsprotokoll etabliert, wobei da aber natürlich nicht die 
tieferen ISO Schichten (Busadressierung, Framing etc) adressiert sind.

Ich habe ein Protokoll entworfen, das deine Voraussetzungen so ziemlich 
erfüllt. Es heisst UTISCP (Universal Transport Independent Securable 
Communication Protocol) und ist z.Zt. bei mehreren industriellen Kunden 
in der Pilotphase. Der Applikationslayer ist komplett konfigurierbar, 
d.h. Du kannst auf demselben Basisframing verschiedene 
Applikationsprotokolle nebeneinander fahren.

Es wird letztendlich offen sein und nichts kosten, aber während der 
Pilotphase ist ein NDA Voraussetzung (bis eventuelle Kindekrankheiten 
raus sind, will ich wissen, wo es ist und wer damit schafft). 
Interessenten dürfen sich gerne per PM oder über meine HP 
(www.ruediger-asche.de) melden.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Ich würde mal noch msgpack in die Runde werfen:

https://msgpack.org/

"It's like JSON.
but fast and small."

von Falk B. (falk)


Lesenswert?

@ Nils N. (nils_h494)

>> ich suche schon ziemlich lange nach einer Lib

>Oder hast du einfach nur keine Lust dir was eigenes auszudenken?
>Generation "LIB" und Generation "Arduino".

Nö, der macht das schon richtig und will das Rad NICHT neu erfinden. 
Warum sollte jeder seinen OneWire, LCD, Ethernet, TCP/IP Treiber selber 
schreiben?

Wiederverwendung bestehender, getesteter und BEWÄHRTET Komponenten war 
schon immer sinnvoll, nicht erst im IT-Zeitalter.

von W.S. (Gast)


Lesenswert?

Daniel V. schrieb:
> Ich verwende gerne...

Das hat den Nachteil, daß man erstens nur blockweise arbeiten kann und 
zweitens (schwerwiegender) nicht zwischen Daten und Steuerzeichen 
unterscheiden kann:

[SYN+] STX Len SRC DST Cmd [Data] CRC
bzw.
[SYN++] STX (LenLo LenHi) SRC DST Cmd [Data] (CRCLo CRCHi)

Hierbei muß man immer den Blockbeginn kennen, sonst funktioniert das 
Ganze überhaupt nicht.

Dieses Protokoll ist rein binär und deshalb eben nicht 
selbstsynchronisierend.

Es kommt noch etwas hinzu: bei rein binären Formaten ist man darauf 
angewiesen, daß beide Geräte intern exakt die gleiche Darstellung haben. 
Das geht öfter als einem lieb ist in die Hose. Ich hab lange genug Daten 
austauschen müssen zwischen Geräten mit internem big endian und solchen 
mit little endian - und da kracht es eben immer, sobald Daten länger 
sind als 8 Bit. Ein ähnliches gilt für numerische Daten im 
Gleitkommaformat.

Also tut man gut daran, auf einer seriellen Schnittstelle mit 
endianfreien Daten zu arbeiten, z.B. eben mit reinem ASCII-Text. Das 
braucht zwar ein paar Zeichen mehr zur Übertragung, aber dafür ist es 
unabhängig von den Interna der beteiligten Geräte.

W.S.

von Niklas Gürtler (Gast)


Lesenswert?

W.S. schrieb:
> Daten austauschen müssen zwischen Geräten mit internem big endian und
> solchen mit little endian

Das kann man auch konvertieren, wenn man das mit Bitshifts macht ist das 
auch portabel.

Wenn es nur um uC<->PC geht könnte man sich überlegen USB direkt zu 
nutzen. Da muss man keine Paketanfänge erkennen und keine Flusskontrolle 
und Fehlereekennung implementieren, weil das da schon die Hardware 
macht. Natürlich ist einiges an Basis Software nötig, aber wenn man die 
einmal hat (als Library oder selbst gemacht) braucht man nur noch seine 
eigenen Daten zu übertragen. Siehe z.B. USB-Tutorial mit STM32.

Soll es doch UART sein, kann man Paketanfänge über den IDLE Interrupt 
(d.h. die Pause zwischen Paketen) erkennen und danach ein Paket am Stück 
empfangen. Eignet sich auch gut für DMA-fähige Controller.

von Purzel H. (hacky)


Lesenswert?

> Also tut man gut daran, auf einer seriellen Schnittstelle mit
endianfreien Daten zu arbeiten, z.B. eben mit reinem ASCII-Text.


Ach soooo?  ... waere '1234' also 1234, oder eher 4321, alles als ASCII?

Da man den Code auf beiden Seiten schreibt, solle es doch moeglich sein, 
die Meldungen richtig zu formatieren. Man muss nicht bitshiften, sondern 
Bytes in der passenden Reihenfolge senden.
Ob bei Little Endian, oder Big Endian, die Bytes sind auf alle faelle 1 
& 2 & 3 & 4, in ASCII geschrieben.

von Curby23523 N. (Gast)


Lesenswert?

Falk B. schrieb:
> @ Nils N. (nils_h494)
>
>>> ich suche schon ziemlich lange nach einer Lib
>
>>Oder hast du einfach nur keine Lust dir was eigenes auszudenken?
>>Generation "LIB" und Generation "Arduino".
>
> Nö, der macht das schon richtig und will das Rad NICHT neu erfinden.
> Warum sollte jeder seinen OneWire, LCD, Ethernet, TCP/IP Treiber selber
> schreiben?
>
> Wiederverwendung bestehender, getesteter und BEWÄHRTET Komponenten war
> schon immer sinnvoll, nicht erst im IT-Zeitalter.

Was ja per se auch vollkommen in Ordnung ist. Aber gerade ein kleines, 
simples Protokoll hätte er schneller selber programmiert, als "ich suche 
schon ziemlich lange nach einer Lib".

von Daniel V. (danvet)


Lesenswert?

W.S. schrieb:
> Daniel V. schrieb:
>> Ich verwende gerne...
>
> Das hat den Nachteil, daß man erstens nur blockweise arbeiten kann und
> zweitens (schwerwiegender) nicht zwischen Daten und Steuerzeichen
> unterscheiden kann:
>
> [SYN+] STX Len SRC DST Cmd [Data] CRC
> bzw.
> [SYN++] STX (LenLo LenHi) SRC DST Cmd [Data] (CRCLo CRCHi)
>
> Hierbei muß man immer den Blockbeginn kennen, sonst funktioniert das
> Ganze überhaupt nicht.
>
> Dieses Protokoll ist rein binär und deshalb eben nicht
> selbstsynchronisierend.
>

Ich glaube du irrst dich. In meinen Implementationen habe ich sehr wohl 
eine Selbstsynchronisierung. Das kann man bei EMV-Tests sehen.

>
> Also tut man gut daran, auf einer seriellen Schnittstelle mit
> endianfreien Daten zu arbeiten, z.B. eben mit reinem ASCII-Text. Das
> braucht zwar ein paar Zeichen mehr zur Übertragung, aber dafür ist es
> unabhängig von den Interna der beteiligten Geräte.
>

Das habe ich jetzt nicht verstanden.
Willst du behaupten dass z.B. das Ethernetprotokoll ASCII bassiert ist?

Was du in deinen Datenbereich reinpackst, bleibt bei dem vorgeschlagenen 
Protokoll völlig offen. Von mir aus ASCII.

von Falk B. (falk)


Lesenswert?

@Nils N. (nils_h494)

>Was ja per se auch vollkommen in Ordnung ist. Aber gerade ein kleines,
>simples Protokoll hätte er schneller selber programmiert, als "ich suche
>schon ziemlich lange nach einer Lib".

Nö. Du unterschätzt den Aufwand für Selbermachen und Testen um 
Größenordungen!

Wie auch dieser Teilnehmer.

Beitrag "Re: FIFO32: Versatile 32 bit fifo with variable array length"

von Ruediger A. (Firma: keine) (rac)


Lesenswert?

W.S. schrieb:
>
> Es kommt noch etwas hinzu: bei rein binären Formaten ist man darauf
> angewiesen, daß beide Geräte intern exakt die gleiche Darstellung haben.
> Das geht öfter als einem lieb ist in die Hose. Ich hab lange genug Daten
> austauschen müssen zwischen Geräten mit internem big endian und solchen
> mit little endian - und da kracht es eben immer, sobald Daten länger
> sind als 8 Bit. Ein ähnliches gilt für numerische Daten im
> Gleitkommaformat.
>
> Also tut man gut daran, auf einer seriellen Schnittstelle mit
> endianfreien Daten zu arbeiten, z.B. eben mit reinem ASCII-Text. Das
> braucht zwar ein paar Zeichen mehr zur Übertragung, aber dafür ist es
> unabhängig von den Interna der beteiligten Geräte.
>
> W.S.

Tut mir leid, der Empfehlung muss ich widersprechen. Das Aufblähen jedes 
Bytes auf die doppelte Grösse wird erfahrunsggemäss von der Last auf der 
seriellen Schnittstelle her untragbar, wenn das Datenvolumen etwas 
grösser wird.

Jeder in der Netzwerkprogrammierung erfahrene Entwickler hat es 
verinnerlicht, htons(), htonl(), ntohs() und ntohl() zu verwenden, um 
genau die Little-Big Endian Probleme zu umschiffen. Ist halt eine 
Disziplinierungsfrage. Wer aber einmal dadurch musste, in einer 
Codebasis sämtliche Konvertierungsschludereien beim Umstieg auf eine 
andere Endian Architektur zu finden und zu bereinigen, wird IMMER 
htons()... im Hinterkopf haben (ist wie Elektroschocktherapie).

Ein "Vorteil" der ASCII Protokollspezifikation ist, dass das framing 
leichter wird (wenn alle Zeichen einer Payload in einem eingeschränkten 
Zeichensatz sind, lassen sich Framingzeichen aus dem verbleibenden 
Vorrat wählen, ohne an Transposition o.ä. denken zu müssen). Wenn man 
allerdings ein sauberes framing implementiert, sit das auch bei 
Binärprotokollen kein Problem.

von Daniel V. (danvet)


Lesenswert?

Ruediger A. schrieb:
>
> Ein "Vorteil" der ASCII Protokollspezifikation ist, dass das framing
> leichter wird (wenn alle Zeichen einer Payload in einem eingeschränkten
> Zeichensatz sind, lassen sich Framingzeichen aus dem verbleibenden
> Vorrat wählen, ohne an Transposition o.ä. denken zu müssen). Wenn man
> allerdings ein sauberes framing implementiert, sit das auch bei
> Binärprotokollen kein Problem.

Ach so. Jetzt habe ich verstanden worauf er hinaus wollte.
Ist aber bei dem vorgeschlagenen Protokoll wie gesagt kein Problem. 
Insofern scheint das "Framing" gut zu sein :-)

von Jack (Gast)


Lesenswert?

Bimbo 3. schrieb:
> Also ich muss ja auch noch wissen wo ein
> Datenpaket anfängt und aufhört usw.
> Die point to point Protokolle aus dem Ethernet Bereich sind irgendwie
> viel zu mächtig und groß für den kleinen µC.

SLIP, RFC 1055 https://tools.ietf.org/html/rfc1055. Damit kannst du 
Datensätze übertragen wie du lustig bist, auch binäre. Sourcecode gibt 
es auf den letzten Seiten des RFC.

Das Gerede über IP im RFC kann man ignorieren, es sei denn man braucht 
IP. SLIP ist so einfach, dass es hier schon Leuten die Zornesröte ins 
Gesicht getrieben hat, weil es nicht ihren Vorurteilen über Protokollen 
aus dem IP-Umfeld entsprach.

von Einer K. (Gast)


Lesenswert?

Bimbo 3. schrieb:
> Hat das jemand schon mal intelligenter und universell gelöst?

Aus der Arduino Welt:
Schaue dir den CmdMessenger an. (oder schaue dir da was ab)

Der machts dir wahlweise in ASCII und auch binär.
Anbindung an C# ist dabei.

von Martin S. (strubi)


Lesenswert?

Ruediger A. schrieb:
> Tut mir leid, der Empfehlung muss ich widersprechen. Das Aufblähen jedes
> Bytes auf die doppelte Grösse wird erfahrunsggemäss von der Last auf der
> seriellen Schnittstelle her untragbar, wenn das Datenvolumen etwas
> grösser wird.

Und lustig wird's dann, wenn die Länge des ASCII-Strings a priori noch 
nicht bekannt ist. Spricht insbesondere gegen Zero-Copy-Ansätze zur 
simplen/performanten Übertragung.

Aber über Transport-Layer lässt sich beliebig streiten. Ich bin ein 
Freund von Framing/Timeouts, irgendwelche Start/Stop-Zeichen, die im 
Datenstrom dann ge-escape't werden müssen sind auch wieder 
problematisch. Dass uCs dann einen Datenstrom durchsuchen sollen um sich 
wieder zu synchronisieren ist in manchen Anwendungen ein no go.

Also divide et impera:
- Suche dir entsprechend deiner Schnittstelle und ihrer 
Fehleranfälligkeit ein Frame-basiertes Transportprotokoll
- Verpacke deinen Lieblings-Protokoll-Layer
- Und ja, ntoh*/hton* sollten dabei das geringste Thema sein

von Olaf (Gast)


Lesenswert?

> Also tut man gut daran, auf einer seriellen Schnittstelle mit
> endianfreien Daten zu arbeiten, z.B. eben mit reinem ASCII-Text. Das
> braucht zwar ein paar Zeichen mehr zur Übertragung, aber dafür ist es
> unabhängig von den Interna der beteiligten Geräte.

Halte ich fuer totalen Quatsch weil dann die Uebertragung doppelt so 
lange dauert und der Mikrocontroller viel zu lange aus dem Sleepmode 
geht und viel zu viel Strom braucht.Und gerade Datenuebertragungen sind 
Strommaessig teuer weil sie oft ueber Optokoppler gehen. Absolut 
inaktzeptabel.
Jedenfalls fuer meine Anwendungen. :-)

Und das ist auch der Grund warum es schlecht ist wenn Arduinokids nichts 
mehr selber auf die Reihe bekommen und nur noch faul kopieren. Wenn man 
die Interna nicht mehr versteht findet man keine optimalen Loesungen 
fuer die eigenen Probleme. Und wenn man sich drei Loesungen aus drei 
Quellen zu einem 'eigenen' Programm zusammenkopiert dann ist man nicht 
nur ein Looser weil man nichts eigenes mehr schafft, sondern die 
Wahrscheinlichkeit ist auch gross das man sich ein dickes Probleme 
eingekauft hat weil unterschiedliche fremde Software nicht immer so gut 
miteinander harmoniert.

Olaf

von Einer K. (Gast)


Lesenswert?

Olaf schrieb:
> ..

Du irrst!

von Johannes S. (Gast)


Lesenswert?

DUST 3964R ist ein grottenaltes Protokoll, funktioniert aber auch heute 
noch gut. Da findet man bestimmt auch Arduino Libs und es gibt viele 
Analysetools die das verstehen.

von W.S. (Gast)


Lesenswert?

Ruediger A. schrieb:
> Tut mir leid, der Empfehlung muss ich widersprechen. Das Aufblähen jedes
> Bytes auf die doppelte Grösse...

Also erstens, du redest von der doppelten Größe und das ist mir zu 
primitiv. Ich versuch's mal weiter unten zu erläutern.

Zweitens wird hier immer wieder und zwar hartnäckig von 
blockorientierter Übertragung (framing..) geschrieben. Das ist in 
Umgebungen von Ethernet und HF zwar usus, aber bedenke mal, daß zwischen 
einer Übertragung in QPSK o.ä. mit entsprechenden Endgeräten und einem 
simplen UART im µC, wie es der TO angesprochen hat, Welten dazwischen 
liegen. Was meinst du eigentlich, weshalb es nen UART in jedem popligen 
µC gibt und sowas wie Ethernet MAC und PHY drei Nummern dicker 
daherkommen?

Also: all die tollen blockorientierten Protokolle taugen herzlich wenig 
für eine simple UART-Situation in einem ebenso simplen µC. Selbst für 
sowas wie olle Kermit und Konsorten braucht es etwas mehr Aufwand.

Und nochwas: das Endian-Problem ist mittlerweile zwar in den Hintergrund 
getreten, aber das Prinzip-Problem bleibt: bei den auszutauschenden 
Daten muß man sich auf irgend ein Austauschformat einigen, sonst ist 
Neese.

Also das betrifft eben nicht die Blockstruktur und Blockerkennung usw., 
sonder es betrifft die zu übertragenden Daten selbst.

So, nun hier mal ein Selbst-Zitat aus der Dokumentation meiner Firmware 
zum FA_NWT als eines von tausenden möglichen Verfahren:
1
3.2 der physische Datenverkehr vom PC zum PIC
2
3
Der PC darf alle Zeichen von 20h bis 5Fh sowie 0Dh und 0Ah zum PIC senden. Das umfaßt alle Großbuchstaben, Ziffern, Leerzeichen, Zeilenschaltungen und
4
die nötigsten Sonderzeichen.
5
Der PIC sendet alle empfangenen und nicht ignorierten Zeichen zurück an den PC.
6
7
3.3 der physische Datenverkehr vom PIC zum PC
8
9
Die vom PIC an den PC gesendeten Zeichen sind in Wertebereiche aufgeteilt, die sich in ihrer Bedeutung unterscheiden.
10
00h .. 0Fh = Bereich für Steuerzeichen
11
10h .. 1Fh = Bereich für Meßpunkt-Infobytes
12
20h .. 5Fh = Bereich für Klartext aller Art
13
60h .. 6Fh = Bereich für Kurvenprotokoll-Infos
14
70h .. 7Fh = spezifisch je nach Kurvenprotokoll
15
80h .. FFh = binäre Meßwerte. Bedeutung je nach Art
16
             des aktuellen Kurvenprotokolles."
Die mit hohem Datenaufkommen daherkommenden Meßwerte werden in 7 Bit 
Portionen über die Serielle geschickt. Das ist hier der Knackpunkt. Die 
Wertebereiche $10..$1F und $70..$FF sind also der Übertragung der 
eigentlichen Meßwerte reserviert und nutzen damit die Bandbreite zu fast 
90% aus. Aber die restlichen Zeichen können zwischendurch für die 
household-Kommunikation benutzt werden. Ich hatte damals (so etwa 2008) 
sogar einen Dekoder für ne IR-FB in den Wobler mit eingebaut, weil mir 
die PC-tastatur auf dem basteltisch zu sperrig war. Über die Serielle 
geht damit also:
- die eigentlichen Meßdaten
- die Infostruktur für die Meßdaten
- der "household"-Verkehr (Wobbel-Einstellungen)
- die Bedienungs per Fernbedienung
und das alles völlig asynchron durch- und miteinander, ohne daß sich da 
was ins Gehege kommt. Und selbstsynchronisierend ist das Ganze auch, 
obwohl hier ohne Pausen back to back gesendet wird. Es gibt also keine 
Pausen oder Breaks, an denen man einen Anfang erkennen könnte.

Jetzt siehst du, daß deine pauschale Annahme "Das Aufblähen jedes Bytes" 
durchaus NICHT zwangsläufig so sein muß. Es geht weitaus effizienter - 
und das eben asynchron und ohne die diskutierten Blockstrukturen.

W.S.

von Niklas Gürtler (Gast)


Lesenswert?

W.S. schrieb:
> Also: all die tollen blockorientierten Protokolle taugen herzlich wenig
> für eine simple UART-Situation in einem ebenso simplen µC.

Das STK500-Protokoll funktioniert so, diverse IMU's und Displays nutzen 
sowas, die XBee-Module von Digi ebenso usw. Das einzige, was dagegen 
spricht, ist die etwas kompliziertere Implementierung der Kodierung, 
dafür wird das Empfangen einfacher, weil die Blockgröße typischerweise 
fix ist - man empfängt einfach bis der Puffer voll ist. Weil man keine 
Division/Multiplikation zur ASCII-Zahlenkodierung braucht ist so etwas 
gerade für kleine Controller geeigneter. Schließlich passen bei weitem 
nicht alle Messwerte/Daten in 7bit, und wenn man mehr als 1 Messwert-Typ 
hat muss der Empfänger ja auch wissen, was was ist.

von Daniel V. (danvet)


Lesenswert?

W.S. schrieb:

> Die vom PIC an den PC gesendeten Zeichen sind in Wertebereiche
> aufgeteilt, die sich in ihrer Bedeutung unterscheiden.
> 00h .. 0Fh = Bereich für Steuerzeichen
> 10h .. 1Fh = Bereich für Meßpunkt-Infobytes
> 20h .. 5Fh = Bereich für Klartext aller Art
> 60h .. 6Fh = Bereich für Kurvenprotokoll-Infos
> 70h .. 7Fh = spezifisch je nach Kurvenprotokoll
> 80h .. FFh = binäre Meßwerte. Bedeutung je nach Art
>              des aktuellen Kurvenprotokolles."

????
Wie erkennst du Störungen auf der Leitung?

von Ruediger A. (Firma: keine) (rac)


Lesenswert?

W.S. schrieb:
>
> Zweitens wird hier immer wieder und zwar hartnäckig von
> blockorientierter Übertragung (framing..) geschrieben. Das ist in
> Umgebungen von Ethernet und HF zwar usus, aber bedenke mal, daß zwischen
> einer Übertragung in QPSK o.ä. mit entsprechenden Endgeräten und einem
> simplen UART im µC, wie es der TO angesprochen hat, Welten dazwischen
> liegen. Was meinst du eigentlich, weshalb es nen UART in jedem popligen
> µC gibt und sowas wie Ethernet MAC und PHY drei Nummern dicker
> daherkommen?
>

Vielleicht schreiben wir aneinander vorbei und sollten erstmal die 
Begriffsbildung klären. Framen heisst für mich nicht, jeden Block a la 
TCP/IP in geschachtelte Header mit Dutzenden von Verwaltungsbytes zu 
prefixin. Framing kommt eigentlich aus der seriellen Welt (z.B. PPP über 
Modemleitungen) und ist gerade in seriellen Protokollen absolut 
essentiell. Zum Einen kann in einer Peer-o-Peer Verbindung jeder Partner 
asynchron durch einen Reset gehen, muss also (da es in den meisten 
seriellen Protokollen keine Möglichkeit gibt, eine logische Verbindung 
physikalisch zu verwalten) im laufenden Datenstrom auf einen Paketanfang 
synchronisieren können. Dazu gibt es z.B. Framingstartzeichen und 
Transpositionen, um die Framingstartzeichen überall anders im Datenstrom 
zu eliminieren (sh. z.B. RFC 1661).

> Also: all die tollen blockorientierten Protokolle taugen herzlich wenig
> für eine simple UART-Situation in einem ebenso simplen µC. Selbst für
> sowas wie olle Kermit und Konsorten braucht es etwas mehr Aufwand.
>

Absolut falsch. Nimm z.B. einen Multidrop Master-Slave Bus über RS485. 
Hier ist das o.d. framing absolut unerlässlich, um Buskollisionen zu 
verhinden. Wie gesagt braucht es hier keinen Frame im Sinne von TCP/IP, 
aber Blockanfang und -ende müssen eindeutig identifizierbar sein.

> Und nochwas: das Endian-Problem ist mittlerweile zwar in den Hintergrund
> getreten, aber das Prinzip-Problem bleibt: bei den auszutauschenden
> Daten muß man sich auf irgend ein Austauschformat einigen, sonst ist
> Neese.
>

Ja, dafür stehr in jeder vernünftigen Protokollspec "transmission of 
length in network byte ordering." Wenn zwei oder mehr Instanzen 
miteinander kommunizieren wollen, müssen sie dabei Regeln einhalten, 
egal ob es Menschen oder Maschinen sind.

>
> 3.3 der physische Datenverkehr vom PIC zum PC
>
> Die vom PIC an den PC gesendeten Zeichen sind in Wertebereiche
> aufgeteilt, die sich in ihrer Bedeutung unterscheiden.
> 00h .. 0Fh = Bereich für Steuerzeichen
> 10h .. 1Fh = Bereich für Meßpunkt-Infobytes
> 20h .. 5Fh = Bereich für Klartext aller Art
> 60h .. 6Fh = Bereich für Kurvenprotokoll-Infos
> 70h .. 7Fh = spezifisch je nach Kurvenprotokoll
> 80h .. FFh = binäre Meßwerte. Bedeutung je nach Art
>              des aktuellen Kurvenprotokolles."
>

Bin ich mir nicht ganz sicher, wie das zu verstehen ist. Wenn der zu 
übermittelnde Datenstrom a priori nicht begrenzt werden kann - z.B. beim 
Herunterladen eines Images für einen Firwmaredownload - wie würde sich 
das in deinem Protokoll niederschlagen?

: Bearbeitet durch User
von W.S. (Gast)


Lesenswert?

Ruediger A. schrieb:
> Bin ich mir nicht ganz sicher,

Also, das ist ein Protokoll für einen Wobbler am PC. Ist grob gesagt so 
etwas ähnliches wie ein PC-Oszilloskop, bloß ein bissel anders.

Da habe ich damals vornehmlich Wert darauf gelegt, daß die Meßwerte 
(regulär 10 Bit, 1 bis 5 Kanäle) möglichst schnell vom Wobbler zum PC 
gelangen. Eben deshalb werden sie in Stücken zu je 7 Bit übertragen. 
Natürlich muß diese Nutzlast ihrerseits einem festgelegten Format 
genügen, aber das kann mitten im Datenstrom vom PIC her angepaßt werden 
per Angaben in $60..$7F Bereich.

Ebenso wichtig war es mir auch, daß es mittendrin in jeglicher 
Meßwertübertragung eben auch Kommandos und anders Zeug in beiden 
Richtungen geben darf, was sozusagen den Meßwert-Datenstrom 
interruptieren kann, ohne ihn zu stören.

Eine Blockstruktur, die zunächst vorgibt, wieviel Bytes da kommen 
werden, wäre viel zu starr und einschränkend gewesen. Immerhin kann es 
ja bei heutigen Bildschirmen sein, daß man ja ein Wobbelbild von fast 
1800 Punkten und bis zu 5 Kurven sehen will - und das bittesehr nicht im 
Schneckentempo, und wenn man was verstellt, will man auch nicht erst 
ewig warten, bis es greift.

Das Ganze ist zweckgebunden und hier war es nicht der Zweck, 
Firmwareupdates zu machen. Ich hatte ja viel weiter oben bereits 
geschrieben, daß es m.E. eben NIEMALS ein alleinseligmachendes 
Universal-Protokoll geben wird. War meine Antwort auf die Frage des TO.

Für Firmwareupdates hatte ich (in der Firma) ein anderes Verfahren 
benutzt, wo ich an die Ziel-HW angepaßte Blöcke mit Adresse, Daten und 
Adler32 gebildet hatte, diese dann komprimiert, dann ähnlich UU codiert 
und übertragen hatte. Der geräteinterne Updater hat dann blockweise 
gearbeitet und jeden Block und dessen Programmierung quittiert. Aber das 
war was für 32 Bitter und keinen kleinen PIC. Andere Aufgabe, anderes 
Verfahren.

W.S.

von Karl (Gast)


Lesenswert?

Olaf schrieb:
> Halte ich fuer totalen Quatsch weil dann die Uebertragung doppelt so
> lange dauert und der Mikrocontroller viel zu lange aus dem Sleepmode
> geht und viel zu viel Strom braucht.

Was für riesige Datenmengen überträgst Du bitte? Für ein paar 
Sensordaten ist das irrelevant.

> Und gerade Datenuebertragungen sind
> Strommaessig teuer weil sie oft ueber Optokoppler gehen. Absolut
> inaktzeptabel.

Dann ist halt Dein Design kaputt. Schau mal nach ADUM1201, da kannst Du 
mit wenig Strom viele Daten übertragen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Karl schrieb:
> Für ein paar Sensordaten ist das irrelevant.

Nicht jeder hat nur „ein paar Sensordaten“, und nicht jeder hat nur
einen ATtiny13.

Bei uns kommen hier auch oft Megabytes zusammen, vorzugsweise über USB,
aber seriell geht auch.  Da drehen wir dann aber auf 500 kbit/s hoch
(der FTDI auf der Gegenseite macht das zum Glück).

von m.n. (Gast)


Lesenswert?

Bimbo 3. schrieb:
> Anwendungsfall wäre üblicherweise folgender: Ich hab irgendein Gerät mit
> einem (relativ kleinen) µC (Atmega o.Ä.) der per UART (+ FTDI, CP2102)
> an einem PC hängt.

Ich denke, darum geht es dem TO?

Übertragung per ASCII sollte dabei doch kein Problem bereiten. Die 
Datenmenge ist auf Grund des kleinen µCs stark begrenzt. Der große 
Vorteil von ASCII-Kodierung dabei ist noch, daß die Daten per Terminal 
angesehen werden können. Als CSV kann man sie bei Bedarf aufzeichnen und 
direkt in ein Kalkulationsprogramm einlesen. Für den PC ist die 
Belastung gleich 0.
Für einfache Anwendungen ist das doch voll in Ordnung!

von Karl (Gast)


Lesenswert?

Jörg W. schrieb:
> Bei uns kommen hier auch oft Megabytes zusammen, vorzugsweise über USB,
> aber seriell geht auch.  Da drehen wir dann aber auf 500 kbit/s hoch

Broken by design. RS232 war für 500kbit nie spezifiziert. Und wo nimmst 
Du aus einem ATmega Megabyte an Daten in wenigen Sekunden her?

Das stimmt hinten und vorn nicht. RS232 am PC oder am Raspi haben keinen 
Datenbuffer für Megabyte, da kannste froh sein wenn der Fifo ein paar 
Byte hat, bessere Karten haben 16kByte. Wenn das OS gerade mit was 
anderen beschäftigt ist, gehen die Daten ins Nirvana. Es sei denn, Du 
machst Hardware-Handshake, aber dann:

Müsste der ATmega bei einem Stop die Megabyte an Daten 
zwischenspeichern. Wo soll er das tun? Ist ja nicht so, dass der 
Megabyte an RAM hätte.

Kann ja sein, dass man das mit Realtime-OS machen kann. Aber das ist 
sicher nicht der übliche Anwendungsfall für RS232. Dafür gab es schon 
vor 30 Jahren andere Schnittstellen. Und heute würde man das sicher über 
USB machen, aber dann nativ und nicht mit einem RS232-Treiber.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Karl schrieb:

> Broken by design.

Du musst es ja wissen.

> RS232 war für 500kbit nie spezifiziert.

Ja, und?  Solange es funktioniert, ist es besser als sinnloses
Warten.

> Und wo nimmst
> Du aus einem ATmega Megabyte an Daten in wenigen Sekunden her?

Ich habe erstens nicht von einem ATmega gesprochen, zweitens kommen
die Daten wortwörtlich „aus der Luft“ (eine Art SDR).

> Das stimmt hinten und vorn nicht.

Nochmal: du musst es ja wissen.

Theoretisiererei.  Wir machen es einfach, und es funktioniert (über
USB natürlich nochmal viel schneller als über UART).

ps: Ich habe natürlich nicht geschrieben, dass wir solch eine
Datenrate kontinuierlich nutzen müssen.  Die Daten fallen über
einen bestimmten Zeitraum an (einige 10 bis 100 ms) und können so
lange im Controller gepuffert werden.  Dennoch kommen bei Messungen
schnell einige Megabyte zusammen, und neben der Geschwindigkeit der
Schnittstelle selbst ist daher ein effizientes Protokoll wichtig.
Daher sind wir vom ursprünglichen ASCII dann zum schon genannten
msgpack übergegangen.

: Bearbeitet durch Moderator
von Karl (Gast)


Lesenswert?

Jörg W. schrieb:
> Ich habe erstens nicht von einem ATmega gesprochen

Der TO allerdings schon. Wie sinnvoll ist es, einen Sonderfall zu 
präsentieren, der den TO nicht tangiert?

Binäre Übertragung bringt nunmal einige Probleme, die man mit 
ASCII-Übertragung nicht hat. Nullbyte, Steuercodes, Framing. Ganz 
abgesehen vom Komfort, den man hat wenn man die ASCII-Werte direkt auf 
einem Terminal mitlesen kann.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Karl schrieb:

> Wie sinnvoll ist es, einen Sonderfall zu
> präsentieren, der den TO nicht tangiert?

Woher weißt du, was ihn tangiert?

Ein „Atmega o.ä.“ deckt als Begriff eine ziemliche Bandbreite ab.

> Ganz
> abgesehen vom Komfort, den man hat wenn man die ASCII-Werte direkt auf
> einem Terminal mitlesen kann.

Daher haben wir ja auch mit ASCII angefangen.  Ist aber eben irgendwann
lästig, auf dem Controller Ressourcen zu verplempern, um die interne
Darstellung in ASCII zu wandeln, nur um auf der anderen Seite wieder
Ressourcen zu verplempern, aus der ASCII-Darstellung eine interne zu
machen.

Irgendwann ist dann eben der Schalter reingekommen, der zwischen human
und machine readable umschaltet.

von Ruediger A. (Firma: keine) (rac)


Lesenswert?

Karl schrieb:

> Ganz
> abgesehen vom Komfort, den man hat wenn man die ASCII-Werte direkt auf
> einem Terminal mitlesen kann.

Naja... einen Decoder zu schreiben, der einen binären Datenstrom lt. 
Protokollspec lesbar aufbereitet, ist vielleicht eine einmalige 
Mehrarbeit von zwei Stunden, bringt dem Entwickler viel Kenntnis des 
Protokolls und bedeutet im Workflow beim Analysieren gerade mal einen 
Schritt mehr. Unter Docklight kann man mit einem Script sogar in 
Echtzeit den aufbereiteten Datenstrom eines binären Protokolls mitlesen.

Ein Vorteil eines binären Protokolls zeigt sich auch bei der Analyse: 
Wenn man Langzeittraces aus dem Feld ziehen und postmortem analysieren 
muss (um eines der typischen Killerbugs zu finden, die nur bei Vollmond 
auftreten), ist ein Tracefile eines "menschenfreundlichen" Protokolls 
ca. doppelt so gross wie der eines komprimierten. Das kann z.B. bei 
einem rund um die Uhr laufenden Master-Slave Protokoll schon Mal in die 
Gigabytes grosse Datei gehen. Da man die dann (unabhängig vom 
verwendeten Protokoll) eh nicht mehr mit Durchsicht analysiert kriegt, 
muss man sie sowieso automatisch vorverarbeiten, was den 
"Lesbarkeitsvorteil" dann wieder wett macht - aber 8G sind logistisch 
immer leichter zu handeln als 16G.

Das sind jetzt keine theoretischen Konstrukte. Genau dieser Fall 
begegnet mir in der Praxis immer wieder.

Ausserdem bedeutet ein - wie Jörg es sehr schön beschrieben hat - 
unnötig auf der einen Seite aufgepumptes und auf der anderen Seite 
wieder abgepumptes Protokoll zwar in Einzelpaketen klein aussehenden 
overhead, kann in der Masse aber einen Riesenunterschied machen. Wer 
schon Mal versucht hat, in einem RS485 Master-Slave Bus mehr als 8 
Knoten (z.B. Kartenleser mit recht komplexen Interaktionen) so effizient 
zu bedienen, dass das System praktisch benutzbar ist, weiss wovon ich 
schreibe...

von A. S. (Gast)


Lesenswert?

Ruediger A. schrieb:
> ca. doppelt so gross

Auch gerne 3 oder 4mal, wenn Mann Leer- und Trennzeichen mitzähl.

Von ASCII zu binär ist es aber am Ende nur eine Optimierung ohne großes 
Potential (keine Größenordnung). Die kann (und sollte) man angehen, wenn 
es notwendig wird.

Und ASCII löst auch die endian-probleme, die hton nunmal nicht lösen 
kann.

von Olaf (Gast)


Lesenswert?

> Was für riesige Datenmengen überträgst Du bitte? Für ein paar
> Sensordaten ist das irrelevant.

Hihi...ich mache Meetings wo es um einstellige Mikroampere geht. Da ist 
ALLES relevant.

> Dann ist halt Dein Design kaputt. Schau mal nach ADUM1201, da kannst Du
> mit wenig Strom viele Daten übertragen.

Brauchen viel zuviel Ruhestrom. 0.85mA Ruhestrom? Das ist ja fast der 
Gesamtstrom mancher Anwendung.

Was ich aber eigentlich aufzeigen wollte, es gibt halt unterschiedliche 
Probleme die unterschiedliche Loesungen beduerfen. Sieht man ja auch an 
dem Beispiel von W.S. Seine Loesung ist gut fuer genau sein Problem.

Olaf

von Adam P. (adamap)


Lesenswert?

Hi bimbo385,

ich hab das alles so gut wie mitgelesen und nu möchte ich dir auch mein 
Vorschlag unterbreiten.

Bei ASCII sehe ich das problem, dass du Sequenzen "escapen" musst.
Außerdem musst du dabei deine Werte erst von Binär in ein String wandeln 
und auf der anderen Seite wieder zurück, was ich als überflüssig 
empfinde, denn sollte dies so eine größer Sicherheit bringen, würden 
TCP/IP ASCII basiert sein :-D kaum vorstellbar...

Ich übertrage alles binär, so kannst du auch direkt strukturen zum 
versenden laden, wenn du sicher stellst, dass das alignment stimmt.

Frameaufbau:

| CRC16 | Type | CMD | Length (der Daten) | Data |

Ich würde es mir nicht komplizierter machen wie es sein muss...
siehe:

Georg G. schrieb:
> KISS ist klein und hat wenig Overhead

Gruß

: Bearbeitet durch User
von Robert S. (bimbo385)


Lesenswert?

Moin,

da habe ich was losgetreten ;-)

Vielen Dank erstmal für die ganzen Infos.
Natürlich habe ich mir schon für mehrere Anwendungsfälle irgendwelche 
Protokolle über UART ausgedacht (ASCII basiert) und war mit dem Ergebnis 
nicht immer 100%tig zufrieden (nicht das es nicht funktioniert hätte).

Es scheint also keine gut/weit verbreitete Universallösung zu geben, das 
ist schon mal gut zu wissen.

Mein Problem bei direkter binärer Übertragung von Werten via UART ist 
immer, dass es kein Escape- oder Trennzeichen mehr gibt. Schließlich 
kann jeder 8-Bit Wert ja auch in einem zu übertragenden Wert vorkommen. 
Daher muss man immer mit Längeninformationen arbeiten.

KISS, SLIP, der CMDmessenger und die Idee von Adam P. sehen auf den 
ersten Blick schon mal ganz gut aus. Ich werde mir das in Ruhe mal 
anschauen und ausprobieren.

Es geht wie schon diskutiert nicht um riesige Datenmengen. Meistens sind 
es nur ein paar hundert Byte pro Sekunde die übertragen werden müssen. 
Das heftigste sind normalerweise Konfigurationsdaten, die schnell in 
einem Rutsch ausgetauscht werden sollen. Aber auch das beschränkt sich 
auf maximal 1-2 kByte und wird manuell vom Benutzer ausgelöst.

Gruß

von Purzel H. (hacky)


Lesenswert?

Es sind ein paar Moeglichkeiten erlaeutert worden, die Einige mit etwas 
viel Herzblut und mangelhaftem Wissen verteidigt haben wollten.
Du hast zumindest zumindest gesehen, dass an einem Protokoll mehr als 
"nehmen wir eine fertige general purpose library" ist.

von Ruediger A. (Firma: keine) (rac)


Lesenswert?

Achim S. schrieb:
>
> Und ASCII löst auch die endian-probleme, die hton nunmal nicht lösen
> kann.

Welche sind das? Die "Normalisierung auf network byte ordering" wird ja 
gerade durch <h|n>to<n|h><s|l> realisiert. Welche ungelösten Probleme 
bleiben dann noch?

Eine Längendarstellung wie "123" statt 0x0000007b wirft natürlich das 
Konvertierungsproblem gar nicht erst auf, aber um den Preis, dass die 
eine Seite aus 0x0000007b (wie immer sie intern repräsentiert wird) den 
String "123" bauen und die Andere Seite den ganzen Prozess umkehren 
muss.

Ausserdem wird typischerweise eine ASCII Länge nicht den gesamten 
Wertebereich eines Short oder long umfassen, d.h. die faktische 
Maximallänge eines Pakets wird durch den Wertebereich begrenzt, der in 
das fixe Längenfeld passt. In den seltensten Fällen wird ein 
Längenstring in Hex definiert oder es werden 9 bzw. 5 Dezimalzeichen für 
die Länge vorgesehen (die man bräuchte, um den Wertebereich eines long 
bzw. eines shorts zu codieren), und wenn die Länge fix in 3 
Dezimalstellen abgelegt wird, ist bei 999 Zeichen definitiv Schluss.

von Michael U. (amiga)


Lesenswert?

Hallo,

ich habe auf AVR vor Jahren mal das alte X-Modem Protokoll benutzt.
Mit 128Byte Blöckgröße vom Ram gut nutzbar, das Handling mit ACK/NACK 
ist simpel und man hat (für AVR-Verhältnisse) für das Füllen oder 
Auswerten des Buffers ewig Zeit, weil die Timeouts recht hoch sind.
Auf der PC-Seite findet man noch ein paar Terminslprogramme, die XModem 
(nicht XModem 1k) können, man kann das dann zum Debug gut als Datei 
ablegen.

Gruß aus Berlin
Michael

von Purzel H. (hacky)


Lesenswert?

Falls man ASCII haben will, weil die Daten hinreichend langsam 
daherkommen, und man per Terminal zuschauen moechte, wuerde ich 
ASCII-Hex, anstelle von ASCII-Dezimal empfehlen, da etwas kompakter und 
man als Entwickler eh in Hex denken kann.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Ruediger A. schrieb:
>> Und ASCII löst auch die endian-probleme, die hton nunmal nicht lösen
>> kann.
>
> Welche sind das?

Vielleicht hat er es unglücklich geschrieben: mit ASCII kannst du
natürlich auch Gleitkommazahlen übertragen, bei denen es binär neben
der Endianess noch die Details der internen Darstellung zu
berücksichtigen gibt.  Im Gegenzug verliert man typischerweise durch
die Hin- und Rückwandlung über ASCII Genauigkeit, außerdem kostet die
Wandlung Rechenleistung.

Andererseits spielt Endianess und Zahlendarstellung mittlerweile eine
ziemlich untergeordnete Rolle.  Big-Endian-Systeme sind nur noch sehr
spärlich anzutreffen, und auch bei Gleitkommazahlen macht kaum noch
jemand was anderes als IEEE754.

von Jack (Gast)


Lesenswert?

Ruediger A. schrieb:
> Dazu gibt es z.B. Framingstartzeichen und
> Transpositionen, um die Framingstartzeichen überall anders im Datenstrom
> zu eliminieren (sh. z.B. RFC 1661).

Da hast du dir mit PPP aber ein etwas kompliziertes Beispiel 
rausgesucht. Ansonsten volle Zustimmung. Ich versehe auch nicht, warum, 
wie beim letzten Mal, die Leute voll durch die Decke gehen, wenn man 
erprobte Techniken aus der Datenkommunikation vorschlägt.

Erprobt heißt meist auch alt, also zu einer Zeit eingeführt, als ein AVR 
als Hochleistungsrechner durchgegangen wären. Klar kann es Fälle geben 
bei denen die nicht verwendbar sind, aber dieser Reflex ist schon 
merkwürdig.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Jack schrieb:
> Ich versehe auch nicht, warum, wie beim letzten Mal, die Leute voll
> durch die Decke gehen, wenn man erprobte Techniken aus der
> Datenkommunikation vorschlägt.

„die Leute“?  Das war wohl einer, und derjenige ist auch dafür
bekannt, dass er so gut wie nur seine Sichtweise propagiert und
akzeptiert.

von Adam P. (adamap)


Lesenswert?

Bimbo 3. schrieb:
> Aber auch das beschränkt sich
> auf maximal 1-2 kByte und wird manuell vom Benutzer ausgelöst.

ok...Super Bsp.

Nehmen wir an 2048 Byte müssen übertragen werden. Wir haben eine Baud 
von 115200.

Würdest du nun die 2048 Byte "raw" übertragen, brauchst du ca. 177ms.
Angenommen du willst ASCII nutzen und hast lediglich Byte Werte, keine 
uint16_t oder uint32_t - dann sieht die Rechnung wie folgt aus:

2048 Mögliche Werte * max. 3 Stellen (Byte) = 6144 Byte
Dies würde das 3 Fache an Übertragungsdauer kosten + die Konvertierung 
von Binär -> ASCII und wieder zurück...

Wer's will - bitte - aber in meinen Augen ist es sinnlos und bringt kein 
Vorteil. Und wenn man es sich im Terminal ansehen will, dann wird man ja 
wohl ein Debug-Interface haben und kann sich die empfangenen Daten 
aufbereiten und ausgeben.

Und falls nicht...sieht man mit einem Logic-Analyser auf der RX/TX 
Leitung sowhl HEX, DEC und auch ASCII. Und damit sollte jeder der sein 
System kennt zurecht kommen, falls es Übertragungsprobleme geben sollte.

: Bearbeitet durch User
von Johannes S. (Gast)


Lesenswert?

Adam P. schrieb:
> Wer's will - bitte - aber in meinen Augen ist es sinnlos und bringt kein
> Vorteil.

Bei 'manuell ausgelöst' ist die Senderate aber eher gering und ein µC 
kann das schon schnell verarbeiten. Bei ASCII und einer Struktur wie 
JSON kann man auf Senderseite etwas dazupacken ohne auf Empfängerseite 
ein Update zu machen. Binär mit fester Struktur hätte diesen Nachteil, 
und bei einer 1 zu n Architektur müssten evtl. viele Empfänger 
aktualisiert werden. Ich sehe da schon Vorteile ASCII/JSON zu nutzen, 
man darf sich nur nicht an den kleinsten verfügbaren µC klammern.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Johannes S. schrieb:
> Binär mit fester Struktur hätte diesen Nachteil,
Na, auch binäre Strukturen darf man erweiterbar konzipieren. Ein 
Beispiel ist das OpenFlight-Format. So etwas ist zwar etwas weniger 
verbreitet, aber mindestens mal ein Versions-Feld um 
Abwärtskompatibilität zu ermöglichen ist gängige Praxis. Beim CAN-Bus 
ist es z.B. überhaupt kein Problem, neue Nachrichten hinzuzufügen...

von Johannes S. (Gast)


Lesenswert?

Bimbo 3. schrieb:
> Mein Problem bei direkter binärer Übertragung von Werten via UART ist
> immer, dass es kein Escape- oder Trennzeichen mehr gibt.

das von mir vorgeschlagene DUST 3964R ist ein transparentes Protokoll,
https://de.wikipedia.org/wiki/3964R
Wenn im Datenstrom das Steuerzeichen 'DLE' vorkommt wird es vom Treiber 
verdoppelt, der Empfänger muss das entsprechend filtern.
Wenn der µC wenig Speicher hat ist ein grosser Datenblock natürlich 
ungüstig, da macht es Sinn die Werte mit verschiedenen Kennungen in 
kleineren Häppchen zu übertragen.

von Ruediger A. (Firma: keine) (rac)


Lesenswert?

Jack schrieb:
> Ruediger A. schrieb:
>> Dazu gibt es z.B. Framingstartzeichen und
>> Transpositionen, um die Framingstartzeichen überall anders im Datenstrom
>> zu eliminieren (sh. z.B. RFC 1661).
>
> Da hast du dir mit PPP aber ein etwas kompliziertes Beispiel
> rausgesucht.

Richtig, PPP macht es komplett überdreht - da wird jedes nicht lesbare 
Zeichen transponiert, und über eine konfigurierbare Maske lassen sich 
auch noch im Restbereich Zeichen zwangstransponieren. Ich hatte PPP nur 
gewählt, weil es vermutlich noch eine Menge Leute gibt, die damit in 
Berührung gekommen sind.

In UTISCP mache ich es Minimalinvasiv; es werden nur das 
Framestartzeichen und das Escapezeichen selber transponiert (andere 
Protokolle machen es auch so). Wenn man die beiden nicht zu ungeschickt 
wählt, ist damit der Overhead sehr gering.

von Karl (Gast)


Lesenswert?

Adam P. schrieb:
> Und wenn man es sich im Terminal ansehen will, dann wird man ja
> wohl ein Debug-Interface haben und kann sich die empfangenen Daten
> aufbereiten und ausgeben.

Wenn man das für sich zu Hause oder im Labor macht...

Ich mach das halt im Feld, und die Kommunikation fragt nicht nur Daten 
ab, sondern steuert auch Geräte. Zum einen tut sich die Steuersoftware 
der Kunden mitunter schwer mit Nullbytes oder ASCII über 127, zum 
anderen ist es halt unheimlich praktisch, wenn man mal schnell ein 
Terminal aufmachen und die Steuerung händisch überprüfen kann, ohne 
dafür das Debug-Interface zu benötigen, welches zuhause auf dem Rechner 
liegt oder welches man auf dem Kundenrechner nicht installieren will 
oder darf.

Ich hab durchaus schon größere Datenmengen binär übertragen und weiss 
daher um die Probleme, die sich dabei ergeben. Daher nehme ich für 
kleine Datenmengen, Sensordaten ASCII.

Und mal ehrlich:
Umrechnung Binär-ASCII im µC => das Rausschicken der Daten dauert 
üblicherweise länger, erheblich länger als die Konvertierung.
Umrechnen ASCII in Binär am PC => das unter einem OS, welches nebenher 
die Festplatte indexiert und Seti rechnet zu diskutieren ist müßig.
Datenmenge => zählt nur, wenn ASCII immer den vollen Wertebereich auch 
nutzen würde.
Speichergröße => Wer Logfiles von 8GB anlegt, hat ganz andere Probleme. 
Bei 115kBaud sind pro Sekunde 15kByte möglich. Bei ununterbrochenem 
Schreiben sind das 7 Tage für 8GB. Ups, die Logdaten der letzten 7 Tage 
sind weg, weil die Speicherkarte voll war... Ich würd sowas ja in kleine 
Dateien aufteilen.

von Adam P. (adamap)


Lesenswert?

Karl schrieb:
> wenn man mal schnell ein
> Terminal aufmachen und die Steuerung händisch überprüfen kann, ohne
> dafür das Debug-Interface zu benötigen

OK, das mag ja sein, aber dann nimmt man z.B. HTerm und kann den 
Datenstrom auch mitlesen (Hex-Darstellung), wenn man den Frameaufbau 
kennt.

Ich glaub eher, dass ist reine Geschmackssache.

Ja die Umrechnungen sind schnell erledigt, aber meins ist es nicht.
Ich (wir) übertragen Daten zwischen medizinischen Geräten und das 
funktioniert im Binär Format super...für ASCII hätten wir gar keine 
Zeit, bzgl. Datenrate und Menge.

Ich würde ja auch meine struct z.B. nicht erst in ASCII konvertieren um 
dies in eine Datei zu speichern - dafür gibts ja den binären 
Schreib-Modi.

...Aber ich denke eher, jeder hat seine Vorgehensweisen und man wird nie 
einer Meinung sein ;-)

: Bearbeitet durch User
von Karl (Gast)


Lesenswert?

Karl schrieb:
> Bei 115kBaud sind pro Sekunde 15kByte möglich. Bei ununterbrochenem
> Schreiben sind das 7 Tage für 8GB.

Ups, sind natürlich 11.5kByte und etwas über 8 Tage...

von Karl (Gast)


Lesenswert?

Adam P. schrieb:
> Aber ich denke eher, jeder hat seine Vorgehensweisen und man wird nie
> einer Meinung sein

Ich denke eher es ist eher eine Frage für den Einsatzzweck das richtige 
Format zu nehmen.

Wie gesagt hab ich auch mit binär angefangen. Als dann noch Steuerdaten 
übertragen werden sollten, hab ich auf Steuerbytes plus Hex-Übertragung 
der Werte gesetzt. Als dann das Datenformat flexibler werden sollte 
(unbekannte Anzahl an Sensoren abfragen oder Aktoren steuern), bin ich 
um Adressbytes plus Steuerbytes nicht mehr drumrumgekommen, und hab die 
Werte als Ganzzahlen überragen. Dann war es noch einen Punkt davon 
entfernt, die Kommawerte gleich als Festpunktzahlen zu übertragen. Das 
ist eine Entwicklung über 2 Jahrzehnte und einige Dutzend Projekte.

Man passt sich halt auch den Möglichkeiten der Hardware an: Zum Beispiel 
könnte man mit 9-bit RS232 prima mit einem Steuerbit zwischen Daten und 
Steuerzeichen umschalten und hätte die vollen 8 Bit Datenbereich. Aber 
viele USB-RS232-Wandler unterstützten 9-bit nicht, und einiges an 
Software kann damit nichts anfangen, obwohl es die meisten µC problemlos 
könnten.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Karl schrieb:
> Zum Beispiel könnte man mit 9-bit RS232 prima mit einem Steuerbit
> zwischen Daten und Steuerzeichen umschalten und hätte die vollen 8 Bit
> Datenbereich.

Kannst ja ein BREAK senden. ;-)

von W.S. (Gast)


Lesenswert?

Karl schrieb:
> Das stimmt hinten und vorn nicht. RS232 am PC oder am Raspi haben keinen
> Datenbuffer für Megabyte, da kannste froh sein wenn der Fifo ein paar
> Byte hat, bessere Karten haben 16kByte. Wenn das OS gerade mit was
> anderen beschäftigt ist, gehen die Daten ins Nirvana. Es sei denn, Du
> machst Hardware-Handshake,...

Also ich schätze mal, daß du ein Linuxer bist, denn Windows puffert bei 
Bedarf allemal 64K Bytes oder gar noch mehr bei seriellen Interfaces in 
beiden Richtungen. Da geht überhaupt nichts ins Nirvana. Schreib also 
nicht solche Behauptungen hin.

Jörg W. schrieb:
> Da drehen wir dann aber auf 500 kbit/s hoch..

..und das erscheint mir doch recht fraglich -un das mal so zurückhaltend 
wie möglich zu sagen. Nach meiner Erfahrung bringt es fast garnichts 
gerade bei einem FTDI, die Baudrate wesentlich über 140kBaud 
hochzudrehen. Es wird dabei nämlich doch nicht schneller, sondern fängt 
bloß an zu lücken. Da ist es eine wesentlich bessere Sache, einen FT245 
zu benutzen und dafür eben auf der µC-Seite nen bytebreiten Port zu 
spendieren.

W.S.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

W.S. schrieb:

> Also ich schätze mal, daß du ein Linuxer bist, […]

Woran man einfach nur erkennt, dass du von Linux keine Ahnung hast.

Aber das ist nicht das Thema.

> Jörg W. schrieb:
>> Da drehen wir dann aber auf 500 kbit/s hoch..
>
> ..und das erscheint mir doch recht fraglich -un das mal so zurückhaltend
> wie möglich zu sagen. Nach meiner Erfahrung bringt es fast garnichts
> gerade bei einem FTDI, die Baudrate wesentlich über 140kBaud
> hochzudrehen. Es wird dabei nämlich doch nicht schneller, sondern fängt
> bloß an zu lücken.

Wie soll er denn „lücken“?  Wir reden von der Richtung Controller ->
PC.  Der Controller pumpt seine Daten mit 500 kbit/s (auch 1 Mbit/s
haben wir schon genutzt, lässt sich nur in unserer aktuellen Hardware
in der UART nicht konfigurieren, weil der Mastertakt nicht passt) in
Richtung FTDI.  Der FTDI kann da nichts „aussitzen“, der muss den Salat
ordentlich in USB-Päckchen einwickeln und zum PC schicken.

Datenverluste an dieser Stelle hatten wir nie, die resultierenden
Datenraten passen allemal über ein Fullspeed-USB.

("PC" ist übrigens mal Linux, mal Windows, um deine obige
Unterstellung, Linux wäre für sowas nicht zu gebrauchen, zu den
Akten zu legen.)

von W.S. (Gast)


Lesenswert?

Karl schrieb:
> Zum Beispiel
> könnte man mit 9-bit RS232 prima mit einem Steuerbit zwischen Daten und
> Steuerzeichen umschalten..

Jaja. Du guckst nicht weit genug: Demnächst brauchst du nicht ein 
Steuerbit, sondern zwei - was dann? Nee, sowas ist von hause aus zu 
oberschlau ausbaldowert und man fällt damit (wie du ja bereits 
schriebest) schon an der nächsten Ecke auf die Nase.

Abgesehen davon frag ich mich, warum hier so viele Leute sich an den 8 
Bit festklammern. Da beißt sich grundsätzlich der Datenstrom mit den 
erforderlichen Steuer- und Kontroll-Informationen. Natürlich kann man 
mit Blockstrukturen und den darin enthaltenen mehrbytigen Präambeln die 
Wahrscheinlichkeit von Fehlinterpretationen absenken - aber eben NICHT 
grundsätzlich beseitigen.

Wenn sowas wirklich ne Rolle spielt, dann muß man eben die vollen 8 Bit 
aufgeben und sich entweder mit einem Bitstream anfreunden, der z.B. in 7 
Bit Häppchen zerteilt wird oder man muß einige der 256 Codes als 
Spezialcodes reservieren und damit leben. So ähnlich (jaja, ganz grober 
Vergleich) wird das ja auch bei HTML gemacht: <irgendwas>.

W.S.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

W.S. schrieb:
> oder man muß einige der 256 Codes als Spezialcodes reservieren und damit
> leben

Genau das ist das, was die üblichen Protokolle dafür machen.  Sie
reservieren dabei üblicherweise nur sehr wenige Spezialcodes (zuweilen
auch nur einen einzelnen), sodass der größte Teil des Datenstroms 1:1
rübergeht.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Gerade bei Blockstrukturen ist das ja aber gar nicht nötig, weil der 
Header ja hoffentlich die Länge des Blocks enthält, und man somit weiß 
wo der nächste Block beginnt. Somit kann man die Daten im Block 1:1 am 
Stück senden.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Was machst du, wenn beide Teile die Synchronisation verloren haben?

Dann interpretiert Teilnehmer B irgendwas als „Blocklänge“ und wartet
sich zu Tode, weil Teilnehmer A nur ein Hundertstel davon sendet …

von W.S. (Gast)


Lesenswert?

Jörg W. schrieb:
> um deine obige
> Unterstellung, Linux wäre für sowas nicht zu gebrauchen, zu den
> Akten zu legen.)

Ich habe da überhaupt nichts unterstellt. Also!

Allerdings habe ich - als Windows-Benutzer - mich wirklich nicht in 
die Details der Verwaltung von seriellen Schnittstellen von Linux 
gekümmert. Wozu auch?

Wenn jemand also felsenfest behauptet, daß es zu Datenverlusten kommt, 
sofern auf einer Karte nicht Puffer vorgehalten wird ("bessere Karten 
haben 16kByte"), dann kann er kein Window'ser sein, folglich ist er 
vermutlichst ein Linuxer oder ein FBSDler (was fast auf's Gleiche 
hinausläuft) - dort mag es ja so sein wie beschrieben.

Und falls beides nicht zutrifft, ist die Behauptung der Datenverluste 
einfach nur Dummschwätz. Aber ich nehme bei jedem zunächst an, daß er 
ernsthaft und logisch sich äußert - jedenfalls solange, bis ich erkenne, 
daß er sich entgegengesetzt outet.

Das ist eben Logik. Klaro?

W.S.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Jörg W. schrieb:
> Dann interpretiert Teilnehmer B irgendwas als „Blocklänge“ und wartet
> sich zu Tode, weil Teilnehmer A nur ein Hundertstel davon sendet …
Dafür gibts Timeouts. Wenn 10ms lang o.ä. kein Byte mehr ankommt (weil 
das Paket zuende ist, aber der Empfänger noch mehr erwartet), setzt man 
den Zustandsautomaten zurück und wartet auf einen neuen Paketbeginn. Die 
Gegenstelle wiederholt Pakete, die nicht bestätigt worden sind alle 
15ms, so berappelt sich das System automatisch. Das passt man natürlich 
noch an die genaue Situation an, welche Seite wartet und welche 
wiederholt, ob/wie man Pakete bestätigt usw. Eine Prüfsumme ist ja 
sowieso Pflicht, um kaputte/halbe Pakete nicht anzunehmen.

Beitrag #5308302 wurde von einem Moderator gelöscht.
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

W.S. schrieb:
> Wenn jemand also felsenfest behauptet, daß es zu Datenverlusten kommt,
> sofern auf einer Karte nicht Puffer vorgehalten wird ("bessere Karten
> haben 16kByte"), dann kann er kein Window'ser sein, folglich ist er
> vermutlichst ein Linuxer oder ein FBSDler (was fast auf's Gleiche
> hinausläuft) - dort mag es ja so sein wie beschrieben.

Es ist entweder bei keinem wie beschrieben oder bei allen möglich.

Wenn sich irgendwas im System gerade verklemmt (bspw. infolge eines
Hardwareproblems mit der Festplatte), dann gehen Daten verloren, die
nicht in irgendeinen Puffer gepasst haben.  Dagegen kann kein OS was
machen, wenn der Zustrom auf Dauer größer als der Abfluss ist, dann
geht's irgendwann nicht mehr weiter.

Dabei ist es mittelprächtig wurscht, ob die Daten nun in einem
Hardware-FIFO oder in einem Puffer des OS gespeichert werden.  FIFOs
in UARTs beim PC interessieren ja sowieso niemanden mehr, seit PCs
gar keine UARTs mehr haben … davor waren sie nur deshalb wichtig,
damit man nicht für jedes einzelne Zeichen einen Interrupt bedienen
muss im OS, ansonsten frisst der Interrupt-Overhead übermäßig
Ressourcen.

von Kai (Gast)


Lesenswert?

Hi,

Ich benutze ASCII. Der UART ist komfortabel angebunden an den stdio 
stream.
Mit der stdio.h/string.h werden einfach printf/getline/scanf etc. 
unterstützt.

Noch einen kleinen Line-Empfangspuffer auf AVR Seite 
implementiert...voila

Den Komfort in der Konsole zu schreiben "set led 10 on<enter>" will ich 
nicht missen.

Für große Blöcke kann man ein Read oder Write Kommando implementieren, 
um einmalig auf Blocktransfer einer bestimmten Länge zu schalten.
Klar kann der bei Byte-Verlust auch mal hängen...

Ich hab nie Timeouts oder CRC implementiert, kann man machen. Aber war 
auch nie Mission Critical.

BTW: Arbeite etwa 20 Jahre mit unterschiedlichen Controller von AVR Tiny 
/ PIC16 / PIC 32 / AVR Mega  SamD  SamV bis imx7/AM335x und ich kann 
mich nicht erinnern, dass ich jemals bewusst auf einer seriellen 
Verbindung einen Fehler gesehen habe. Und bis SSH über LAN läuft, muss 
uboot und Co darüber laufen...

Aber ich muss zugeben, die Boards laufen alle bei Raumtemperatur 
zwischen 20° und 27° und mit massiven Streaming Daten auf der seriellen 
Schnittstelle habe ich wenig zu tun gehabt. Allerdings mit Logview alle 
paar 100ms ein paar Daten dauerhaft.

PS : Die AVRs liefen mit internem RC Oszillator damals noch mit CALBYTE 
:-) Aber wehe, man ändert die Spannung zu sehr, dann gibt es wirre 
Zeichen...


Gruß Kai

von Karl (Gast)


Lesenswert?

W.S. schrieb:
> Also ich schätze mal, daß du ein Linuxer bist, denn Windows puffert bei
> Bedarf allemal 64K Bytes oder gar noch mehr bei seriellen Interfaces in
> beiden Richtungen.

Windows puffert bis zu 64kByte, wenn man die Buffer entsprechend groß 
einstellt. Üblicherweise eingestellt sind 16kByte. Das ist aber 
Softwarepuffer, die RS232-Karten oder die USB-seriell-Wandler halten nur 
einige Byte.

64kByte sind bei 115kBaud in 6 Sekunden voll. Und ja, ich hatte schon 
den Effekt, dass ein Vergrößern oder Verschieben des Fensters die 
Eventloop so lange beschäftigt hat, dass der Eventtimer nicht ausgeführt 
wurde und die RS232 für mehrere Sekunden nicht abgefragt wurde, was 
bestenfalls zum schnellen Einlaufen der fälligen Daten, 
schlechtestenfalls zum Datenverlust führte. Gelöst habe ich das durch 
eine andere Timerstruktur, aber - kann vorkommen.

W.S. schrieb:
> Jaja. Du guckst nicht weit genug: Demnächst brauchst du nicht ein
> Steuerbit, sondern zwei - was dann?

Ähem, mit einem Bit mehr verdoppele ich die Zeichenzahl. Damit kann ich 
8bit-Binärdaten von 0..255 schicken und hab noch 256 Steuerzeichen zur 
Verfügung.

Theoretisch könnte man das auch mit 8 Bit machen: Zeichen von $00 bis 
$7F als Steuercodes, Zeichen von $80 bis $FF, also mit dem höchsten Bit 
gesetzt sind 7-bit-Binärzahlen, damit könnte man 7 Bit, 14 Bit, 21 Bit 
Binärwerte senden. Das Anpassen auf 8-bit Werte kann einfach durch Shift 
erfolgen und die Datenrate wäre gerade mal 1/8 = 12% langsamer. Wenn man 
davon ausgeht, dass sowieso seltenst alle 16 bit eines Integer genutzt 
werden, verliert man gar nix.

Also nur so eine Idee, nicht das ich das machen würde... ;-)

von Olaf (Gast)


Lesenswert?

> Das Anpassen auf 8-bit Werte kann einfach durch Shift
> erfolgen und die Datenrate wäre gerade mal 1/8 = 12% langsamer.

Ja, koennte man machen. Aber da Daten in der Regel auf zwei Byte ueber 
die Schnittstelle gehen, auf welche der beiden Haelften bezieht sich 
dein so gewonnenes Steuerbit?

> Wenn man davon ausgeht, dass sowieso seltenst alle 16 bit eines Integer
> genutzt werden, verliert man gar nix.

Und wenn doch? Sonderfallbehandlung? Seufz. Noe, mein Gehirn hat eine 
Granularitaet von 8Bit und das soll so bleiben. :-)

Olaf

von A. S. (Gast)


Lesenswert?

Die einfachsten Protokolle haben doch z.b. ein reserviertes Start-Byte 
(z.B. 0xaa) und Ende-Byte (z.B. 0xbb) und dazwischen halt den Datenstrom 
irgendwie aufgebaut (Längen-Infos, Daten, Checksumme, ...)

Da braucht man dann keine Pausen, keine Wartezeiten, keine irgendwas. 
Wenn 0xaa kommt, lege ich los, wenn 0xbb kommt, werte ich aus, wenn 0xaa 
vorher kommt (dann gab es wohl einen Fehler, den ich nicht beheben 
kann), dann fange ich von vorne an.

Damit 0xaa und 0xbb im restlichen Datenstrom nicht vorkommen, gibt's 
noch ein drittes (Bytestuff)-Zeichen (0xcc). Kommt eines der 3 Zeichen 
im Datenstrom vor, so wird 0xcc gesendet und das zeichen danach z.b. um 
0x80 verändert.

Wenn die Sonderzeichen selten sind, ist alles gut, die Telegrammlänge 
wird kaum mehr. Im Worst-Case aber doppelt so lang.

Wählt man dagegen Sonderzeichen, die häufig vorkommen, so kann man das 
Verfahren oben umstellen, so dass das Telegramm auch im Worst Case kaum 
länger wird. für das Beispiel oben:

1 Zeichen länger im Normalfall
Im Worst Case zusätzlich noch 1 Zeichen alle 126 Zeichen

von Fitzebutze (Gast)


Lesenswert?

Weia..

W.S. schrieb:
> Also ich schätze mal, daß du ein Linuxer bist, denn Windows puffert bei
> Bedarf allemal 64K Bytes oder gar noch mehr bei seriellen Interfaces in
> beiden Richtungen. Da geht überhaupt nichts ins Nirvana. Schreib also
> nicht solche Behauptungen hin.

Was soll das mit Linux oder Windows zu tun haben?
Mit Verlaub, sowas ist unreflektierter Fanboy-Dummschwätz a la carte.

Wenn ein OS was anderes macht und die Hardware/der Treiber kein DMA 
macht, kann immer mal was verloren gehen. Darum haben beide 
Desktop-Konfigurationen bei Echtzeit-/Safety-Anforderungen nix verloren 
und man muss sich seine HW genau aussuchen (es ist allerdings dann mit 
Linux/Xenomai und anderen RT-Erweiterungen möglich).

Und zum Stichwort DMA: Spätestens wenn abrissfreier Datentransfer 
garantiert werden muss, fliegt auf dem uC typischerweise der 
Streaming-Ansatz mit Escape-Bytes und 
Software-Start/Stop-Synchronisation eben raus, da die Blocklängen je 
nach Inhalt variabel sind. Sowas im eigentlichen Protokoll zu 
reflektieren (siehe Frage des TO) ist Murks. Das gehört wenn nötig in 
einen Paketisierungs-Layer.

Kai schrieb:
> Ich hab nie Timeouts oder CRC implementiert, kann man machen. Aber war
> auch nie Mission Critical.

Wenn ich schon sowas lese...da trennt sich eben Industrie von Frickelei.
Zu Recht kann man argumentieren, dass UART nur noch als 
Board-To-Board-Kanal mit kurzem Kabel implementiert werden sollte, aber 
niemals ohne Timeout-Handler. Ansonsten: Siehe Modbus and keep it 
simple. Und ich erinnere noch an RTS-CTS-Leitungen, wenn ihr schon mit 
lustigen Ideen wie 9. Kontrollbit kommt.

Wenn viele Fehler erwartet werden und Performance ein Thema ist, muss 
man fast immer seinen Transport-Layer neu designen, sei es mit 
forward-error-correction oder Resend-Möglichkeit, oder was auch immer.
Dabei läuft es aber so gut wie immer auf Frames raus, kein 
Streaming-Gefrickel. Man sehe sich z.B. ieee802.11 an.

Wenn ein Protokoll gut getestet/auf Fehleranfälligkeit verifiziert 
wurde, sind eigentlich auch ASCII-Hacks nicht mehr nötig. Dann macht es 
mehr Sinn, ein "Human Interface" a la "set led 1" zu implementieren, 
aber sicher nicht auf Protokollebene, denn da wären wir wieder beim 
Stream (mit u.U undefinierten States ohne Timeout) versus Paket.

Wie dann der Payload interpretiert wird, sollte eine Frage des höheren 
Layers sein, mit den gängigen Auswahl:

- Registerbasiert
- Kommandoprotokoll
- Mailboxen (a la CAN)

Das simpelste dürfte nach wie vor das erste sein. Da muss man sich dann 
nur noch Registerlänge und Endianness überlegen.
Das Marshalling von Datenstrukturen, wenn sie als ein Paket wie ein 
Remote-Procedure-Call daherkommen, dürfte die nächste Frage sein.

Da kann man durchaus JSON, oder andere XML-Ansätze zur Beschreibung der 
statischen Datenstrukturen gut verwenden, letzere Datenübertragung im 
Klartext aber für den uC bloss nicht, das ist wieder was für 
HTML-4-Anwendungen.

von W.S. (Gast)


Lesenswert?

Karl schrieb:
> Und ja, ich hatte schon
> den Effekt, dass ein Vergrößern oder Verschieben des Fensters die
> Eventloop so lange beschäftigt hat, dass der Eventtimer nicht ausgeführt
> wurde und die RS232 für mehrere Sekunden nicht abgefragt wurde,

Du hast also NICHT mit separaten Threads gearbeitet? Da solltest du 
eventuell noch ein bissel dazulernen. Dann kommt sowas nämlich nicht 
mehr vor. Bei meinem o.g. PC-Programm für den Wobbler hatte ich den 
gesamten Verkehr zwischen PC und PIC in einen separaten Thread 
ausgelagert. Das entkoppelt alle UI- und Bildschirm- Obliegenheiten sehr 
schön von der Datenübertragung.

Aber dein Einwurf ist dennoch gut, denn er zeigt etwas ganz anderes sehr 
deutlich: Bei einer seriellen Schnittstelle muß man immer damit rechnen, 
daß die Verbindung nie wirklich schulbuchmäßig ist und eben DESHALB sein 
Protokoll auf der Seriellen so einrichten, daß es sich ohne Probleme 
wieder selbst synchronisiert. Bei einer sturen Blockübertragung ist das 
erwiesenermaßen ne Schwierigkeit.

W.S.

von W.S. (Gast)


Lesenswert?

Adam P. schrieb:
> denn sollte dies so eine größer Sicherheit bringen, würden
> TCP/IP ASCII basiert sein :-D kaum vorstellbar...
>
> Ich übertrage alles binär, so kannst du auch direkt strukturen zum
> versenden laden, wenn du sicher stellst, dass das alignment stimmt.

Du schmeißt hier alles durcheinander.

Bedenke mal, daß gerade Ethernet und TC/IP als blockorientierte 
Übertragungen völlig anders organisiert sind als eine simple 
UART-Verbindung. Und das sowohl hardwaremäßig als auch bzgl. der 
logischen Layer.

Und wenn du "alles binär" überträgst, dann ist das wie der Tanz auf dem 
Rand des Vulkans. Es kann recht oft gut gehen, aber man kann damit auch 
barbarisch auf die Nase fallen, denn es gibt keine Sicherheiten in 
jeglicher Hinsicht. ich stell mitr grad mal vor, rein binär nen struct 
auszutauschen zwischen einem 8 Bitter und einem 32 Bitter oder mal bloß 
zwischen einem Cortex M0 und einem M4, wo beim einen misaligned Zugriff 
möglich ist was beim anderen in die Hose geht. Kurzum, rein binäre 
Übertragungen bedürfen ihrerseits eines Austausch-Protokolls und so 
müssen beide Parteien an den Daten herumrechnen. Von wegen "alles 
binär"...

W.S.

von W.S. (Gast)


Lesenswert?

Jörg W. schrieb:
> Es ist entweder bei keinem wie beschrieben oder bei allen möglich.

Schon wieder stellst du Behauptungen auf. Woher nimmst du die Chuzpe, 
über "bei allen" hinzuschreiben? Du kennst doch mit Gewissheit nicht 
Alle, sondern nur all diejenigen, die dir grad einfallen.

Von mir wirst du wohl kaum Behauptungen lesen, die sich auf Zeugs 
beziehen, was ich nicht oder zu wenig kenne - allenfalls mehr oder 
weniger fundierte Vermutungen. Das ist wohl der Unterschied, gelle?

W.S.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

W.S. schrieb:
> Und wenn du "alles binär" überträgst, dann ist das wie der Tanz auf dem
> Rand des Vulkans

Wenn man es falsch macht vielleicht.

W.S. schrieb:
> denn es gibt keine Sicherheiten in
> jeglicher Hinsicht.
Es gibt den C-Standard, der diverse Dinge garantiert. Wenn man nur diese 
Dinge annimmt, kann man auch problemlos binär Daten übertragen.

W.S. schrieb:
> ich stell mitr grad mal vor, rein binär nen struct
> auszutauschen zwischen einem 8 Bitter und einem 32 Bitter oder mal bloß
> zwischen einem Cortex M0 und einem M4, wo beim einen misaligned Zugriff
> möglich ist was beim anderen in die Hose geht.
Überhaupt kein Problem bei portablem, korrektem Code. Wie sonst können 
binäre IP-Pakete zwischen allen möglichen Plattformen ausgetauscht 
werden, und offenbar effizient genug für sehr große Datenraten?

W.S. schrieb:
> Kurzum, rein binäre
> Übertragungen bedürfen ihrerseits eines Austausch-Protokolls und so
> müssen beide Parteien an den Daten herumrechnen.
Das Rechnen beschränkt sich auf Bitshifts, die sind meist sehr effizient 
und können von Compilern gut optimiert werden. Besser als 
ASCII-Kodierung allemal.

W.S. schrieb:
> daß es sich ohne Probleme
> wieder selbst synchronisiert. Bei einer sturen Blockübertragung ist das
> erwiesenermaßen ne Schwierigkeit.
Ja, es erfordert etwas zusätzlichen Aufwand. Das ist aber ein alter Hut 
und ist schon lange gelöst, selbst bei Shared Medium Systemen (Ethernet, 
WLAN).

von Karl (Gast)


Lesenswert?

Achim S. schrieb:
> Kommt eines der 3 Zeichen
> im Datenstrom vor, so wird 0xcc gesendet und das zeichen danach z.b. um
> 0x80 verändert.

Soso, und wenn im Datenstrom nativ 0xCC vorkommt?

Und wenn im Datenstrom nativ 0xCC und dann 0x2A?

Klar kann man das mit weiteren "Stuffbytes" erschlagen. Aber der Witz 
ist ja, dass im binären Datenstrom prinzipiell jede Kombi vorkommen 
könnte, die man sich auch als "Stuffbytes" vorstellen kann.

von Karl (Gast)


Lesenswert?

W.S. schrieb:
> Du hast also NICHT mit separaten Threads gearbeitet? Da solltest du
> eventuell noch ein bissel dazulernen.

Mit Multithreading holt man sich wieder andere Probleme rein, und es war 
in dem Fall unnötig. Bekommt man auch ohne hin.

Aber danke dass Du Dir um meinen Lernzustand Gedanken machst. Ist aber 
auch unnötig.

von Ruediger A. (Firma: keine) (rac)


Lesenswert?

Karl schrieb:
> Achim S. schrieb:
>> Kommt eines der 3 Zeichen
>> im Datenstrom vor, so wird 0xcc gesendet und das zeichen danach z.b. um
>> 0x80 verändert.
>
> Soso, und wenn im Datenstrom nativ 0xCC vorkommt?
>
> Und wenn im Datenstrom nativ 0xCC und dann 0x2A?
>

Genau, deswegen wird das Escapezeichen selber auch immer transponiert. 
Damit gibt es grundsätzlich nur eine kleine Menge Sequenzen, die legal 
einem Escape folgen dürfen. Das funktioniert auch extrem robust und 
zuverlässig.

von Karl (Gast)


Lesenswert?

Niklas G. schrieb:
> Das Rechnen beschränkt sich auf Bitshifts, die sind meist sehr effizient
> und können von Compilern gut optimiert werden. Besser als
> ASCII-Kodierung allemal.

Siehste, und das ist der Witz an der Sache: Da hat mal jemand mit 
irgendwelchen Stringoperationen in C versucht Binär in ASCII zu wandeln, 
was der Compiler dann beschissen und mit ganz vielen Divs umgesetzt hat. 
Dann wars so arschlahm, dass fortan des Urteil feststeht: 
ASCII-Konvertierung ist langsam.

Binär in ASCII mit feststehender Stelle (10er) geht über Subtraktion in 
wenigen Takten, ich schätze jetzt mal 60 Takte pro Stelle maximal.

ASCII in Binär geht mit Multiplikation in etwa 10 Takten pro Stelle bei 
16 Bit, bei 8 Bit in 5 Takten. Man multipliziert einfach den bisherigen 
Wert mit 10 und addiert die neue Ziffer dazu.

ASCII in Binär bei ATtinys ohne mul-Befehl geht mit einigen Shifts. x10 
ist nämlich einfach x2 + x8. Sind 3 Shifts und 2 Additionen.

Binär in Hex oder Hex in Binär geht rein über swap, and und add.

Achso, und was die unglaublich vielen 60 Takte von oben angeht: Das 
Rausschieben dieser Stelle bei 8MHz und 115kBaud dauert mehr als Zehnmal 
solange.

von m.n. (Gast)


Lesenswert?

Karl schrieb:
> Binär in ASCII mit feststehender Stelle (10er) geht über Subtraktion in
> wenigen Takten, ich schätze jetzt mal 60 Takte pro Stelle maximal.

Da es um ATmega geht: Beitrag "schnelle Wandlung long -> ASCII"

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Karl schrieb:
> Binär in ASCII mit feststehender Stelle (10er) geht über Subtraktion in
> wenigen Takten, ich schätze jetzt mal 60 Takte pro Stelle maximal.

Ich hab nicht gesagt dass der Unterschied gigantisch ist; es ging mir 
nur um W.S.' Argument, dass Binär mit (viel) Rechnen verbunden ist.

Karl schrieb:
> Achso, und was die unglaublich vielen 60 Takte von oben angeht: Das
> Rausschieben dieser Stelle bei 8MHz und 115kBaud dauert mehr als Zehnmal
> solange.
Klar, aber es kann ja auch sein dass man noch andere Dinge laufen lässt, 
für die man die Rechenzeit braucht.

von Karl (Gast)


Lesenswert?

Niklas G. schrieb:
> Klar, aber es kann ja auch sein dass man noch andere Dinge laufen lässt,
> für die man die Rechenzeit braucht.

Ja aber mal ehrlich: Bei den meisten Anwendungen rödelt der Controller 
eh meistens in der Schleife und könnte nebenbei noch Seti rechnen. 
Gerade wenn es um die Abfrage irgendwelcher Sensorwerte geht.

Ich hab letztens die Umrechnung der Sensorwerte eines BMP180 
Drucksensors anhand dessen Kalibrierdaten gemacht. Da sind so viele Divs 
drin, bei 8MHz braucht der 5msec zur Wandlung eines Wertes.

Da gönn ich mir auch den Luxus, die Werte dann per nRF in ASCII zu 
übertragen.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Karl schrieb:
> Ja aber mal ehrlich: Bei den meisten Anwendungen rödelt der Controller
> eh meistens in der Schleife und könnte nebenbei noch Seti rechnen.

Könnte sein. Energieverbrauch bei Akku-Betrieb wäre noch ein Punkt - 
aber ok, wenn man mit einem PC kommuniziert hat man wahrscheinlich eh 
Netzbetrieb.
Andererseits wird hier im Forum oft auf den letzten Takt optimiert... 
Wenn man es wagt die Nutzung von C++ vorzuschlagen wird direkt dagegen 
diskutiert weil es den einen oder anderen Takt langsamer sein könnte 
(was ohnehin zweifelhaft ist).

: Bearbeitet durch User
von Karl (Gast)


Lesenswert?

Niklas G. schrieb:
> Andererseits wird hier im Forum oft auf den letzten Takt optimiert...
> Wenn man es wagt die Nutzung von C++ vorzuschlagen wird direkt dagegen
> diskutiert weil es den einen oder anderen Takt langsamer sein könnte
> (was ohnehin zweifelhaft ist).

Beispiel: Ein 8-Kanal-PWM-LED-Dimmer mit 300Hz in Software. Ist in 
Assembler vom Timing ausgereizt. Dennoch kann man problemlos die 
Steuersignale mit 9600baud in Ascii konvertieren, nebenher noch ein 
Display mit Zeichen beschicken, natürlich auch mit ASCII-Konvertierung 
und eine Tastenmatrix abfragen. Weil der Dimmer im Interrupt läuft, 
während der Rest nebenher rödelt und es ihm nicht schadet, wenn der 
Interrupt immer mal dazwischengrätscht. Optimieren da, wo es drauf 
ankommt.

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.