Von Serial Input Zeilenweise lesen

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
dokle
Beiträge: 19
Registriert: 19.09.2010 22:40:06

Von Serial Input Zeilenweise lesen

Beitrag von dokle » 16.02.2011 11:50:33

Hallo,

ich versuche jetzt seit Tagen verzweifelt von einer Seriellen Schnittstelle zeilenweise zu lesen und die Daten weiterzuverarbeiten;
Die Daten kommen unaufgefordert und unregelmäßig in folgendem Format an:

9600N8 Asynchronous data transmission (9600,N,8,1)
#UserID 10Stellig <LEER> Infomeldung
1234567890 Hallo, ich bin ein Infotext und ende mit CR LF *Edit: Echte Daten siehe Post 3*

Ich möchte diese Daten jetzt Zeilenweise kontinuierlich von der Schnittstelle lesen und bei eintreffen neuer Daten diese per Bash-Script weiterverarbeiten.

Das ganze mit cat /dev/ttyUSB1 > /tmp/input.tmp zu schreiben geht. Allerdings müsste ich dann mit meinem Script die input.tmp Zeitweise parsen und Zeilenweise lesen, geht das auch eleganter?, vorallem nur wenn auch Daten ankommen?

Folgendes funktioniert nicht:
stty -F /dev/ttyUSB1 9600 -echo # Wird abgebrochen, warum? *Edit: Blödsinn, siehe Post 3*
read < /dev/ttyUSB1 # Wird ebenfalls abgebrochen

Code: Alles auswählen

#!/bin/sh
# while-script:
while read LINE
    do
    echo $LINE
    done
./while-script < /dev/ttyUSB1 # Wäre mir am liebsten, läuft aber nur bis zum ersten Datensatz, danach bricht es auch ab, warum?

Vielleicht hat noch jemand eine Idee...

Grüße
dokle
Zuletzt geändert von dokle am 17.02.2011 14:18:35, insgesamt 1-mal geändert.

cosmac
Beiträge: 4576
Registriert: 28.03.2005 22:24:30

Re: Von Serial Input Zeilenweise lesen

Beitrag von cosmac » 16.02.2011 20:50:25

hi,
dokle hat geschrieben:stty -F /dev/ttyUSB1 9600 -echo # Wird abgebrochen, warum?
was heißt in dem Fall abgebrochen? Der Befehl ändert die Einstellungen (hier Baudrate und echo), gibt keine Meldung aus und macht auch sonst nichts weiter - also erscheint sofort wieder der Shell-Prompt. Außer natürlich, es gibt das ttyUSB1 nicht oder du hat keine Berechtigung dafür.

"Leider" funktioniert hier dein "while-script < /dev/ttyUSB0"; ich finde keine Einstellungen, mit denen es nicht geht (naja, es gibt ja auch tausende). Ein Schönheitsfehler könnte sein, dass sowohl <CR> als auch <LF> jeweils ein echo auslösen, das zweite gibt dann eine Leerzeile. Das könnte man mit "stty -F /dev/ttyUSB0 igncr" abstellen.

Ansonsten sollten nach "stty cooked" die meisten Einstellung passen. Am besten postest du mal die Ausgabe von "stty -F /dev/ttyUSB0", vielleicht sieht hier jemand ein seltsames Flag.

Überhaupt solltest du einen passenden stty-Befehl mit ins Script schreiben, weil die Einstellungen nach dem Booten sicher anders sind, als nach setserial oder z.B. einem minicom-Aufruf.
Beware of programmers who carry screwdrivers.

dokle
Beiträge: 19
Registriert: 19.09.2010 22:40:06

Re: Von Serial Input Zeilenweise lesen

Beitrag von dokle » 17.02.2011 14:04:00

Hallo cosmac,
danke für deine Antwort.

stty -F /dev/ttyUSB1 9600 -echo # Wird abgebrochen... stimmt natürlich so nicht. Ich bin fälschlich davon ausgegangen, das ein "echo" folgt, was natürlich nicht sein kann - somit nimmt er diese Einstellung an, es ändert aber nichts an meinem Grundproblem.

ttyUSB1 gibt es, da an der Maschine 2 Serial -> USB Wandler hängen, über ttyUSB0 laufen Digitemp aufzeichnungen.

Mit vielen stty Parametern, insb. auch igncr hab ich schon rumgespielt, jetzt passt es wenigstens in der file.out.

Ein stty -F /dev/ttyUSB1 -a gibt folgendes zurück:

Code: Alles auswählen

speed 9600 baud; rows 0; columns 0; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = ^M; eol2 = ^M; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W;
lnext = ^V; flush = ^O; min = 1; time = 5;
-parenb -parodd cs8 hupcl -cstopb cread clocal -crtscts
ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany -imaxbel -iutf8
-opost -olcuc -ocrnl -onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
-isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase -tostop -echoprt -echoctl -echoke
Ein cat -v von file.out (cat /dev/ttyUSB1 > file.out), also echte Daten, sehen mit allen Zeichen, so aus:

