Leyendo datos en serie en tiempo real en Python

Estoy usando un script en Python para recostackr datos de un microcontrolador PIC a través del puerto serie a 2Mbps.

El PIC funciona con una sincronización perfecta a 2Mbps, también el puerto serie USB FTDI funciona muy bien a 2Mbps (ambos verificados con un osciloscopio)

Estoy enviando mensajes (tamaño de aproximadamente 15 caracteres) aproximadamente 100-150x veces por segundo y el número aumenta (para comprobar si tengo mensajes perdidos, etc.)

En mi computadora portátil tengo Xubuntu ejecutándose como máquina virtual, puedo leer el puerto serie a través de Putty y a través de mi script (python 2.7 y pySerial)

El problema:

  • Al abrir el puerto serie a través de Putty, veo todos los mensajes (el contador en el mensaje aumenta de 1 en 1). ¡Perfecto!
  • Al abrir el puerto serie a través de pySerial, veo todos los mensajes, pero en lugar de recibir 100-150x por segundo, los recibo a aproximadamente 5 por segundo (aún así el mensaje aumenta de 1 en 1), pero probablemente se almacenan en algún búfer como cuando apago El PIC, puedo ir a la cocina y volver, y sigo recibiendo mensajes.

Aquí está el código (omití la mayor parte del código, pero el bucle es el mismo):

ser = serial.Serial('/dev/ttyUSB0', 2000000, timeout=2, xonxoff=False, rtscts=False, dsrdtr=False) #Tried with and without the last 3 parameters, and also at 1Mbps, same happens. ser.flushInput() ser.flushOutput() While True: data_raw = ser.readline() print(data_raw) 

¿Alguien sabe por qué pySerial tarda tanto tiempo en leer desde el puerto serie hasta el final de la línea? ¿Alguna ayuda?

Quiero tener esto en tiempo real.

Gracias

Puede usar inWaiting() para obtener la cantidad de bytes disponibles en la cola de entrada.

Luego puedes usar read() para leer los bytes, algo así:

 While True: bytesToRead = ser.inWaiting() ser.read(bytesToRead) 

¿Por qué no usar readline() en este caso de Docs?

 Read a line which is terminated with end-of-line (eol) character (\n by default) or until timeout. 

Usted está esperando el tiempo de espera en cada lectura, ya que espera eol. la entrada serial Q sigue siendo la misma, solo un montón de tiempo para llegar al “final” del búfer. Para entenderlo mejor: estás escribiendo en la entrada Q como un auto de carreras, y leyendo como un auto viejo 🙂

Debe establecer el tiempo de espera en “Ninguno” cuando abra el puerto serie:

 ser = serial.Serial(**bco_port**, timeout=None, baudrate=115000, xonxoff=False, rtscts=False, dsrdtr=False) 

Este es un comando de locking, por lo que está esperando hasta que reciba los datos que tienen una línea nueva (\ n o \ r \ n) al final: línea = ser.readline ()

Una vez que tengas los datos, volverá lo antes posible.

Del manual :

Valores posibles para el tiempo de espera del parámetro: … x establecer el tiempo de espera en x segundos

y

readlines (sizehint = None, eol = ‘\ n’) Lee una lista de líneas, hasta que se agote el tiempo. sizehint se ignora y solo se presenta por compatibilidad de API con los objetos de archivo integrados.

Tenga en cuenta que esta función solo regresa en un tiempo de espera.

Así que sus readlines volverán a lo sumo cada 2 segundos. Use read() como Tim sugirió.