2013-07-23 159 views
3

我的問題是,PySerial似乎失去了一些數據包,我不知道爲什麼。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)這一行,那麼一切正常,我會收到預期的數據。所以對我來說,似乎我的腳本從串口讀取數據太慢......但是爲什麼?

回答

5

接收機的分裂是扔行了。這應該更好的工作:

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 
+0

謝謝,它工作得很好! – user2494129

1

當你什麼也沒有睡覺時......一個串行緩衝區是相當小的,可能只是填滿睡眠的時間(在接收者身上)......一旦它完全不能再服用,直到你讀取它,以便其他位丟失(或者它們可能會覆蓋緩衝區中的位)...因爲串行沒有一些握手說嘿我收到這些位

當您從發件人取消註釋睡眠行時讓它睡覺,直到接收已經閱讀全碼流和清理出來的更多的數據

或也許嘗試

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

,因爲信息可以與

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

丟失,如果你已經收到2(或更多)\n

+0

如果我對你有幫助,我應該刪除接收腳本中的睡眠?我嘗試過,但沒有任何變化。 – user2494129

+0

已更新答案,以反映我的腳本中看到的其他潛在問題 –

+0

感謝您提供了很好的建議,我沒有想過!從理論上講,應該不可能在一行中接收兩個(或更多)'\ n',但它會使程序更加防彈,所以我會添加它。謝謝! – user2494129