4

我的问题是,PySerial 似乎丢失了一些数据包,我不知道为什么。

我有两个 python 脚本,第一个从文本文件中读取数据并将其写入微控制器,在微控制器中处理数据。然后,微控制器通过不同的串行端口将修改后的数据发送回 PC。(澄清:我需要两个串口,因为在最终的应用程序中,脚本将在不同的PC上运行。但是,出于测试目的,在一台PC上运行两个脚本更容易)

所以基本上,我的硬件设置如下:

PC ----(serial port 1)----> microcontroller
   <---(serial port 2)----- 

将数据写入微控制器后,我期望得到一定数量的数据字节。如果我使用终端程序(如超级终端)来监控接收到的数据,一切看起来都很好。但是,如果我尝试使用 Python 脚本读取数据,我只会得到预期数据字节的一小部分。

例如:

+--------------------+--------------------+
| with HyperTerminal | with Python script |
+--------------------+--------------------+
| 1:W:00522          | 1:W:00522          |
| 1:W:00532          | 1:W:00532          |
| 1:W:00518          | 1:W:00522          |
| 1:W:00522          | 1:W:00526          |
| 1:W:00522          | 1:W:00514          |
| 1:W:00526          | 1:W:00520          |
| 1:W:00514          | 1:W:00514          |
| 1:W:00520          | 1:W:00522          |
| 1:W:00520          | 1:W:00526          |
| 1:W:00514          | 1:W:00520          |
| 1:W:00516          | 1:W:00526          |
| 1:W:00522          | 1:W:00520          |
| 1:W:00526          | 1:W:00524          |
| 1:W:00520          | 1:W:00526          |
| 1:W:00520          | 1:W:00532          |
| 1:W:00526          | 1:W:00506          |
| 1:W:00522          | 1:W:00520          |
| 1:W:00520          | 1:W:00526          |
| 1:W:00524          | 1:W:00524          |
| 1:W:00522          | 1:W:00526          |
| 1:W:00526          | 1:W:00514          |
| 1:W:00514          | 1:W:00522          |
| 1:W:00532          | 1:W:00520          |
| 1:W:00506          | 1:W:00510          |
| 1:W:00522          | 1:W:00506          |
| 1:W:00520          |                    |
| 1:W:00526          |                    |
| 1:W:00530          |                    |
| 1:W:00524          |                    |
| 1:W:00526          |                    |
| 1:W:00514          |                    |
| 1:W:00514          |                    |
| 1:W:00522          |                    |
| 1:W:00524          |                    |
| 1:W:00520          |                    |
| 1:W:00510          |                    |
| 1:W:00506          |                    |
+--------------------+--------------------+

如您所见,如果我尝试使用 Python 脚本从串行端口读取数据,则会丢失一些数据。由于事实上,如果我使用终端程序,我会得到预期的数据,我假设我的 Python 脚本有错误。

我用于向微控制器发送数据的 Python 脚本如下所示:

import serial
import re
import time

class digiRealTest():
    def __init__(self):
        #configure serial port 
        self.ser = serial.Serial(7, 9600, parity=serial.PARITY_NONE) 


    def main(self):
        filepath = 'C:\\Users\\Bernhard\\Desktop\\TomatoView\\Qt\\test_output.txt'
        with open(filepath, 'r') as content_file:
            content = content_file.read().decode("hex")
            for match in re.finditer('[\02](.*?)[\03]', content, re.S):
                res = match.group(1)
                complete =  '\x02' + res + '\x03'
                # time.sleep(0.3) <-- if i uncomment this line, it work's!!!
                self.ser.write(complete)

if __name__ == "__main__": #wenn Modul direkt ausgefuehrt wird
    d = digiRealTest()
    d.main()

我用于接收从微控制器发送的数据的 Python 脚本:

import Queue
import threading
import serial

class mySerial(threading.Thread):
    def __init__(self, queue):
        super(mySerial, self).__init__()

        self.queue = queue #the received data is put in a queue

        self.buffer = ''

        #configure serial connection
        self.ser = serial.Serial(timeout = 0, port = 3, baudrate=9600)

    def run(self):              
        while True:
            self.buffer += self.ser.read(self.ser.inWaiting()) #read all char in buffer
            if '\n' in self.buffer: #split data line by line and store it in var
                var, self.buffer = self.buffer.split('\n')[-2:]
                self.queue.put(var) #put received line in the queue
        time.sleep(0.01)   #do not monopolize CPU



class Base():
    def __init__(self):
        self.queue = Queue.Queue(0) #create a new queue
        self.ser = mySerial(self.queue) 
        self.ser.start() #run thread


    def main(self   ):
        while(True):
            try:
                var = self.queue.get(False) #try to fetch a value from queue
            except Queue.Empty: 
                pass #if it is empty, do nothing
            else:
                print(var) 


if __name__ == '__main__':
    b = Base() 
    b.main()

我不知道为什么,但如果我取消注释#time.sleep(0.3)发送脚本中的行,一切正常,我会得到预期的数据。所以对我来说,似乎不知何故我从串口读取数据的脚本太慢了....但是为什么呢?

4

2 回答 2

7

你的接收器的分裂正在扔掉线。这应该会更好:

def run(self):              
    while True:
        self.buffer += self.ser.read(self.ser.inWaiting()) #read all char in buffer
        while '\n' in self.buffer: #split data line by line and store it in var
            var, self.buffer = self.buffer.split('\n', 1)
            self.queue.put(var) #put received line in the queue
        time.sleep(0.01)   #do not monopolize CPU

您还可以通过在创建串行端口时摆脱超时来摆脱轮询/睡眠,并在队列中没有任何内容时请求 1 个字节。

class mySerial(threading.Thread):
    def __init__(self, queue):
        super(mySerial, self).__init__()
        self.queue = queue #the received data is put in a queue
        self.buffer = ''
        #configure serial connection
        self.ser = serial.Serial(port = 3, baudrate=9600)

    def run(self):              
        while True:
            self.buffer += self.ser.read(self.ser.inWaiting() or 1) #read all char in buffer
            while '\n' in self.buffer: #split data line by line and store it in var
                var, self.buffer = self.buffer.split('\n', 1)
                self.queue.put(var) #put received line in the queue
于 2013-07-23T20:04:12.267 回答
2

当你睡觉时什么都没有发生......串行缓冲区相当小,可能只是在睡眠所需的时间内填满(在接收器上)......一旦它满了,它就不能再花时间了,直到你阅读它,所以其他位丢失(或者它们可能覆盖缓冲区中的位)......因为串行没有握手说嘿我收到了这些位

当您从发送方取消注释睡眠线时,让它进入休眠状态,直到接收方读取整个流并将其清除以获取更多数据

或者试试

var, self.buffer = self.buffer.split('\n',1)  #this will only split once

因为信息可能会丢失

var, self.buffer = self.buffer.split('\n')[-2:]

如果您收到 2 个(或更多)\n

于 2013-07-23T19:24:42.493 回答