【问题标题】:Problems when storing and processing serial data存储和处理串行数据时的问题
【发布时间】:2020-09-21 05:14:42
【问题描述】:

我正在读取串行数据并尝试对单个数据包进行排序和显示。 问题是当我收到一个数据包时,我可以使用 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()

【问题讨论】:

    标签: python queue python-multithreading pyserial


    【解决方案1】:

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

    • 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 并将它们拆分...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-05
      • 2014-05-14
      • 2023-04-10
      • 1970-01-01
      相关资源
      最近更新 更多