Forum: Mikrocontroller und Digitale Elektronik COM-Port, FT232 Kommunikation mit Integer?


von Peter (Gast)


Lesenswert?

Hallo Leute,

ich wollte ein paar 16bit Sensorwerte auf dem PC darstellen. Der Sensor 
ist an einem Atmega324p (16MHz) angeschlossen.
Für die Kommunikation nutze ich einen Ft232r und einen virtuellen 
COM-Port. Es klappt alles wunderbar, allerdings ist die Kommunikation 
recht langsam. Ich betreibe es momentan bei 38400 Baud. Da wäre sicher 
noch mehr drin, allerdings soll erst mein eigenes 
Kommunikationsprotokoll optimiert werden.

Zur Kommunikation:
Ich muss jeden Wert einzeln erfragen, was auch so bleiben soll. Dazu 
schicke ich vom PC Programm einen String "b1" (für Sensor b und Channel 
1).Der Atmega bekommt einen Interrupt, wertet den String aus und liefert 
den geforderten Sensorwert zurück. Dafür wandelt der Atmega den 16bit 
Integer in einen String und schickt diesen. Der String wird vom PC 
empfangen und wieder in einen Integer umgerechnet.Klappt wunderbar, 
allerdings wird jede Zahl einzeln als String geschickt, das ist nicht 
besonders effizient.

Gibt es da eine bessere Variante oder kann ich auch irgendwie direkt 
Integer über den COM-Port schicken?

Vielen Dank

von Peter II (Gast)


Lesenswert?

Peter schrieb:
> Klappt wunderbar,
> allerdings wird jede Zahl einzeln als String geschickt, das ist nicht
> besonders effizient.

das würde aber kaum etwas ändern. Deine Übertragung ist so langsam, weil 
du jeden Wert einzeln abfragst. Damit bringt es fast nichts, ob man nun 
2 oder 5byte für eine Zahl überträgt.

Aber du kannst es gerne versuchen, einfach den 16bit wert in 2bytes 
zerlegen und diese direkt übertragen. Nur hast du damit ein Problem, das 
dann auch Sonderzeichen entstehen können, ob du damit klar kommt hängt 
daovn ab wie du den Protokoll umgesetzt hast.

von Peter D. (peda)


Lesenswert?

Peter schrieb:
> Da wäre sicher
> noch mehr drin

Mit einem 14,7456MHz Quarz.

Peter schrieb:
> kann ich auch irgendwie direkt
> Integer über den COM-Port schicken?

Dann mußt Du Dir erstmal ein Protokoll ausdenken, was die Paketerkennung 
gewährleistet.
Beim String hast Du das durch das "\n" am Ende gewährleistet.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Du kannst beliebige Daten verschicken, dazu musst Du sie nur in einzelne 
Bytes zerstückeln.

Allerdings solltest Du ein Protokoll verwenden, bei dem Du (resp. Dein 
Programm) erkennen kann, wo ein Datensatz beginnt und wo er endet.

Daher ist es nicht ausreichend, Deinen "int" als zwei bzw. vier einzelne 
Bytes zu senden -- wenn Dein sendendes und Dein empfangendes Programm 
"aus dem Takt" geraten, was z.B. beim Stecken/Trennen der Verbindung 
leicht passieren kann, dann kommt nicht das an, was Du erwartest, 
sondern Quark.

Daher ist die Übertragung als Text, auch wenn sie ineffizient erscheinen 
mag, gar nicht so schlecht.

Das simpelste Protokoll ist bei der Textübertragung die Zeile, d.h. 
ein Datensatz wird mit \n abgeschlossen.


Wenn Du tausende von Werten übertragen willst, ist eine 
Effizienzbetrachtung angebracht, aber wenn Du nur gelegentlich mal einen 
Sollwert vorgeben willst, ist das eher irrelevant.

von Peter (Gast)


Lesenswert?

Rufus Τ. Firefly schrieb:
> Wenn Du tausende von Werten übertragen willst, ist eine
> Effizienzbetrachtung angebracht, aber wenn Du nur gelegentlich mal einen
> Sollwert vorgeben willst, ist das eher irrelevant.

Mhm, ich würde meine Daten ja gerne als Graph anzeigen. Nun komme ich 
vielleicht auf eine max. Abtastrate von 1kHz. Falls ich dann noch 2 
Sensoren abfrage sinkt die Rate leider deutlich.

