Hallo,
ich möchte mit Phyton Sensordaten von einem uC auswerten. Dazu habe ich
pyserial installiert. Leider bekomme ich Fehler die ich nicht verstehe?
System:
Win 7 64
Python 3.4.1
pyserial 2.7
Der Code ist eigentlich 1 zu 1 kopiert:
1
import time
2
import serial
3
4
5
6
ser = serial.Serial(
7
port='\\.\COM3',
8
baudrate=9600,
9
parity=serial.PARITY_NONE,
10
stopbits=serial.STOPBITS_ONE,
11
bytesize=serial.EIGHTBITS
12
)
13
14
15
16
17
print("Bitte etwas eingeben")
18
a = input()
19
20
ser.write(a)
21
print("gesendet: " + a)
22
23
24
time.sleep(1)
25
26
27
b = ser.readline()
28
print("Antwort: " + b)
29
30
ser.close()
Ich bekomme folgende Fehlermeldung:
Traceback (most recent call last):
File "C:\Python34\serial_test.py", line 20, in <module>
ser.write(a)
File "C:\Python34\lib\site-packages\serial\serialwin32.py", line 283,
in write
data = to_bytes(data)
File "C:\Python34\lib\site-packages\serial\serialutil.py", line 76, in
to_bytes
b.append(item) # this one handles int and str for our emulation and
ints for Python 3.x
TypeError: an integer is required
Hallo,
casten nach int - im Prinzip ja.
Das sieht dann so aus:
> print("Bitte etwas eingeben")> a = input()>
# a als bytes
a = bytes(a, encoding = "ascii")
> ser.write(a)
# zurück zu String
a = a.decode("ascii")
> print("gesendet: " + a)
test schrieb:> Allerdings funktioniert der readline() Befehl nicht?
warum benutzt du readline?
Du weisst doch bestimt wie lang die antwort ist, also nimm read() und
sag wie viele zeichen gelesen werden sollen.
Ansonsten hat die Klasse serial.Serial keine Funktion readline. (siehe
Doku)
Die Klasse serial.FileLike hat aber diese Funktion.
http://pyserial.sourceforge.net/pyserial_api.html
Hallo,
readline() erwartet eine Eingabe, die mit '\n' abgeschlossen ist.
Einfacher kann es sein, zuerst zu prüfen, ob bzw. wieviele Bytes im
Empfangspuffer sind.
Das macht die Methode inWainting()
Wenn mehr als 0 Byte warten, dann kann man diese Anzahl von Bytes
einlesen
cnt = ser.inWaiting()
if cnt:
in = ser.read(cnt)
Ersteinmal danke für die viele Hilfe! Ich habe das jetzt mit einer
Schleife realisiert. Klappt auch bis auf einen Fall perfekt.
Ich sende über die seriele Schnittstelle Befehle an meinen uC. Das
klappt auch perfekt. Ein Problem bekomme ich allerdings wenn ich mir
Sensordaten vom uC schicken lasse und parallel Komandos an den uC
schicke.
Diese werden zwar eigentlich immer ausgeführt allerdings kommen die
Bestätigungsantworten nicht richtig durch bzw. gehen in den Sensordaten
unter.
Hat jemand so etwas schon einal programmiert oder hat eine Idee?
Mir ist bis jetzt noch keine intelligente Lösung eingefallen.
Mein einzigster Ansatz wäre durchgehend die Schnittstelle auszulesen und
eine Art RX Interrupt zu bauen, am besten ausgelagert in einen weiteren
thread.
Gibt es gängige Fehlerquellen die man in Python/pySerial begehen kann,
die dazu führen das Fehler beim senden auftreten? Teilweise müssen
einzelne Zeichen beim senden verloren gehen. Da mit HTerm alles
wunderbar funktioniert, gehe ich davon aus das der Fehler im Python Code
liegt?
Was mich ein wenig wundert ist, dass ich beim Sednen Probleme habe, da
es bei UART doch zwei Leitungen gibt. Also sollten Timing Fehler durch
paralles Senden und Empfangen eigentlich nicht auftreten?
Ich hätte noch mal eine Frage zu pyserial. Und zwar habe ich ein Problem
beim übertragen meines Stopbefehls an meinen uC. Über send_command wird
dieser gesendet. Das Problem ist, dass die Antwort zwischen Messwerten
verborgen ist. Deswegen die rx_filter Funktion. Vom Grunde her
funktioniert auch alles. Allerdings wenn ich die Übertragung von
Messwerten länger als ca. 4 sec laufen lasse und ich dann meinen
Stopbefehl sende, hängt sich das Programm auf. Das gleiche passiert nach
ca. 20sec bei Dauerübertragung von Messwerten. Ich taste mit 1kHz ab und
schreibe den Inputbuffer in ein array. Baudrate ist 115200. Kann es zu
irgendwelchen Überläufen kommen?
Vermutlich kommt es in send_command zu einer Endlosschleife. Aber ich
versteh nicht wie sie entsteht. Ich lösche meinen Buffer, sende dann
meinen Befehl, fülle meinen Buffer und lese ihn dann aus. Warum macht es
einen Unterschied wie lange ich vorher in den Buffer geschrieben habe.
Ich leere ihn doch. Sollte also immer gleich sein.
Kann es sein, dass der flushInput() Befehl nicht funktioniert? So länger
das Interval zwischen Übertragungsstart und stop ist, so mehr Messwerte
kommen vor der Antwort des uC am PC an. Die Anzahl müsste doch immer
gleich sein wenn man davor den Buffer entlehrt?
test schrieb:> Kann es sein, dass der flushInput() Befehl nicht funktioniert?
Den Verdacht hatte ich auch schon einmal.
Ersetze doch testhalber flushInput() durch:
while ser.inWaitung():
ser.read(1)
oder
i = ser.inWaiting()
while i:
ser.read(i)
i = ser.inWaiting()
Bringt das Besserung ?
OK, ich habe noch einmal ein wenig experimentiert. Wenn ich den Buffer
zwischendurch (bei mir waren es 30ms)leere habe ich keine Probleme. Ich
habe jetzt meine Abtastfrequenz auf 800Hz gesenkt und frage den Buffer
mit 1kHz ab. Wie kann das sein das der Buffer überläuft? Ist der QTimer
zu ungenau oder ist meine Funktionskette aus rx_buffer_read und
rx_filter zu langsam?
test schrieb:> Vermutlich kommt es in send_command zu einer Endlosschleife.
Bau doch einfach print()'s in die Schleifen ein, dann siehts Du, wo das
Programm hängt.
test schrieb:> while rx != "\n":
Das könnte so eine Stelle sein, bist Du sicher, dass ein "\n" ankommt ?
Naja ansich läuft das Programm ja. Hängt sich halt ab einen gewissen
Zeitraum auf. Lösche ich allerdings regelmäßig den InputBuffer passiert
das nicht. Für mich bedeutet das, dass der Fehler irgendwo dort liegen
muss? Gibt es sowas wie einen Buffer Überlauf bei pyserial? An der
Hardware sollte es eigentlich nicht liegen, da ich über HTerm noch kein
falsches Verhalten feststellen konnte.