存储和处理串行数据时出现问题

问题描述

我正在读取串行数据,并试图对单个数据包进行分类显示。 问题是,当我收到一个数据包时,可以使用print()打印它,并且数据包可以完美打印。但是,当我将此数据包添加到list []或尝试将该数据包添加到ListBox(tkinter)时,有时会合并/加扰这些数据包,而我会看到两个数据包显示一个更长的数据包。

  • 串行数据以不规则的间隔出现,有时会在很短的时间内突发几个数据包。
  • 数据包长度在9到26个ASCII字符之间可变,并以\ r终止
  • 目前,串行速度限制为115200,这是在不中断通信的情况下获得突发传输数据包的最低速度。

这是我到目前为止尝试过的:

  • 试图在没有队列的情况下运行处理,只是直接处理数据包-结果,将所有数据包print()打印成功,但是将数据包添加到list []和/或ListBox(tkinter)时,有些数据包组合成一个小包。

  • 试图实现FIFO队列,并在一个线程中将数据包添加到队列,并在另一个线程中删除/处理它们,所以我认为它们将是完全独立的-结果-与上述相同,print( )所有数据包都可以正常打印,但是将数据包添加到list []和/或ListBox(tkinter)时,某些数据包将合并为一个数据包。

我尝试了许多代码变体,但都失败了。打印功能可以正确显示数据包,但是当我尝试对它们执行任何操作时,即将它们分类到列表中或将其添加到列表框中,某些数据包就会合并在一起……。看来,当数据包以突发的方式传入时,它们之间的时间延迟最小,python是否无法足够快地处理它们?但是打印功能确实可以跟上,并且当我运行用于将数据包放入队列的单独线程和用于从队列中读取数据包的单独线程时,计时应该不是问题,对吧?

请帮助,我已经用尽了所有想法...

我正在使用串行读取线功能获取数据包:

def serial_read_line(port):
    ser = serial.Serial(port,115200,timeout=0.01)
    ser.flushinput()
    while 1:
        x = ser.readline()
        if len(x) < 1:
            pass
        else:
            y = str(x.decode('utf-8'))
            if y != x:
                x = y
                return y

以上功能在单独的线程中运行,因此不会阻塞程序。

# *********** Scanning for packets **********
# scan for incoming packets
# set global variable for start/stop packet scan
stop = 1
q1 = queue.Queue()


def ser_packet_scan():
    port = serial_port_selection.get()
    global q1
    while True:
        packet_1 = sio.serial_read_line(port)
        q1.put(packet_1)
        process_packets()
        if stop == 1:
            break


# starting thread for packet scan
def start_thread():
    global stop
    stop = 0
    th = Thread(target=ser_packet_scan)
    th.start()
    th2 = Thread(target=process_packets)
    th2.start()


# stopping thread for packet scan
def stop_thread():
    global stop
    stop = 1

该处理在单独的线程中运行,我也尝试在主程序线程中运行它。

def process_packets():
    # sort packets into lists
    global q1
    pckt_r = q1.get()
    print(pckt_r)
    pck.sort_into_lists(pckt_r)
    # update packet lists
    if list_Box_selection.get() == 'Running':
        list_Box_display.insert(0,pckt_r)
        # limit listBox display size
        if list_Box_display.size() > 100:
            list_Box_display.delete(END)
…
…
    # time.sleep(0.5) have tried with the sleep and without it… no diference...
    q1.task_done()

解决方法

好的,我找到了解决方案。我还发现了几个问题。

  • print()函数自动执行换行并理解\ r,因此即使数据包由两个或多个数据包组成,我的打印输出也始终是正确的。
  • 内置函数readline()不能很好地工作。即使存在\ r字符,某些数据包仍会合并。

解决方案: 我已经用自定义函数替换了内置的readline():

def read_line_c(ser):
    buf = bytearray()
    i = buf.find(b"\r")
    if i >= 0:
        r = buf[:i + 1]
        buf[i + 1:]
        return r
    while True:
        i = max(1,min(2048,ser.in_waiting))
        data = ser.read(i)
        i = data.find(b"\r")
        if i >= 0:
            r = buf + data[:i + 1]
            buf[0:] = data[i + 1:]
            return r
        else:
            buf.extend(data)

使用此自定义readline数据包似乎一切正常,但我需要对其进行更多测试,以查看是否存在任何问题...或者,我可以使用内置的readline(),然后查找那些在其中包含\ r并将其拆分...