如何同时检查串行输入和键盘输入(同时使用readchar和串行库)

时间:2019-10-29 20:54:17

标签: python linux raspberry-pi

我试图在树莓派中使用python3编写以下代码:

1)等待14位数的条形码(条形码扫描器通过usb端口连接,并接收输入作为键盘数据)

2)读取条形码后,等待串行通信(设备连接到USB端口并发送串行命令。可能是一个或多个。。。)的想法是,接收到的所有命令都将与扫描的条形码

3)当读取新条形码时,必须停止等待串行命令的过程。这是我没有弄清楚该怎么做的部分

经过研究,我决定将“ readchar”库用于条形码扫描仪,将“ serial”库用于所接收的串行通信。他们两个人都自己工作,但问题是当我尝试同时检测到这两种情况时。

在以下代码中,我设法读取了条形码,然后等待5行串行通信以最终重复该过程并再次读取条形码。该程序现在可以正常工作,但是问题是我不知道我将收到多少行串行通信,因此我需要以某种方式检测新条形码,同时还要等待接收串行通信。

import readchar
import time
import serial

ser = serial.Serial(
 port='/dev/ttyUSB0',
 baudrate = 115200,
 parity=serial.PARITY_NONE,
 stopbits=serial.STOPBITS_ONE,
 bytesize=serial.EIGHTBITS,
 timeout=1
)

print("Waiting for barcode...")
while 1:
    inputStr = ""
    while len(inputStr) != 14:  #detect only 14 digit barcodes
        inputStr += str(readchar.readchar())
        inputStr = ''.join(e for e in inputStr if e.isalnum())  #had to add this to strip non alphanumeric characters           
    currentCode = inputStr
    inputStr = ""
    print(currentCode)
    ser.flushInput()
    time.sleep(.1)

    # Wait for 5 lines of serial communication
    # BUT it should break the while loop when a new barcode is read!
    count = 0  
    while count < 5:
        dataRead=ser.readline()
        if len(dataRead) > 0:
            print(dataRead)
            count+=1

    print("Waiting for barcode...")

如果我在while循环中添加一个条件,该条件使用(ser.readline())读取串行通信,以便从扫描仪(readchar.readchar())读取字符,则会使事情搞砸。就像readline和到达器不能在while循环中一样。

做一些研究,我认为我需要使用异步IO,线程或类似的东西,但是我没有任何线索。我也不知道是否可以继续使用相同的库(串行和readchar)。请帮助

2 个答案:

答案 0 :(得分:1)

我不确定(我没有条形码阅读器和串行端口设备),但是根据您所说的,我认为您不需要线程,您只需要依靠缓冲区来保存数据,直到您有时间阅读它们。

只需将第二个while循环的条件更改为:

while serial.inWaiting() != 0:

这样,您将确保串行端口上的RX缓冲区为空。根据您设备的速度和时间,这种方法可能行不通。

您还可以尝试在清空缓冲区后添加短暂的延迟:

import serial
import time
ser=serial.Serial(port="/dev/ttyUSB0",baudrate=115200, timeout=1.0)          
time.sleep(1)
data=b""
timeout = time.time() + 1.0
while ser.inWaiting() or time.time()-timeout < 0.0:   #keep reading until the RX buffer is empty and wait for 1 seconds to make sure no more data is coming
    if ser.inWaiting() > 0:
        data+=ser.read(ser.inWaiting())
        timeout = time.time() + 1.0
    else:
        print("waiting...")

在接收到最后一个字节后,这将继续尝试从端口读取1秒钟,以确保没有其他消息。您可能还想根据延迟的持续时间进行播放,这又取决于设备的速度和时序。

同样,我没有您的设备,所以我无法判断,但是您从条形码/键盘上读取字符的方式看起来并非最佳。我怀疑readchar是最好的方法。归根结底,您的条形码读取器可能是一个串行端口。您可能想研究一下和/或找到一种更有效的方法,以便一次性读取多个键盘笔触。

答案 1 :(得分:0)

我在另一个问题中找到了这个答案:

How to read keyboard-input?

我已经尝试过了,并且有效!我还将尝试Marcos G提出的方法。