pyserial linux/windows

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
\^/ili
User
Beiträge: 9
Registriert: Samstag 8. Juni 2013, 19:57

Hallo,

ich muss mit einem Industricodiersystem kommunizieren.

Dies geschieht über eine RS232 Schnittstelle / USB.
Gegeben ist folgendes Programm. Python 2.7

Code: Alles auswählen

import time
import sys
import os

sys.path.extend(['./site-packages'])

import serial

toHex = lambda x:" ".join([hex(ord(c))[2:].zfill(2).upper() for c in x])
if os.name == 'posix':
   rs232 = serial.Serial('/dev/ttyUSB0',57600,timeout=3)
elif os.name == 'nt':
   rs232 = serial.Serial('COM19',57600,timeout=3)
else:
   raise Exception('ungueltiges os: {0}'.format(os.name))
   
msg = '\x02\x00\x09\x00\x3D\x01\x05\x41\x41\x41\x41\x41\x91\x03'
print toHex(msg)
result = rs232.write(msg)
while rs232.inWaiting() == 0:pass
x = rs232.read(rs232.inWaiting())
print toHex(x)
rs232.close()
Das Gerät antwortet mit:
02 00 02 00 4F 51 03
Dieses Funktioniert Problemlos unter Windows 7.
Sobald ich es auf einem Raspberry oder Ubuntu (13.04) ausführe, blockiert das System.

Unter den Linux Systemen funktioniert die Schnittstelle /dev/ttyUSB0 wenn ich es mit einem anderen Computer verbinde einwandfei.

Verschiedene Versuche mit flush und unterschiedlichen timeout haben nichts ergeben.

Has jemand eine Idee?

Besten Dank im vorraus.
\^/ili
BlackJack

@\^/ili: `extend()` mit einer Liste mit einem Element aufrufen ist eine recht umständliche Art `append()` zu umschreiben. Warum ist das `serial`-Paket nicht ordentlich installiert?

`toHex()` ist auch recht umständlich formuliert und ein Missbrauch von ``lambda``. Damit definiert man *anonyme* Funktionen. Wenn man eine anonyme Funktion an einen Namen bindet, ist sie ja nicht mehr anonym. Man hat aber trotzdem den Nachteil, dass die Funktion ihren Namen nicht kennt, was zum Beispiel bei Fehlermeldungen einen Unterschied macht.

Die `Serial.write()`-Methode gibt nichts zurück.

Das „busy waiting” ist ziemlich ungünstig. Wenn Du warten möchtest bis Daten anliegen, dann lies einfach in einer Schleife bis tatsächlich Daten gelesen wurden.

Nach dem `write()` fehlt ein `flush()` damit sichergestellt ist, dass die Daten auch sofort geschrieben werden. Ansonsten kann ich da erst einmal nichts anderes entdecken.

Ausser dass das Lesen der Antwort so natürlich nicht garantiert, dass sie komplett ist. Dazu muss man wissen wie lang die Daten sind oder wie das Ende gekennzeichnet ist, und dann entsprechend oft lesen bis man mindestens die Antwort hat, auf die man wartet.

Code: Alles auswählen

#!/usr/bin/env python
import os
import sys
sys.path.append('./site-packages')
import serial


def to_hex(string):
    return ' '.join(c.encode('hex') for c in string).upper()


def main():
    os_name2serial_port = {
        'nt': 'COM19',
        'posix': '/dev/ttyUSB0',
    }
    try:
        port = os_name2serial_port[os.name]
    except KeyError:
        raise Exception('ungueltiges bs: {0}'.format(os.name))
    else:
        with serial.Serial(port, 57600, timeout=3) as rs232:
            message = '\x02\x00\x09\x00\x3D\x01\x05\x41\x41\x41\x41\x41\x91\x03'
            print to_hex(message)
            rs232.write(message)
            rs232.flush()
            while True:
                response = rs232.read(1024)
                if response:
                    break
            print to_hex(response)


if __name__ == '__main__':
    main()
\^/ili
User
Beiträge: 9
Registriert: Samstag 8. Juni 2013, 19:57

Hallo BlackJack,

erstmal besten Dank fuer die rasche und kompetente Antwort.

Deine Kodierungstips sind für mich hilfreich.
Man lernt nie aus!

>Warum ist das `serial`-Paket nicht ordentlich installiert?
Der von mir gepostet Code ist nicht der Produktionscode sonder wurde aus der Anwendung zusammankopiert um eine möglichst kleines Beispielprogramm zu habe.
Deshalb ist es so wie er ist.
BTW: Serial.write gibt die Anzahl der gesendeten Bytes zurück.


