Seite 1 von 1

Serielle Schnittstelle

Verfasst: Samstag 16. Februar 2019, 16:00
von wattwurm
Moin,
ich bekomme von einen Arduino Temperaturwerte die ich mit Python2 über serielle Schnittstelle abfrage:

Code: Alles auswählen

#!/usr/bin/env python2
# coding: utf-8
import serial

def rauchgastemperatur():
    ### with verwenden!
    with serial.Serial('/dev/ttyUSB0') as tty:
        #tty = serial.Serial('/dev/ttyUSB0')
        #while True:
        #    print tty.readline()
        temperatur = tty.readline()
    #Abbruch einbauen!!!
    #tty.close()
    #print tty 
    return temperatur

def main():
    #wegen Abbruch (strg+c)
    try:
         while True:
            print rauchgastemperatur()
    except KeyboardInterrupt:
        serial.Serial('/dev/ttyUSB0').close()       
        print serial.Serial('/dev/ttyUSB0')
if __name__== '__main__':
    main()
Ausgabe:

Code: Alles auswählen

thomas@raspberry:~/heizung$ ./testSerial.py 


22

22

27

26

22

22

^CSerial<id=0xb6cd3fb0, open=True>(port='/dev/ttyUSB0', baudrate=9600, bytesize=8, parity='N', stopbits=1, timeout=None, xonxoff=False, rtscts=False, dsrdtr=False)
Frage1:
Wieso wird die die Schnittstelle nicht geschlossen? "open=True>(port='/dev/ttyUSB0)"


Frage2:
Wie bekomme ich die Leerzeichen(zeilen) weg? (evtl. kommen die aber auch schon vom Arduino :?: )


Danke + Gruß
Thomas

Re: Serielle Schnittstelle

Verfasst: Samstag 16. Februar 2019, 16:18
von __blackjack__
@wattwurm: Ad 1: Du öffnest die Schnittstelle einmal in der `rauchgastemperatur()`-Funktion. Dort wird sie durch das ``with`` auch wieder geschlossen.

Dann öffnest Du die Schnittstelle im ``except KeyboardInterrupt:``-Zweig und schliesst sie gleich wieder. Das ist total sinnlos. Und dann kommt das ``print`` wo Du die Schnittstelle ebenfalls noch einmal öffnest und, nun ja, dann ist sie halt offen. Lass den Unsinn im ``except`` einfach komplett sein.

Ad 2: Es kommt ein Zeilenende vom Arduino, und eines durch ``print``. Ich würde das vom Arduino entfernen.

Ungetestet:

Code: Alles auswählen

#!/usr/bin/env python2
# coding: utf-8
from __future__ import absolute_import, division, print_function
import serial


def main():
    try:
        with serial.Serial('/dev/ttyUSB0') as lines:
            for line in lines:
                print(line, end='')
    except KeyboardInterrupt:
        pass  # Intentionally ignored.


if __name__ == '__main__':
    main()
Edit: Und steig auf Python 3 um. :-)

Re: Serielle Schnittstelle

Verfasst: Samstag 16. Februar 2019, 16:37
von wattwurm
Danke Blackjack!
Lass den Unsinn im ``except`` einfach komplett sein.
:lol:
ok, ich wollte damit auch nur prüfen ob dei Schnittstelle nun geschlossen ist oder nicht (das ging ja nach hinten los) :roll:

Code: Alles auswählen

from __future__ import absolute_import, division, print_function
<-- Das gucke ich mir gleich an.

Re: Serielle Schnittstelle

Verfasst: Samstag 16. Februar 2019, 17:41
von wattwurm
@Blackjack, dass Script läuft, die Leerzeilen sind weg.
Ich denke auch das es besser wäre die Leerzeilen im Arduino zu killen, da muß ich mal suchen wie das geht.

Code: Alles auswählen

from __future__ import absolute_import, division, print_function
Das mit Python3 werde ich mir mal überlegen

Re: Serielle Schnittstelle

Verfasst: Samstag 16. Februar 2019, 18:23
von __deets__
Ich wuerde die genau NICHT im Arduino killen. Die serielle Schnittstelle braucht ein Protokoll. Das einfachste, was man machen kann, ist immer zeilenweise einlesen. Und darum solltest du daran nicht rumfummeln.

Re: Serielle Schnittstelle

Verfasst: Samstag 16. Februar 2019, 18:31
von __blackjack__
Die Frage ist vielleicht auch ob es nicht sinnvoll wäre die Zeilen mit den Ziffernfolgen tatsächlich in Zahlen umwandeln.

