web-dev-qa-db-fra.com

Communication série bidirectionnelle Python3: Lecture de données

J'essaie d'établir une communication bidirectionnelle via Python3. Un télémètre laser est branché sur l’un de mes ports USB et j’aimerais envoyer/recevoir des commandes. J'ai une feuille de commandes qui peuvent être envoyées et ce qu'elles renverraient, donc cette partie est déjà là. 

Ce dont j'ai besoin, c'est d'un moyen pratique de le faire en temps réel. Jusqu'à présent, j'ai le code suivant:

import serial, time

SERIALPORT = "/dev/ttyUSB0"
BAUDRATE = 115200

ser = serial.Serial(SERIALPORT, BAUDRATE)
ser.bytesize = serial.EIGHTBITS #number of bits per bytes
ser.parity = serial.PARITY_NONE #set parity check: no parity
ser.stopbits = serial.STOPBITS_ONE #number of stop bits
ser.timeout = None          #block read
ser.xonxoff = False     #disable software flow control
ser.rtscts = False     #disable hardware (RTS/CTS) flow control
ser.dsrdtr = False       #disable hardware (DSR/DTR) flow control
ser.writeTimeout = 0     #timeout for write

print ("Starting Up Serial Monitor")

try:
    ser.open()
except Exception as e:
    print ("Exception: Opening serial port: " + str(e))

if ser.isOpen():
    try:
        ser.flushInput()
        ser.flushOutput()
        ser.write("1\r\n".encode('ascii'))
        print("write data: 1")
        time.sleep(0.5)
        numberOfLine = 0
        while True:
            response = ser.readline().decode('ascii')
            print("read data: " + response)
            numberOfLine = numberOfLine + 1
            if (numberOfLine >= 5):
                break
        ser.close()
    except Exception as e:
        print ("Error communicating...: " + str(e))
else:
    print ("Cannot open serial port.")

Donc, dans le code ci-dessus, j'envoie "1", ce qui devrait déclencher la fonction "getDistance ()" du laser Finder et renvoyer la distance en mm. J'ai essayé ceci sur PuTTY et cela fonctionne, retourne des distances allant jusqu'à 4 chiffres. Cependant, lorsque je lance le script Python ci-dessus, ma sortie est uniquement la suivante:

Starting Up Serial Monitor
Exception: Opening serial port: Port is already open.
write data: 1
read data: 

et ça va pour toujours. Il n'y a aucune donnée lue ou que ce soit. 

Où est-ce que je me trompe?

3
Schütze

Apparemment, une version beaucoup plus simple du code a résolu le problème. 

import serial
import time

ser = serial.Serial('/dev/ttyUSB0', 115200, timeout = 1) # ttyACM1 for Arduino board

readOut = 0   #chars waiting from laser range Finder

print ("Starting up")
connected = False
commandToSend = 1 # get the distance in mm

while True:
    print ("Writing: ",  commandToSend)
    ser.write(str(commandToSend).encode())
    time.sleep(1)
    while True:
        try:
            print ("Attempt to Read")
            readOut = ser.readline().decode('ascii')
            time.sleep(1)
            print ("Reading: ", readOut) 
            break
        except:
            pass
    print ("Restart")
    ser.flush() #flush the buffer

Sortie, comme vous le souhaitez:

Writing:  1
Attempt to Read
Reading: 20
Restart
Writing:  1
Attempt to Read
Reading:  22
Restart
Writing:  1
Attempt to Read
Reading:  24
Restart
Writing:  1
Attempt to Read
Reading:  22
Restart
Writing:  1
Attempt to Read
Reading:  26
Restart
Writing:  1
Attempt to Read
Reading:  35
Restart
Writing:  1
Attempt to Read
Reading:  36
2
Schütze

Il me semble que votre ser.timeout = None peut causer un problème ici. Le premier cycle de votre boucle while semble bien se dérouler, mais votre programme se bloque lorsqu'il tente ser.readline() pour la deuxième fois.

Il y a plusieurs façons de résoudre ce problème. Ma méthode préférée serait de spécifier un délai d'attente non -None, peut-être d'une seconde. Cela permettrait à ser.readline() de renvoyer une valeur même lorsque le périphérique n'envoie pas de caractère de fin de ligne.

Une autre solution serait de changer votre ser.readline() pour qu'il soit quelque chose comme ser.read(ser.in_waiting) ou ser.read(ser.inWaiting()) afin de renvoyer tous les caractères disponibles dans le tampon.

0
Alton Campbell