Ich dachte das Problem hätte bestimmt schon jemand gelöst und ich könnte 
einen "offenen" Code verweden. Aber dann werde ich wohl erst einmal die 
Baudrate erhöhen

von Walter Tarpan (Gast)


Lesenswert?

Peter schrieb:
> Ich dachte das Problem hätte bestimmt schon jemand gelöst

Im Normalfall löst man dieses Problem, indem man die Telegramme 
vergrößert - also nicht jeden Wert einzeln abfragt, sondern 
Wertegruppen, z.B. eine Sensorgruppe oder einen gepufferten Werteverlauf 
eines einzelnen Sensors.

Und wenn das dann immer noch zu langsam ist, gibt es noch mehr 
Standardmethoden, z.B. Komprimierungsverfahren.

Aber um das zu beschreiben, müßte man mehr über Deine Anforderungen an 
Latenz und Bandbreite wissen.

"Als Graph darstellen" klingt zum Beispiel nach sehr geringen 
Anforderungen in der Latenz.

von Peter II (Gast)


Lesenswert?

Peter schrieb:
> Mhm, ich würde meine Daten ja gerne als Graph anzeigen. Nun komme ich
> vielleicht auf eine max. Abtastrate von 1kHz. Falls ich dann noch 2
> Sensoren abfrage sinkt die Rate leider deutlich.

ja, aber das liegt ja nur ein deinem Protokoll.

Ich würde es so machen:

PC sagt welchen Sensor wie oft abgefragt werden soll.
µC sendet selbstständig alle werte ohne das der PC dafür etwas machen 
muss. Vor jeden wert kommt einfach die Kennung vom welchen Sensor.

Damit kannst du die Leitung fast 100% auslasten und du hast kein 
Zeitproblem mehr.

von Peter D. (peda)


Lesenswert?

Peter schrieb:
> Ich betreibe es momentan bei 38400 Baud.

Peter schrieb:
> Nun komme ich
> vielleicht auf eine max. Abtastrate von 1kHz.

Das kann man doch einfach ausrechnen.
Nehmen wir mal an, der String hat 5 Byte (4 Hex-Digits + \n):
38400 / 10 / 5 = 768 Hz

von Peter (Gast)


Lesenswert?

Walter Tarpan schrieb:
> "Als Graph darstellen" klingt zum Beispiel nach sehr geringen
> Anforderungen in der Latenz.

Ja, das ist nur ein Hobbyprojekt. Ich will ein bisschen mit 
verschiedenen Sensoren spielen und vielleicht eine kleine Regelung 
aufbauen.

Peter II schrieb:
> Ich würde es so machen:
>
> PC sagt welchen Sensor wie oft abgefragt werden soll.
> µC sendet selbstständig alle werte ohne das der PC dafür etwas machen
> muss. Vor jeden wert kommt einfach die Kennung vom welchen Sensor.

Das klingt schon sehr gut... Momentan möchte ich die Einzelwertabfrage 
behalten, weil ich auch eine kleine Regelung am PC (nicht auf dem 
Atmega) realisieren will. Je nach Abtastwert soll dann zwischendurch 
noch ein Wert an ein Stellglied geschickt werden.
Wahrscheinlich bieten sich dann zwei Modi an. Zusätzlich zur 
Einzelwertabfrage realisiere ich auch deine Paketabfrage.

Peter Dannegger schrieb:
> Nehmen wir mal an, der String hat 5 Byte (4 Hex-Digits + \n):
> 38400 / 10 / 5 = 768 Hz

Das passt schon ganz gut, dann reicht mir die Erhöhung der Abtastrate 
eigentlich.