Zum Thema Python 3: Bei Python 2 ist dieses Jahr Ende. Neues damit anzufangen macht eher keinen Sinn.

Re: Serielle Schnittstelle

Verfasst: Sonntag 17. Februar 2019, 12:39
von DeaD_EyE
Mit CR/LF bzw LF lässt sich ein Serielles Protokoll zeilenbasiert behandeln. Sendet man hingegen irgendein anderes Steuerzeichen am Zeilenende, muss man erstmal gucken wie man das mit PySerial macht. Ein binäres Protokoll würde eine Bytefolge für den Start benötigen und eine feste Definition des Protokolls.

Ich würde einfach die Methode str.rstrip() benutzen, um das Zeilenende aus dem String zu entfernen.
Mal angenommen du wechselst jetzt auf Python 3, dann würde dein Code weiterhin funktionieren, aber bei der Ausgabe hättest du die präsentation als Bytes: b'das was du empfangen hast'
PySerial empfängt und sendet bytes. In der Schliefe müsstest du dann die Zeile dekodieren.

Bytes -> decode() -> String
String -> encode() -> Bytes

Code: Alles auswählen

# Python 3
        with serial.Serial('/dev/ttyUSB0') as lines:
            for line in lines:
                line = line.rstrip().decode()
                print(line, end='')

Re: Serielle Schnittstelle

Verfasst: Sonntag 17. Februar 2019, 14:05
von Sirius3
Da es sich um Zahlen handelt, die sicher irgendwie weiterverarbeitet werden sollen, am besten gleich umwandeln:

Code: Alles auswählen

        with serial.Serial('/dev/ttyUSB0') as lines:
            for line in lines:
                temperature = int(line)
                print(temperature)

Re: Serielle Schnittstelle

Verfasst: Dienstag 19. Februar 2019, 20:56
von wattwurm
Hallo,
ich habe nun mal die Strings in Integer umgewandelt.
Nun kommt aber folgende Fehlermeldung:

Traceback (most recent call last):
File "serial_byte_convert.py", line 8, in <module>
print(int(line))
ValueError: invalid literal for int() with base 10: ''

Da wird wohl versucht was umzuwandeln was aber nicht möglich ist (Leerzeile, Leerzeichen oder NULL character).
Kann es sein das die Serielle Übertragung noch nicht vollständig beendet, bzw. gestartet ist?
Wie kann man dem entgegenwirken?

Ich dachte an sowas:

Code: Alles auswählen

  if type(x) == int:
        ...
    else:
        ....
habe aber gelesen das sei nicht so elegant?

Ohne Umwandlung laufen die Scripte und man sieht die Problemstellen, jeweils 1. Zeile:

Code: Alles auswählen

/heizung$ python3 serial_byte.py 
<class 'str'> 			[color=#BF00BF]<<<<<<<=======[/color]
<class 'str'> 198
<class 'str'> 199
<class 'str'> 198
<class 'str'> 196
<class 'str'> 193
<class 'str'> 193

Code: Alles auswählen

~/heizung$ python3 serial2arduino.py
b'\x00\n'			[color=#804080]<<<===[/color]
b'27\r\n'
b'27\r\n'
b'26\r\n'
b'23\r\n'
b'21\r\n'
^Xb'22\r\n'
Danke und Gruß
Thomas

Re: Serielle Schnittstelle

Verfasst: Dienstag 19. Februar 2019, 21:47
von Sirius3
Du startest irgendwo mit der Übertragung, da kann e s eben sein, dass die erste Nachricht korrupt ist.

Re: Serielle Schnittstelle

Verfasst: Mittwoch 20. Februar 2019, 21:34
von wattwurm
Ja, dass kann ich mir vorstellen, man steigt ja auch nicht in einem fahrenden Zug ein.
Habe es nun so geschrieben (zumindest läuft es).

Geht es auch ohne die while-Schleife?

Code: Alles auswählen

~/heizung$ cat serial2arduino.py
#!/usr/bin/env python3
#coding: utf-8
import serial
def main():
    while True:
        try:
            with serial.Serial('/dev/ttyUSB0') as lines:
                for line in lines:
                    print(int(line))
        except ValueError:
            print('->NaN<-: Warten')
        except KeyboardInterrupt:
             #pass
             break

if __name__ == '__main__':
    main()

Code: Alles auswählen

/heizung$ python3 serial2arduino.py
->NaN<-: Warten
141
141
141
142
144
145
146
145
144
^Cthomas@raspberry:~/heizung$

Re: Serielle Schnittstelle

Verfasst: Mittwoch 20. Februar 2019, 22:04
von __blackjack__
@wattwurm: Ich denke schon.