Problem beim Senden von Integer über RS232 / Python mit Pyserial

OP #5122902
Lesenswert?

Hallo,

ich habe folgendes vor:
Ich will von einem Raspberry Pi über die RS232 Daten an eine 
Steuerzentrale senden. Die Zentrale erwartet ein Byte mit der Adresse 
und ein zweites Byte mit den 8-Bit-Daten.

Konfiguration des Pi:
Python 3.4.2
Pyserial 3.2.1
Raspbian

Hier mein Code:
1
import serial
2

3
adresse=0b10000001
4
daten=0b10101010
5

6
ser=serial.Serial('/dev/ttyUSB0', 19200)
7

8
ser.write(adresse)
9
ser.write(daten)
10
ser.close
11

12
print('fertig')

Mit diesem Code bekomme ich folgende Fehlermeldung:
1
Traceback (most recent call last):
2
  File "serialtest.py", line 8, in <module>
3
    ser.write(adresse)
4
  File "/usr/local/lib/python3.4/dist-packages/pyserial-3.2.1-py3.4.egg/serial/serialposix.py", line 558, in write
5
TypeError: object of type 'int' has no len()

Zum Testen habe ich einen String gesendet.
1
ser.write(b'text')
Hier läuft das Programm ohne Fehler durch. Ob die Daten auch korrekt 
ankommen, kann ich aber nicht sagen. Die Steuerzentrale wertet nur die 
Bytedaten aus. Mit dem Text kann die natürlich nichts anfangen und schon 
gar nicht anzeigen. Für ein Terminalprogramm am PC fehlt mir momentan 
eine RS232 oder ein weiterer USB-RS232-Adapter.

An dem Raspberry ist ein RS232-USB-Wandler angeschlossen. Dieser sollte 
korrekt funktionieren und die Rechte entsprechend vergeben sein. Mit 
einer "fertigen" Software läuft die Kommunikation ohne Probleme.

In der Doku zu Pyserial steht, daß nur Byte-Werte gesendet werden 
können.Wie kann ich den int-Wert in ein Byte umwandeln?

Für Hilfe wäre ich dankbar.

Gruß Rüdiger
Gast #5122909
Lesenswert?

Entweder so:
1
adresse = bytes([0b10000001])
2
daten = bytes([0b10101010])
3

4
...
5

6
ser.write(adresse)
7
ser.write(daten)

oder so:
1
adresse = 0b10000001
2
daten = 0b10101010
3

4
...
5

6
ser.write(bytes([adresse]))
7
ser.write(bytes([daten]))
OP #5122930
Lesenswert?

Hallo,

zunächst einmal tausenfachen Dank!

Ich habe es so versucht:
Kaj schrieb:
> Entweder so:
>
1
> adresse = bytes([0b10000001])
2
> daten = bytes([0b10101010])
3
> 
4
> ...
5
> 
6
> ser.write(adresse)
7
> ser.write(daten)
8
>

Hat sofort funktioniert. Keine Fehlermeldung in Python und meine 
Steuerzentrale hat korrekt reagiert.

Ich habe den ser.write Befehl nochmals verändert.
ser.write(adresse + daten)
Funktioniert ebenfalls und spart eine Zeile.


Gruß Rüdiger
Gast #5123073
Lesenswert?

R. F. schrieb:
> Die Zentrale erwartet ein Byte mit der Adresse
> und ein zweites Byte mit den 8-Bit-Daten.

Hoffentlich weiß deine Zentrale auch, wie sie sich synchronisiert, falls 
wegen Störungen die Byte 1-/Byte 2-Zählung zwischen Sender und Empfänger 
mal außer Tritt gerät.
OP #5123251
Lesenswert?

Hallo,

ich habe zur Synchronisation etwas herausgefunden. Die Zentrale 
synchronisiert offenbar durch das Schließen und Öffnen der seriellen 
Schnittstelle.


Versuch 1:
Schnittstelle öffnen
Adresse1
Daten1
Adresse2
Daten2
Adresse3
Daten3
Schnittstelle schließen

Wie erwartet alles ok.


Versuch 2:
Schnittstelle öffnen
Adresse1
Daten1
Adresse2
Adresse3
Daten3
Schnittstelle schließen

Das Paket Daten2 habe ich weggelassen und damit eine Störung simuliert. 
Wie erwartet kam ab dem 2. Paket "Müll" heraus. Der Wert von Adresse3 
wurde in Daten2 geschrieben.

