Forum: PC-Programmierung Problem beim Senden von Integer über RS232 / Python mit Pyserial


von R. F. (inet_surfer88)


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

von Kaj (Gast)


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]))

von R. F. (inet_surfer88)


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

von Wolfgang (Gast)


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.

von R. F. (inet_surfer88)


Lesenswert?

Hallo,

das mit der Synchronisation habe ich noch gar nicht bedacht. Da werde 
ich noch einige Tests dazu machen. Informationen hierüber liegen mir 
nicht vor.


Gruß Rüdiger

von R. F. (inet_surfer88)


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

von Wolfgang (Gast)


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.

von Kaj (Gast)


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.

von R. F. (inet_surfer88)


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

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.