python - 存储和处理串行数据时的问题
问题描述
我正在读取串行数据并尝试对单个数据包进行排序和显示。问题是当我收到一个数据包时,我可以使用 print() 打印它,并且数据包打印得很好。但是当我将此数据包添加到 list[] 或尝试将数据包添加到 Listbox(tkinter) 时,这些数据包有时会被合并/加扰,我会得到两个数据包显示为一个更长的数据包。
- 串行数据以不规则的间隔出现,有时在很短的时间内以几个数据包的突发形式出现。
- 数据包长度在 9 到 26 个 ASCII 字符之间可变,并以 \r 结尾
- 串行速度目前限制为 115200,这是在不阻塞通信的情况下传输数据包突发的最低速度。
这是我到目前为止所尝试的:
尝试在没有队列的情况下运行处理,只是在数据包到来时直接处理它们 - 结果, print() 所有数据包都打印正常,但是当将数据包添加到 list[] 和/或 Listbox(tkinter) 时,一些数据包被组合成单个数据包。
尝试实现 FIFO 队列,并在一个线程中将数据包添加到队列中,并在另一个线程中删除/处理它们,所以我认为它们将完全独立 - 结果 - 与上面相同,print() 所有数据包都打印好了,但是当将数据包添加到 list[] 和/或 Listbox(tkinter) 时,一些数据包被组合成单个数据包。
我尝试了许多代码变体,但都失败了。打印功能正确显示数据包,但是当我尝试对它们做任何事情时,即将它们排序到列表中或将它们添加到列表框中,一些数据包被合并......。似乎当数据包以最小的时间延迟突然出现时,python 处理它们的速度不够快?但是打印功能确实跟上了,当我运行单独的线程将数据包放入队列和单独的线程将它们从队列中读取时,时间应该不是问题,对吧?
请帮忙,我已经用尽了我所有的想法......</p>
我正在使用串行读取线功能来获取数据包:
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 的数据包在他们里面并分裂他们......
推荐阅读
- python - “GetPassWarning:无法控制终端上的回声”是什么意思?“设备的 ioctl 不合适”?
- python - 通过 python 脚本安装软件包后如何更新 pip 的已安装发行版列表?
- ios - 基于调试级别的 Swift NSLog 启用
- ios - 以错误的顺序从 Firestore 存储下载 URL
- javascript - 问:我如何附加附件带有src地址的iframe?
- ruby - CSV.foreach 未读取 CSV 文件中的第一列
- javascript - Brightcove:转到视频中的特定时间
- hyperledger-fabric - 未安装 Docker 并通过下载 Fabric 图像
- r - Ifelse...在这里使用正确的功能吗?
- r - 取消合并 ggplot 图例