Hallo
Ich habe das im Anhang befindliche noch sehr rohe Python 3 Skript
"TestTerminal5b.py" geschrieben, um mich ein wenig in die serielle
Kommunikation in Python einzuarbeiten.
Während das Senden unter Debian Squeeze erstmal funktioniert, habe ich
mit dem Empfangen so meine Schwierigkeiten.
Hintergrund ist, das ich eigentlich kontinuierlich auf der Leitung
lauschen möchte, und "Readline" nicht verwenden kann, weil das
Empfangene nicht zwangsweise Zeilenenden enthält.
Also habe ich mir etwas zusammengestellt, das eine Anzahl von Bytes
einliest bzw. einen Timeout bekommt, und ständig neu aufgerufen wird, in
der Hoffnung, so nichts zu verlieren.
Das ganze ist aber wackelig (es ist ein rohes Konstrukt) und irgendwie
vom Konzept her unelegant.
Nur fällt mir nichts besseres ein......
Der nächste Punkt ist der, das ich das Skript an jemanden weitergegeben
habe, der Windows XP benutzt, und dort kommt immer eine Fehlermeldung:
File "C:\Programme\Python\lib\site-packages\serial\serialwin32.py", line
59, in open
raise SerialException("could not open port %s: %s" % (self.portstr,
ctypes.WinError()))
serial.serialutil.SerialException: could not open port COM1: [Errno 5]
Zugriff verweigert.
Zugriffsrechte auf den Port hat er aber.
Das Problem tritt auf, sobald versucht wird, den Port konkret zu öffnen,
z.B. mit "Ausgang = open(GlobVariables.stPort, mode="w")" in folgendem
Codefragment:
ser = serial.Serial(GlobVariables.stPort, int(GlobVariables.stBaud), timeout=1)
6
7
Ausgang = open(GlobVariables.stPort, mode="w")
8
Ausgang.write(EntrySendText.get())
9
Ausgang.flush()
10
Ausgang.close()
Mein Verdacht ist nun, das unter Windows schon die Konfigurierung des
Ports mit "ser = serial.Serial(GlobVariables.stPort,
int(GlobVariables.stBaud), timeout=1)" den Port belegt und für jeden
weiteren Zugriff spertrt, und der konkrete Zugriff darauf mit "Ausgang =
open(GlobVariables.stPort, mode="w")" als erneutes Belegen verstanden
wird, das nun verboten ist.
Meine Idee dagegen ist, wie im im Anhang befindlichen Skript den obigen
Codeblock zu variieren, indem ich den Port mit "ser.close()" ersteinmal
wieder schliesse und freigebe, bevor ich konkret darauf zugreife. Siehe:
ser = serial.Serial(GlobVariables.stPort, int(GlobVariables.stBaud), timeout=1)
6
ser.close()
7
Ausgang = open(GlobVariables.stPort, mode="w")
8
Ausgang.write(EntrySendText.get())
9
Ausgang.flush()
10
Ausgang.close()
Leider habe ich selber keine Möglichkeit, das unter XP zu probieren.
Meine Frage darum:
1) Funktioniert das so unter Windows?
2) Macht das nun unter Linux Probleme? (Bei mir scheint es zu laufen)
3) Hat jemand eine bessere Idee?
Mit freundlichem Gruß: Bernd Wiebus alias dl1eic
http://www.dl0dg.de
Mit ser = serial.Serial(GlobVariables.stPort, int(GlobVariables.stBaud),
timeout=1) wird der Port auch gleich geöffnet.
open() ist also nicht notwendig.
Jedenfalls meiner Meinung nach..
Ich benutze eine ältere pyserial-Version , auch unter WinXP.
http://sourceforge.net/projects/relaycontrol/?source=directory
Gruß
masla
Bernd Wiebus schrieb:> Während das Senden unter Debian Squeeze erstmal funktioniert, habe ich> mit dem Empfangen so meine Schwierigkeiten.
~~~~~~~
> Das ganze ist aber wackelig (es ist ein rohes Konstrukt) und irgendwie> vom Konzept her unelegant.
Wackelig insoweit, das ich es geschafft habe, bisher einmal Daten zu
empfangen.
Ansonsten kommt meist NICHTS.
Allerdings, komischerweise, wenn ich rohe Binärdaten zum Senden
verwende, bekomme ich manchmal eine Fehlermeldung, das sie nicht utf8
decodiert werden können??????
Also scheint doch irgendwas anzukommen.
Ich verwende einen USB zu Seriell Adapter (ttyUSB0) auf beiden Seiten.
Mit CuteCom auf beiden Seiten keine Probleme. CuteCom benutze ich auch
als Gegenstelle für "TestTerminal5b.py".
> Nur fällt mir nichts besseres ein......
Ich bin sehr ratlos.
Mit freundlichem Gruß: Bernd Wiebus alias dl1eic
http://www.dl0dg.de
Schau Dich doch mal beim RepRap - Projekt um.
Die benutzen Python-scripts zum kommunizieren mit dem Arduino.
Meiner Erfahung nach funktionieren diese Dinge auch zufriedenstellend
und zuverlässig.
Die Stichworte wären PRONTERFACE bzw. Repetier-Host
Ich hoffe das hilft.
Gruß Thilo
kannst du den empfangen wenn du in einer endlosschleife nur liest?
Falls ja, dann lager das lesen in einen thread aus, ein Beispiel ist in
den Beispielen zu pyserial zu finden.
Hallo Masla, Thilo und adsf.
Danke für Eure Tipps.
> Mit ser = serial.Serial(GlobVariables.stPort, int(GlobVariables.stBaud),> timeout=1) wird der Port auch gleich geöffnet.> open() ist also nicht notwendig.> Jedenfalls meiner Meinung nach..
Interessant. Werde ich beim nächsten größeren Umbau garantiert
probieren. Aber zumindest eine Angabe, ob ich den Port zum lesen oder
schreiben öffne müsste ich noch hineinbringen, oder habe ich es hier mit
extrem fortschrittlichen Duck-typing zu tun?
> Habe z.B. das hier gefunden:> https://github.com/kliment/Printrun/blob/master/pronsole.py
Auch interessant. Die benutzen wohl irgendwas anderes als pyserial, weil
ich im Header nichts mit "import serial" finde. Ist natürlich Python 2,
kann ja sein, dass das dafür anders lautet. Jedenfalls muss ich da noch
mal in die Tiefe gehen. Offensichtlich ist es für mich jedenfalls noch
nicht. Könnte auch sein, das pyserial erst von irgendeinem der anderen
verwendeten Module verwendet wird.
> kannst du den empfangen wenn du in einer endlosschleife nur liest?> Falls ja, dann lager das lesen in einen thread aus, ein Beispiel ist in> den Beispielen zu pyserial zu finden.
Ha, das ist ja gerade das merkwürdige. Mir ist es genau zweimal
gelungen, das Programm zu starten und dann etwas zu empfangen. Und zwar
auf den kurzen Blick sogar recht gut und zuverlässig. Ich habe darum die
"Hoffnung" das ich selber etwas mit den Parametereinstellungen
zerdengelt habe, und durch "irgendetwas" dann doch mal den passenden
Parameter einstelle. In dem Zusammenhang werde ich also mein Konstrukt
noch einmal heftigst durchsuchen müssen.
Auf der anderen Seite lese ich bei falschen Parametereinstellungen unter
CuteCom meist noch irgendwelchen Müll.....hier kriege ich nur manchmal
eine Fehlermeldung bezüglich misslungenem utf8 decoding, wenn ich eine
Binärdatei sende.....achselzuck.
Leider bin ich z.Z. etwas eingeschränkt und komme erst die nächsten Tage
wieder dazu, mir vorübergehend ein Hardwaresetup hinzustellen, mit dem
ich wieder serielle Schnittstellen (per USB Adapter) betreiben und
untersuchen kann.
Ob das ganze dann auch unter Windows läuft, ist wieder eine andere
Nummer. Erst muss es überhaupt hier unter Linux laufen.....dann schaue
ich weiter. Alles der Reihe nach.
Mit freundlichem Gruß: Bernd Wiebus alias dl1eic
http://www.dl0dg.de
Deinen eigenen Code habe ich mir nicht im Detail angeschaut, da mir
gerade etwas die Zeit dazu fehlt.
Hier sind trotzdem ein paar Hinweise zu deinen letzten Fragen:
Bernd Wiebus schrieb:>> Mit ser = serial.Serial(GlobVariables.stPort, int(GlobVariables.stBaud),>> timeout=1) wird der Port auch gleich geöffnet.>> open() ist also nicht notwendig.>> Jedenfalls meiner Meinung nach..>> Interessant. Werde ich beim nächsten größeren Umbau garantiert> probieren.
Auszug aus der pySerial-Doku in
http://pyserial.sourceforge.net/pyserial_api.html :
The port is immediately opened on object creation, when a port
9
is given. It is not opened when port is None and a successive
10
call to open() will be needed.
Wenn du also für das Argument port einen Namen oder eine Nummer
angibst, wird das Device sofort geöffnet, und ein nachfolgendes open
macht dann logischerweise Schwierigkeiten:
- Windows meckert, weil die Schnittstelle bereits geöffnet ist.
- Unter Linux kannst du die Schnittstelle zwar mehrmals parallel öffnen,
was kann aber zum Datenchaos führen kann, wenn mehrere Threads oder
Prozesse versuchen, davon zu lesen.
> Aber zumindest eine Angabe, ob ich den Port zum lesen oder schreiben> öffne müsste ich noch hineinbringen, oder habe ich es hier mit extrem> fortschrittlichen Duck-typing zu tun?
Serielle Schnittstellen werden üblicherweise immer zum Lesen und zum
Schreiben geöffnet. Das macht auch pySerial so.
> Auch interessant. Die benutzen wohl irgendwas anderes als pyserial,> weil ich im Header nichts mit "import serial" finde.
Der Zugriff auf die serielle Schnittstelle verbirgt sich im Modul
printcore :
https://github.com/kliment/Printrun/blob/master/printcore.py
Dort wird serial importiert.
Wie ich beim Überfliegen deines Codes gesehen habe, öffnest und schließt
du die Schnittstelle mehrmals. Sendet der Gegenüber Daten, während die
Schnittstelle gerade geschlossen ist, gehen diese Daten verloren. Öffne
die Schnittstelle nur ein einziges Mal am Anfang des Programms, und lass
das am besten das Serial -Objekt bei dessen Instanziierung (wie in der
pySerial-Doku beschrieben) selber machen. Danach kannst du nach Belieben
mit den Member-Funktionen write und read Daten senden und empfangen.