pyserial-如何读取从串行设备发送的最后一行

2024-04-24 06:16:39 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个Arduino连接到我的计算机,运行一个循环,每100毫秒通过串行端口向计算机发送一个值

我想制作一个Python脚本,每隔几秒钟就从串行端口读取一次,所以我想让它只看到从Arduino发送的最后一个东西。

在Pyserial中你是怎么做到的?

这是我试过的不起作用的代码。它按顺序读取行。

import serial
import time

ser = serial.Serial('com4',9600,timeout=1)
while 1:
    time.sleep(10)
    print ser.readline() #How do I get the most recent line sent from the device?

Tags: the端口代码import脚本time顺序计算机
3条回答

也许我误解了你的问题,但由于它是一个串行行,你必须按顺序阅读从Arduino发送的所有内容-它将在Arduino中缓冲,直到你阅读它。

如果你想有一个状态显示,显示最新发送的东西-使用一个线程,其中包括你的问题代码(减去睡眠),并保持最后一个完整的一行读作为最新的一行从Arduino。

更新:mtasic的示例代码非常好,但是如果在调用inWaiting()时Arduino发送了一个部分行,则会得到一个截断行。相反,您要做的是将最后一个complete行放入last_received,并将部分行保持在buffer,以便它可以附加到下一次循环中。像这样的:

def receiving(ser):
    global last_received

    buffer_string = ''
    while True:
        buffer_string = buffer_string + ser.read(ser.inWaiting())
        if '\n' in buffer_string:
            lines = buffer_string.split('\n') # Guaranteed to have at least 2 entries
            last_received = lines[-2]
            #If the Arduino sends lots of empty lines, you'll lose the
            #last filled line, so you could make the above statement conditional
            #like so: if lines[-2]: last_received = lines[-2]
            buffer_string = lines[-1]

关于readline()的使用:下面是Pyserial文档要说的(为了清晰起见进行了一些编辑,并提到了readlines()):

Be careful when using "readline". Do specify a timeout when opening the serial port, otherwise it could block forever if no newline character is received. Also note that "readlines()" only works with a timeout. It depends on having a timeout and interprets that as EOF (end of file).

我觉得这很合理!

这些解决方案将占用CPU,同时等待字符。

您应该至少执行一个阻塞调用来读取(1)

while True:
    if '\n' in buffer: 
        pass # skip if a line already in buffer
    else:
        buffer += ser.read(1)  # this will block until one more char or timeout
    buffer += ser.read(ser.inWaiting()) # get remaining buffered chars

…和以前一样做分裂的事情。

from serial import *
from threading import Thread

last_received = ''

def receiving(ser):
    global last_received
    buffer = ''

    while True:
        # last_received = ser.readline()
        buffer += ser.read(ser.inWaiting())
        if '\n' in buffer:
            last_received, buffer = buffer.split('\n')[-2:]

if __name__ ==  '__main__':
    ser = Serial(
        port=None,
        baudrate=9600,
        bytesize=EIGHTBITS,
        parity=PARITY_NONE,
        stopbits=STOPBITS_ONE,
        timeout=0.1,
        xonxoff=0,
        rtscts=0,
        interCharTimeout=None
    )

    Thread(target=receiving, args=(ser,)).start()

相关问题 更多 >