连续从串口接收可变数据的Python代码

标签 python python-2.7 pyserial

我的电脑上安装了 Python 2.7.4 和 pyserial-2.5 win32。在这里,我将微 Controller 设备用作主设备(主要),将我的电脑用作从设备(次要)。这里每次单片机都会发送数据,而我的PC必须通过串口接收数据。我想要 Python 中的代码来接收连续数据。这里传输的数据大小会一直变化。这里我写了一段传输数据的代码,代码为

import serial
ser= serial.serial("COM10", 9600)
ser.write("Hello world\n")
x = ser.readline()
print(x)     

使用这段代码,我可以将数据传输到另一台 PC,我通过在另一台 PC 上打开 super 终端进行交叉检查,我可以看到传输的数据 (hello world)。

我也写了接收数据的代码:

import serial
ser=serial.serial("COM10", 9600)  
while 1:
if ser.inwaiting():
val = ser.readline(ser.inwaiting())
 print(val)  

如果我从 super 终端发送数据(你好吗),我可以使用上面的代码在我的 PC 中接收数据。

在此之前一切都很好。

我现在的问题是,当微 Controller 在可变时间段传输可变数据时,我需要在我的 PC 中使用 Python 接收该数据。我需要使用缓冲区来存储接收到的数据吗?如果是,代码将如何?为什么以及如何在 Python 中使用缓冲区?根据我在网上的搜索,缓冲区是用来对字符串进行切片的。

最佳答案

通常,与微型计算机通信时,您所做的是为轻量级的东西使用单个字符或创建通信协议(protocol)。基本上你有一个开始标志、结束标志和某种校验和来确保数据正确传输。有很多方法可以做到这一点。

以下代码适用于 Python 3。您可能需要对字节数据进行更改。

# On micro
data = b"[Hello,1234]"
serial.write(data)

在您要运行的计算机上

def read_data(ser, buf=b'', callback=None):
    if callback is None:
        callback = print

    # Read enough data for a message
    buf += ser.read(ser.inwaiting()) # If you are using threading +10 or something so the thread has to wait for more data, this makes the thread sleep and allows the main thread to run.
    while b"[" not in buf or b"]" not in buf:
        buf += ser.read(ser.inwaiting())

    # There may be multiple messages received
    while b"[" in buf and b']' in buf:
        # Find the message
        start = buf.find(b'[')
        buf = buf[start+1:]
        end = buf.find(b']')
        msg_parts = buf[:end].split(",") # buf now has b"Hello, 1234"
        buf = buf[end+1:]

        # Check the checksum to make sure the data is valid
        if msg_parts[-1] == b"1234": # There are many different ways to make a good checksum
            callback(msg_parts[:-1])

   return buf

running = True
ser = serial.serial("COM10", 9600)
buf = b''
while running:
    buf = read_data(ser, buf)

如果您使用的是 GUI,则线程很有用。然后,当您的 GUI 显示数据时,您可以让线程在后台读取数据。

import time
import threading

running = threading.Event()
running.set()
def thread_read(ser, callback=None):
    buf = b''
    while running.is_set():
        buf = read_data(ser, buf, callback)

def msg_parsed(msg_parts):
    # Do something with the parsed data
    print(msg_parsed)

ser = serial.serial("COM10", 9600)
th = threading.Thread(target=thread_read, args=(ser, msg_parsed))
th.start()


# Do other stuff while the thread is running in the background
start = time.clock()
duration = 5 # Run for 5 seconds
while running.is_set():
    time.sleep(1) # Do other processing instead of sleep
    if time.clock() - start > duration
        running.clear()

th.join() # Wait for the thread to finish up and exit
ser.close() # Close the serial port

请注意,在线程示例中,我使用了一个回调,它是一个作为变量传递并稍后调用的函数。另一种方法是将数据放入队列中,然后在代码的不同部分处理队列中的数据。

关于连续从串口接收可变数据的Python代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16870335/

相关文章:

python - 在 NetworkX 中的节点顶部显示可变大小的圆圈

javascript - netlify 构建失败 : npm ERR! 路径/opt/build/repo/package.json

python - Python 3.4 是否向后兼容 2.7 程序/库?

python - 将 python 字符串列表转换为字节数组

python - 加速 Python

python - 如何使线图中的颜色在 matplotlib 和 python 中淡出

python - 将多个元素(基于条件)移动到列表末尾

python - 在 Python 中读取/写入文件

python - 使用 pySerial 包的完整示例

python - Pyserial 读取没有返回我写出的内容