Code: Alles auswählen

3645296075  ^R^L^A^@^@^@^@^@^@^@^@^M
3645296070  ^R,^A^@^@^B^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^M
3645267439  ^@^H^A^@^@^@^@^@^@^@^@8E<\"^N^M
Sie enden also alle mit einem "^M" und beginnen immer mit 10 Ziffern, daher hab ich "^M" als eol gesetzt.
Die file.out wird auch richtig geschrieben, alles schön in eine Zeile, aber ich hab keine Möglichkeit hinbekommen, direkt aus dem Device und wichtig, Zeilenweise, den Input zu verarbeiten.

Bei einem read LINE < /dev/ttyUSB1 hab ich das Problem, das in LINE Zeichen fehlen. Meißtens die ersten 2 Ziffern. Ferner kommen die Daten nicht in "Echtzeit", werden wohl irgendwie gepuffert und es scheint mir als finde er das Zeilenende nicht, die Ausgaben sind dann unvollständig oder es kommt eine leere LINE Variable.

Die Daten stammen von einem Microcontroller, Asynchronous data transmission (9600,N,8,1), der an einem RS232-USB Wandler hängt. Verkabelt sind übrigens nur

Code: Alles auswählen

Sub - D9 Pins:
5 -> Signalmasse
1,6,8,4 gebrückt  > (DCD,DSR,CTS,DTR)
2 -> Daten 
Die Schaltung funktioniert unter Windows, z.B. mit Putty seit Jahren in diesem Setup, soll jetzt aber auf meinen Debian umziehen.

Vielleicht sieht hier der ein oder andere noch einen Lösungsansatz.

Grüße
dokle

Benutzeravatar
detix
Beiträge: 1743
Registriert: 07.02.2007 18:51:28
Wohnort: MK

Re: Von Serial Input Zeilenweise lesen

Beitrag von detix » 19.02.2011 18:55:22

Hiermit beschäftige ich mich auch sehr lang, meine Plattform ist der Arduino,
eine gemeinsame Lösung für cat und tail scheint es seit ein paar Monaten (squeeze) nicht mehr zu geben.
Um heraus zu finden welcher der stty Parameter für welches Lesen geeignet ist, hab ich einige Versuche durch,
angefangen mit einem kompletten Rücksetzen der Parameter (muss uU 2x ausgeführt werden, Schnittstelle bitte anpassen):

Code: Alles auswählen

stty -F /dev/ttyUSB0 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
dann mal ein paar der Grundeinstellungen wieder eingetragen (speed bitte anpassen):

Code: Alles auswählen

stty -F /dev/ttyUSB0 115200 intr ^C quit ^\\ erase ^? kill ^U eof ^D start ^Q stop ^S susp ^Z rprnt ^R werase ^W lnext ^V flush ^O
und noch die Zeichengröße auf N Bits setzen

Code: Alles auswählen

stty -F /dev/ttyUSB0 cs8
So müsste es für "tail -f /dev/ttyUSB0" eigentlich klappen,
tut es aber nicht (Parameter "min 0" scheint für tail wichtig zu sein)!
Es gibt aber einen undokumentierten Parameter für tail und damit geht dies zumindest hier:

Code: Alles auswählen

tail ---disable-inotify -f /dev/ttyUSB0 #ja, 3x minus
Für cat siehts wieder etwas anders aus, da muss es (neben Obigem) "min 1" sein!

Code: Alles auswählen

stty -F /dev/ttyUSB0 min 1
cat /dev/ttyUSB0
Wenn es hilfreich war und da jemand Parameter für beide Auslesearten zugleich weiß, bitte posten!
Gruß an alle Debianer, und immer daran denken:
Macht ohne Haftung funktioniert nicht!

dokle
Beiträge: 19
Registriert: 19.09.2010 22:40:06

Re: Von Serial Input Zeilenweise lesen

Beitrag von dokle » 21.07.2011 13:30:12

Hallo zusammen,

nachdem ich mir zwischendurch einen RS232 -> USB mit einem Atmega selber gebaut habe, weil ich das Zeug hier eh noch rumliegen hatte und noch einen brauchte, wird dieser nun unter /dev/ttyACM0 eingebunden.

Jetzt stelle ich zu meiner Verwunderung fest, dass

Code: Alles auswählen

#!/bin/sh
while read LINE
    do
    echo $LINE
    done
damit, im Gegensatz zu /dev/ttyUSB1, wunschgemäß funktioniert.
Das muss ich jetzt nicht verstehen, oder?!

Grüße
dokle

Antworten