Leider ist es so, dass das Problem weiterhin besteht.
Dein Beispielprogramm funktioniert unter Windows problemfrei ist aber unter Linux nicht lauffähig.
Getestet mit Raspberry, und einem Laptop mit umbuntu.

Die Daten werden an das Gerät gesendet - dieses Faktum kann ich nachvollziehen - aber die Antwort wird nicht empfangen.
Der Empfänger ist ein Black-Box und ich kann daran ganau nichts ändern oder einstellen.

Ich kann mittels eines RS232 Editor nachvollziehen, dass das Endgerät korrekt funktioniert.
BlackJack

@\^/ili: Ist denn sicher, dass es ein Problem mit Python beziehungsweise diesem Quelltext ist und nicht eines auf einer Schicht darunter?
\^/ili
User
Beiträge: 9
Registriert: Samstag 8. Juni 2013, 19:57

Danke BlackJack,

Ich versuche gerade herauszufinden, ob es mit RTS/CTS oder sonstiger Hardwarehandshaking zu tun hat.

Darauf bin ich gekommen, da es beim Laptop/Ubuntu als auch im Raspberry nicht funktioniert.

Soweit ich die pyserial Doku richtig gelesen/interpretiert habe ist da per dafault ausgeschalten.
(Habe es auch schon mit explititen ausschalten Probiert)

Leider sind meine Linux Kenntnisse nicht alzu groß.
Deshalb wende ich mich gerade seit der letzten halbe Stunde mit meinem Freund google.
Soweite ich es bis jetzt herausgefunden habe, ist der ganze flowcontroll unter Linux abgeschalten.

Ich habe außer minicom (noch) noch keine Rs232 editoren (auf Windows verwende ich docklight und bin ein bisschen verwöhnt :-))

lg
\^/ili
\^/ili
User
Beiträge: 9
Registriert: Samstag 8. Juni 2013, 19:57

Hallo,

nur um dieses Thema korrekt abzuschließen.

Soweit ich es beurteilen kann handelt es sich definitiv nicht um eine Python Problem.

Es scheint so, dass es Probleme beim bidirektionalen Betrieb mittels /dev/ttyUSBx gibt.

Solte jemand Details wissen wollten:
http://www.forum-raspberrypi.de/Thread- ... 9#pid16949

Ich möchte mich für die kompetente Hilfe in diesem Forum bedanken!

lg
\^/ili
\^/ili
User
Beiträge: 9
Registriert: Samstag 8. Juni 2013, 19:57

Das Problem konnte gelöst werden nachdem ich eine

USB->RS232 Konverter mit ftdi chipsatz

http://de.rs-online.com/web/p/entwicklu ... e/6877806/

verwende.
Linux scheint Probleme mit dem PL2303 Chipsatz zu haben.


lg
\^/ili
hypnoticum
User
Beiträge: 132
Registriert: Dienstag 15. März 2011, 15:43

Ich aergere mich hier jetzt auch gerade mit einem raspberry und einem USB2RS232 adapter rum.
k.A welcher Chipsatz in dem adapter drin ist, aber:
    1. wenn ich einen Jumper auf Rx und Tx setze funktioniert mein Python Script so gut wie garnicht (eben hat es zum ersten mal 'at' angezeigt, was ich auch gesendet habe, sonst kommt maximal das 't' zurueck.
    2. Lasse ich die Hardware wie sie ist und sende das gleiche ueber minicom, kriege ich zuverlaessig (?) ein echo.
sieht eher nach problemen des scripts aus aus als nach treiberproblemen.
ein delay hilft auch nicht. die daten werden scheinbar nur zu gewissen zeitpunkten angenommen und alles andere geht verloren. fuer '01234567890123456789' bekomme ich:
    1. <nix>
    2. '1234567890123456789'
    3. '01234567890123456789'
    4. <nix>
    5. '01234567890123456789'
    6. <nix>
      ....
hypnoticum
User
Beiträge: 132
Registriert: Dienstag 15. März 2011, 15:43

nehme ich eine Schleife, passiert folgendes:
mit /dev/ttyUSB0:
0:
2: at
3: at
4: at
5: at
6: at
7: at
8: at
9: at
zweiter start der schleife mit /dev/ttyUSB0:
0: at
2: at
3: at
4: at
5: at
6: at
7: at
8: at
9: at
wenn ich den port auf den Hardware-USART (/dev/ttyAMA0) des Raspberry umstelle:
0: a tb (<- kein Tippfehler leerzeichen ist da)
2: at
3: at
4: at
5: at
6: at
7: at
8: at
9: at
zweiter start der schleife mit /dev/ttyAMA0:
0: at
2: at
3: at
4: at
5: at
6: at
7: at
8: at
9: at
Antworten