Versuch3:
Schnittstelle öffnen
Adresse1
Daten1
Schnittstelle schließen
Schnittstelle öffnen
Adresse2
Schnittstelle schließen
Schnittstelle öffnen
Adresse3
Daten3
Schnittstelle schließen

Auch hier habe ich Daten2 weggelassen. Dieses mal wurde an Adresse2 
nichts verändert, da ja auch keine Daten hierfür übertragen wurden. Die 
Daten an Adresse3 wurden wieder korrekt übertragen.

Hier mein derzeitiger Code (mit Daten2):
1
import serial
2

3
ser=serial.Serial('/dev/ttyUSB0', 19200)
4
adresse=bytes([0b10000001])
5
daten=bytes([0b00000001])
6
ser.write(adresse + daten)
7
ser.close
8

9
ser=serial.Serial('/dev/ttyUSB0', 19200)
10
adresse=bytes([0b10000010])
11
daten=bytes([0b00000010])
12
ser.write(adresse + daten)
13
ser.close
14

15
ser=serial.Serial('/dev/ttyUSB0', 19200)
16
adresse=bytes([0b10000011])
17
daten=bytes([0b00000011])
18
ser.write(adresse + daten)
19
ser.close
20

21
print('fertig')

Muss ich jedes mal zum öffnen der Schnittstelle
1
ser=serial.Serial('/dev/ttyUSB0', 19200)
verwenden?

Beim 2. und 3. mal habe ich es einfach mit ser.open() probiert, 
allerdings erhalte ich dann folgenden Fehler:
1
 File "/usr/local/lib/python3.4/dist-packages/pyserial-3.2.1-py3.4.egg/serial/serialposix.py", line 261, in open
2
serial.serialutil.SerialException: Port is already open.

Gruß Rüdiger
Gast #5123277
Lesenswert?

Öffnen und Schließen der Schnittstelle für die Synchronisation halte ich 
nicht für besonders glücklich.
Besser wäre, ein zusätzliches Byte zu übertragen. Bei 3 Byte hättest du 
8 frei verfügbare Bits für Synchronisation und Datensicherung. Das 
oberste Bit könnte zur Synchronisation verwendet werden (0 beim ersten, 
1 beim zweiten und dritten Byte) und dann hätte man noch 5 Bit für eine 
Prüfsumme.
Es gibt natürlich auch noch andere Verfahren.
Gast #5123354
Lesenswert?

Wolfgang schrieb:
> Öffnen und Schließen der Schnittstelle für die Synchronisation halte ich
> nicht für besonders glücklich.
> Besser wäre, ein zusätzliches Byte zu übertragen. Bei 3 Byte hättest du
> 8 frei verfügbare Bits für Synchronisation und Datensicherung. Das
> oberste Bit könnte zur Synchronisation verwendet werden (0 beim ersten,
> 1 beim zweiten und dritten Byte) und dann hätte man noch 5 Bit für eine
> Prüfsumme.
So wie ich das verstehe hat der TO keinen einfluss auf die 
Steuerzentrale. Und wenn die Steuerzentrale das offenbar so handhabt, 
dann ist das so.
OP #5123374
Lesenswert?

Hallo,

Kaj schrieb:
> So wie ich das verstehe hat der TO keinen einfluss auf die
> Steuerzentrale. Und wenn die Steuerzentrale das offenbar so handhabt,
> dann ist das so.

Genau so ist das.

Es handelt sich um eine Zentrale für eine Modellbahnsteuerung. Deswegen 
habe ich in einem Modellbahnforum nach dem Protokoll gefragt und 
mittlerweile einen Tipp bekommen. Es wird über das Timing geregelt. Die 
Zeit zwischen Adressbyte und Datenbyte darf eine bestimmte Zeit nicht 
überschreiten. Die Zeit ist Abhängig von der Übertragungsgeschwindigkeit 
und entspricht einer Zeit von 10Bit. Die Länge zum nächsten Paket ist 
beliebig. Ich kann die Schnittstelle also offen lassen und muss 
lediglich eine kleine Wartezeit zwischen den Paketen einbauen. Offenbar 
hatte das Schließen und Öffnen der Schnittstelle so eine Wartezeit 
verursacht.


Gruß Rüdiger

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren