Kommunikation Raspberry über COM

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Antworten
Didination
User
Beiträge: 16
Registriert: Montag 1. Februar 2021, 15:24

Hallo,

ich habe ein kleines Problem mit meinem kleinen Test-Programm. Ich will damit testen, ob ob die Daten, die ich senden will, auch so gesendet werden, wie ich es möchte. Nun habe ich mit dem folgen Code aber ein kleines Problem:

Code: Alles auswählen

import serial
from time import time

ser = serial.Serial(
            port = "/dev/ttyUSB0",
            baudrate = 19200,
            parity = serial.PARITY_EVEN,
            stopbits = serial.STOPBITS_ONE,
            bytesize = serial.EIGHTBITS,
            timeout = 5,
            )
try:
    print ("Serial Port ist offen")
    ser.isOpen()
    
except Exception:
    
    print ("Error" + str(e))
    
    exit()

if ser.isOpen():
    try:
        ser.write(b"564\n")
        print ("write data: 564")
        
    except Exception:
        print ("error kommunikation: " + str())
else:
    print ("Serial Port kann nicht geöffnet werden!")

try:
    while 1:
        x = ser.readline().rstrip()
        print (str(x))
        
# Tastatur Unterbrechung abfangen, zum beenden mit [STRG] + [C]
except (KeyboardInterrupt, SystemExit):
    print ("Abbruch")
    ser.close()
Wenn ich das nun starte, bekomme ich nur folgendes ausgegeben:

Code: Alles auswählen

Serial Port ist offen
write data: 564
b' '
b' '
b' '
Irgendwas mache ich falsch, ich komme aber nicht darauf, was genau.


Danke für die Hilfe
Gruß, Didination
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du hast viel zu viel schlechte Fehlerbehandlung. Da es in diesem trivialen Programm eh keinen Weg gibt, mit einem Fehler sinnvoll umzugehen, schmeiß die weg. Alle try excepts. Die maskieren dir nämlich Programmierfehler.

Ansonsten scheint das Programm zu tun, was es soll. Statt die eingelesenen Daten zu prozessieren, entferne das rstrip und benutze repr statt Star auf den Bytes, damit man mal sieht, was da wirklich ankommt.
Sirius3
User
Beiträge: 18054
Registriert: Sonntag 21. Oktober 2012, 17:20

`exit` wird benutzt aber nirgends definiert. Die isOpen-Abfragen sind allesamt überflüssig, weil wenn es ein Problem beim Öffnen gibt, dann fliegt schon die erste Zeile serial.Serial mit einer Exception raus, die Du gar nicht abfängst. Ist auch besser so, denn so bekommst Du die gesamte Fehlermeldung präsentiert.
Die while-Schleife sollte eine while-True-Schleife sein, statt 1. Noch besser wäre es aber, einfach eine for-Schleife zu benutzen. Wir landen also bei:

Code: Alles auswählen

import serial

def main():
    with serial.Serial(
            port = "/dev/ttyUSB0",
            baudrate = 19200,
            parity = serial.PARITY_EVEN,
            stopbits = serial.STOPBITS_ONE,
            bytesize = serial.EIGHTBITS,
            timeout = 5,
            ) as connection:
        connection.write(b"564\n")
        print("write data: 564")
        for line in connection:
            print(line.rstrip())

if __name__ == "__main__":
    main()
Und die Ausgabe kommt daher, dass Du eine timeout hast, die Gegenseite aber nichts sendet.
Didination
User
Beiträge: 16
Registriert: Montag 1. Februar 2021, 15:24

Danke für die schnelle Antwort, ich habe die ganzen Exception jetzt rausgeworfen und auch das str().
Ich hab auch die while-Schleife abgeändert.
Wenn ich das Programm jetzt starte, kommt aber die gleiche Meldung. Wenn ich das ohne den timeout machen, kommt die gleiche Meldung wie schon genannt.
Ich hätte gerne nur den Beispielzahlen "564" ausgegegeben haben. ich habe auch im Internet und auch hier im Forum schon gesucht. Bisher aber nichts gefunden, wie ich das hinbekomme.
Ich will mit dem kleinen Programm lediglich testen, ob auch das ankommt, was ich schicken will.
Gruß, Didination
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Was ergibt die Ausgabe von repr der empfangenen Daten? Oder kommen keine Daten wegen des timeouts?
Didination
User
Beiträge: 16
Registriert: Montag 1. Februar 2021, 15:24

Code: Alles auswählen

Serial Port ist offen
write data: 564
b' '
b' '
b' '
Das kommt wenn ich das so abgeändert habe. Wenn ich das timout drin lasse, wenn ich es rausnehme, dann wartet der die ganze zeit

Der zugehörige code ist

Code: Alles auswählen

import serial
from time import time

ser = serial.Serial(
            port = "/dev/ttyUSB0",
            baudrate = 19200,
            parity = serial.PARITY_EVEN,
            stopbits = serial.STOPBITS_ONE,
            bytesize = serial.EIGHTBITS,
            timeout = 5,
            )
print ("Serial Port ist offen")
ser.isOpen()
    

if ser.isOpen():
    ser.write(b"Test")
    print ("write data: Test")

else:
    print ("Serial Port kann nicht geöffnet werden!")

while True:
    x = ser.readline()
    print (repr(x))
Gruß, Didination
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Dann kommt eben nix von der Gegenstelle. Warum kann hier keiner sagen. Wenn ich raten müsste: du sendest was, aber das hat kein CR/NL am Ende, und darum will die gegenstelle nicht. Schreib

ser.write(b”test\r\n”)
Sirius3
User
Beiträge: 18054
Registriert: Sonntag 21. Oktober 2012, 17:20

@Didination: wie schwer ist es, das isOpen wegzulassen? Wie schon geschrieben, ist das völlig unnötig.
`x` ist immer noch eine schlechter Name für eine Zeile.
Das einfachste wäre es, meinen aufgeräumten Code zu übernehmen.
Und wie schon zu Anfang geschrieben, liegt das an der Gegenstelle. Was ist das für ein Gerät und wie sollte es auf ein 564 reagieren?
Didination
User
Beiträge: 16
Registriert: Montag 1. Februar 2021, 15:24

Es soll nur ein Test sein, ob das, was ich da schicke, auch funktioniert. 564 ist jetzt einfach etwas was ich eingetippt habe. Hätte da auch Test reinschreiben können.
Das eigentlich kommt erst später, ich will erst schauen, ob es so funktioniert.
Gruß, Didination
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Es kann aber nur funktionieren, wenn es dem Protokoll entspricht. Ohne Verständnis der Gegenseite kannst du keine Antwort erwarten. Wenn du im ländlichen China einem Bauern “Kartoffelgnocci” entgegenrufst, wird der auch nicht mit italienischen Köstlichkeiten reagieren. Sondern gar nicht (oder nur lächeln). Man muss schon eine gemeinsame Sprache sprechen.

Ohne deine Gegenseite zu kennen, kann man nur sagen: der code verhält sich erwartbar. Da ist nichts falsch in dem Sinne dran. Höchstens überflüssiges oder ungeschicktes wie das isOpen. Ändert aber das Ergebnis nicht.
Didination
User
Beiträge: 16
Registriert: Montag 1. Februar 2021, 15:24

Ich will ein Programm schreiben, mit dem ich die Daten eines Dataloggers auslese. Die Daten werden nur nicht automatisch gesendet, dies geschieht nur auf Anweisung. Jetzt wollte ich es nur erstmal hinbekommen, Daten über die serielle Schnittstelle des Raspberry zu senden.
Der Datalogger stellt diese dem Profibus-Protokoll DIN19425 nach zur Verfügung. Da dies aber gleich zu dicht an der Lösung wäre, wollte ich nicht direkt danach fragen.
Gruß, Didination
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Nun, du kennst jetzt ja die Antwort. Der Datalogger liefert augenscheinlich (kenne die DIN nicht) nur Daten, wenn man richtig mit ihm spricht.
Didination
User
Beiträge: 16
Registriert: Montag 1. Februar 2021, 15:24

Ich habe mittlerweile rausbekommen, dass der Datenlogger die daten nach dem empfangen einer Anweisung aus einer dll-datei sendet. Das heißt, ich muss aus meinem Programm die dll starten und dann die COM auslesen. Das bekomme ich hin.
Das Problem ist jetzt leider nur, dass ich vor Ort aufgrund von Schulschließung nicht arbeiten kann. Deswegen wollte ich jetzt die Werte mit einem Programm simulieren.
Gruß, Didination
Antworten