Lectura de datos serie en tiempo real en Python
Estoy usando un script en Python para recopilar datos de un microcontrolador PIC a través de un puerto serie a 2Mbps.
El PIC funciona con sincronización perfecta a 2Mbps, también el puerto serie usb FTDI funciona muy bien a 2Mbps (ambos verificados con osciloscopio)
Estoy enviando mensajes (tamaño de unos 15 caracteres) alrededor de 100-150 veces por segundo y el número allí aumenta (para comprobar si tengo mensajes que se pierden y así sucesivamente)
En mi portátil tengo Xubuntu corriendo 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 1 por 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 1 por 1), pero probablemente se almacenan en algún búfer, ya que cuando apago la foto, puedo ir a la cocina y volver y todavía estoy 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
3 answers
Puede usar inWaiting()
para obtener la cantidad de bytes disponibles en la cola de entrada.
Entonces 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.
Está esperando el tiempo de espera en cada lectura, ya que espera eol. la entrada de serie Q sigue siendo la misma, solo un montón de tiempo para llegar al "final" del búfer, Para entenderlo mejor: está escribiendo a la entrada Q como un coche de carreras, y leyendo como un coche viejo :)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-11 15:07:32
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 bloqueo, por lo que está esperando hasta recibir datos que tengan una nueva línea (\n o \r\ n) al final: line = ser.readline ()
Una vez que tenga los datos, volverá LO antes posible.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-21 10:41:09
De el manual:
Posibles valores para el parámetro timeout: … x establecer el tiempo de espera en x segundos
Y
Readlines (sizehint=None, eol='\n') Lee una lista de líneas, hasta el tiempo de espera. sizehint se ignora y solo está presente para API compatibilidad con objetos de archivo incorporados.
Tenga en cuenta que esta función solo devuelve en un tiempo de espera.
Por lo que su readlines
volverá a lo sumo cada 2 segundos. Use read()
como Tim sugirió.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-11 14:57:56