von Peter II (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Das kann man doch einfach ausrechnen.
> Nehmen wir mal an, der String hat 5 Byte (4 Hex-Digits + \n):
> 38400 / 10 / 5 = 768 Hz

nein kann man nicht. Es kommt ja noch die zeit für die Abfrage dazu. 
Dann kommt auch noch die Verbartungszeit auf beiden Seiten dazu weil es 
scheinbar ein synchrones Protokoll ist.

PC -> µC   "b1\n"   3byte
µC verarbeitet      ? ms
µC -> PC    1234\n  5byte
USB Latenz          ? ms
PC verarbeitet      ? ms

dann geht es wieder von vorne los. Damit wird mal nie sinnvoll schnell 
werden.

von Joachim B. (jar)


Lesenswert?

Peter schrieb:
> Der Sensor
> ist an einem Atmega324p (16MHz) angeschlossen.

da kannst du doch bis 1M baud gehen
http://forum.arduino.cc/index.php?topic=240000.0
der FTDI oder CH340 macht das mit!

leider erlaubt Hyperterminal nur 921600 Bd
und Hterm nur 256000 Bd (Achtung 256kBd != 250kBd)

250kB und 1M geht prima mit 16MHz alle anderen brauchen eben 
Baudratenquarze

für 921600 Bd wäre ein Baudratenquarz nötig
https://www.mikrocontroller.net/articles/Baudratenquarz

http://www.gjlay.de/helferlein/avr-uart-rechner.html
http://wormfood.net/avrbaudcalc.php
http://elektronik-kompendium.de/public/arnerossius/programme/windows/avrbaud.htm
http://www.avrcalc.elektronik-projekt.de/xmega/baud_rate_calculator

von Peter II (Gast)


Lesenswert?

Joachim B. schrieb:
> leider erlaubt Hyperterminal nur 921600 Bd
> und Hterm nur 256000 Bd (Achtung 256kBd != 250kBd)

glaubst du, das er die Daten Hyperterminal abruft?

von Ralf (Gast)


Lesenswert?

Hab mir den Beitrag nicht komplett durchgelesen, aber noch ein kleiner 
Hinweis:
Nur die Baudrate hochschrauben bringt allein nix, richtig Speed bekommt 
das wegen dem USB-Serial-Converter erst wenn das größere Pakete sind. 
Das liegt daran dass USB-Pakete immer gleich lang sind - und X Bytes in 
ein Byte beinhaltenden Paketen zu senden dauert länger als X Bytes am 
Stück zu verschicken.

Ralf

von CaptainAlbern (Gast)


Lesenswert?

Vielleicht nicht exakt die Antwort, aber ein paar Anregungen...

Ich habe mal eine Messverbindung zwischen Arduino (ATMega256) und PC 
aufgebaut. Dabei sollten je bis zu ca. 120Bytes ca. 50Mal pro Sekunde 
übertragen werden (48kBaud netto). Der Controller sendet:

- 2 Byte Startkennung (bei mir $0D0A = Zeilenumbruch)
- feste Anzahl Datenbytes
- 2 Byte Prüfsumme

Der PC synchroniert bei der ersten Messung:
- lese bis $0D0A gefunden wird
- lese feste Anzahl Datenbytes
- lese Prüfsumme und vergleiche mit Selbstberechneter
- wenn die Prüfsumme stimmt: Synch hergestellt
- wenn nicht: war $0D0A wohl zufällig in den Nutzdaten -> nochmal

Bei "lebenden" Messdaten, die sich ständig etwas ändern, ist es damit 
recht unwahrscheinlich, dass die Startsequenz permanent falsch erkannt 
wird.

Zu erwähnen ist, dass der PC über USB verbunden die RS232-Schnittstelle 
auf PC-Seite per Treiber emuliert (soweit ich verstanden habe) und das 
die CPU-Last erstaunlich erhöht. Ich bin bei 65kBaud gebleiben, bei 115 
gab es Probleme. Da kam der PC nicht mehr hinterher, die Daten wurden 
gepuffert und die Messung war dann nicht mehr Echtzeit sondern ein paar 
Sekunden verzögert.

-------

Zum Rückkanal (Befehle PC and µC): Wenn keine Daten, sondern nur reine 
eindeutige 8Bit "Befehle", z.B. $01="Sensor1Aus" gesendet werden, 
braucht man dafür ggf. kein extra Protokoll.

-------

Auch wenn die Daten nur auf Anforderung und nicht kontinuierlich 
gesendet werden, sollte man irgendwie markieren, um welches Datum es 
sich jeweils handelt. Ansonsten ist die zeitlich Zuordnung schwer, falls 
sich etwas verzögert oder außer Takt gerät.

von Peter II (Gast)


Lesenswert?

CaptainAlbern schrieb:
> Ich bin bei 65kBaud gebleiben, bei 115
> gab es Probleme. Da kam der PC nicht mehr hinterher, die Daten wurden
> gepuffert und die Messung war dann nicht mehr Echtzeit sondern ein paar
> Sekunden verzögert.

dann war es ein Programmfehler. PC habe auch mit weit über 1Mbaud keine 
Problem wenn man es richtig macht.

von Peter D. (peda)


Lesenswert?

Peter II schrieb:
> nein kann man nicht. Es kommt ja noch die zeit für die Abfrage dazu.

Die UART ist Full-Duplex, man kann also die nächsten Daten schon 
anfordern, bevor die vorherigen Daten eingetroffen sind.

Sinvoller Weise spendiert man der UART auf dem MC eine FIFO und liest 
ständig den ADC (ADC-Interrupt), so daß man die Daten sofort losschicken 
kann.
Als Flaschenhals bleibt dann wirklich nur die reine Senderate übrig.

Ich mach das oft so, daß der Master die FIFO-Größe abfragen kann. D.h. 
er weiß also, wieviel Anfragen er auf einen Rutsch losschicken kann.

von Peter II (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Peter II schrieb:
>> nein kann man nicht. Es kommt ja noch die zeit für die Abfrage dazu.
>
> Die UART ist Full-Duplex, man kann also die nächsten Daten schon
> anfordern, bevor die vorherigen Daten eingetroffen sind.

deswegen habe ich geschrieben, das er vermutlich ein Synchrones 
Protokoll verwendet. Sonst könnte er ja gar nicht mehr erkennen, welchen 
zahl zu welcher Anfrage gehört.

Und da hilft es nicht wenn Full-Duplex ist, wenn er es nicht nutzt.

von Joachim B. (jar)


Lesenswert?

Peter II schrieb:
> glaubst du, das er die Daten Hyperterminal abruft?

ich bin vor 47 Jahren ausgetreten, glauben ist nicht so mein Ding.

Weisst du mit was er die Daten abruft und welche Baudraten er einstellen 
kann?

von W.S. (Gast)


Lesenswert?

Peter schrieb:
> Für die Kommunikation nutze ich einen Ft232r und einen virtuellen
> COM-Port. Es klappt alles wunderbar, allerdings ist die Kommunikation
> recht langsam.

Wenn es dir auf Geschwindigkeit ankommt, dann machst du das Ganze in 
zweifacher Hinsicht grundfalsch.

1. Nimm anstelle des seriellen Chips von FTDI einen mit 8 Bit 
Parallelschnittstelle, denn da bist du frei von allen 
Baudraten-Beschränkungen. Kannst also mit größter Speed, was dein Atmel 
so hergibt, senden.

2. Versuche bloß nicht irgend ein Ping-pong-Protokoll. Also PC sendet 
"haben wollen", µC ermittelt und sendet "da isses" zurück. Sowas ist 
IMMER grottenlangsam.

Laß den µC stattdessen lustig vor sich hinsenden, also Daten sammeln, in 
eine ausgemachte Protokollform bringen und dann raus damit. Das Programm 
auf dem PC muß aus dem sprudelnden Stream dann bloß noch sich das 
heraussuchen, was es haben will. So geht es am schnellsten.

W.S.

von uwe (Gast)


Lesenswert?

Ein USB 2.0 time slot dauert immer 1ms egal ob du 1000 Byte oder 1 Byte 
sendest. Dann kommt noch die Antwort, die auch immer 1ms dauert egal ob 
1 Byte oder 1000. Das ist halt so bei USB.

von c-hater (Gast)


Lesenswert?

uwe schrieb:

> Ein USB 2.0 time slot dauert immer 1ms egal ob du 1000 Byte oder 1 Byte
> sendest. Dann kommt noch die Antwort, die auch immer 1ms dauert egal ob
> 1 Byte oder 1000. Das ist halt so bei USB.

Nö, in deinen Angaben stimmt fast garnix.

Erstens hängt die Sache natürlich nicht direkt von der USB-Version ab, 
sondern vom "Speed-Grade". Von der USB-Version hängt nur ab, welche 
Speed-Grades überhaupt verfügbar sind.

Bei USB2.0 gibt es LowSpeed(1,5MBit/s), FullSpeed(12MBit/s) und 
HighSpeed(480MBit/s).

Bei LowSpeed und FullSpeed dauert ein "time slot" (richtiger: ein Frame) 
tatsächlich genau 1ms, bei HighSpeed hingegen nur 125µs.

Da für ein "Ping-Pong-Protokoll" mindestens zwei Frames erforderlich 
sind, ist also die kürzestmögliche Latenz für Low/FullSpeed 2ms, für 
HighSpeed hingegen nur 250µs. Dazu kommen aber natürlich die Latenzen 
des OS und sofern es sich nicht um ein Echtzeit-OS handelt, können die 
die durch USB vorgegebene Mindestgröße der Latenz nochmal locker um ein 
bis zwei Größenordnungen "nach oben korrigieren", wenn im System gerade 
viel los ist.

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.