簡體   English   中英

在Python中實時讀取串行數據

[英]Reading serial data in realtime in Python

我使用Python中的腳本通過串行端口以2Mbps從PIC單片機收集數據。

PIC工作在2Mbps的完美時序,FTDI usb串行端口也能在2Mbps下工作(均通過示波器驗證)

我發送消息(大約15個字符大小)大約每秒100-150倍,並增加數量(以檢查我是否有丟失的消息等)

在我的筆記本電腦上我有Xubuntu作為虛擬機運行,我可以通過Putty和我的腳本(python 2.7和pySerial)讀取串口

問題:

  • 當通過Putty打開串口時,我看到所有消息(消息中的計數器逐1遞增)。 完善!
  • 當通過pySerial打開串口時,我看到所有消息,但不是每秒接收100-150x,而是以每秒約5次的速度接收它們(仍然消息以1為單位遞增)但它們可能存儲在某個緩沖區中,就像我關機時一樣PIC,我可以去廚房然后回來,我仍然收到消息。

這是代碼(我省略了大部分代碼,但循環是相同的):

ser = serial.Serial('/dev/ttyUSB0', 2000000, timeout=2, xonxoff=False, rtscts=False, dsrdtr=False) #Tried with and without the last 3 parameters, and also at 1Mbps, same happens.
ser.flushInput()
ser.flushOutput()
While True:
  data_raw = ser.readline()
  print(data_raw)

任何人都知道為什么pySerial需要這么多時間從串口讀取直到行尾? 有幫助嗎?

我想實時擁有這個。

謝謝

您可以使用inWaiting()來獲取輸入隊列中可用的字節數。

然后你可以使用read()來讀取字節,類似於:

While True:
    bytesToRead = ser.inWaiting()
    ser.read(bytesToRead)

為什么不使用readline() 在這種情況下,從文檔:

Read a line which is terminated with end-of-line (eol) character (\n by default) or until timeout.

你正在等待每次讀數的超時,因為它等待eol。 串行輸入Q保持不變只需要很長時間才能到達緩沖區的“結束”,為了更好地理解它:你正在寫入輸入Q就像賽車一樣,讀起來就像一輛舊車:)

打開串口時,需要將超時設置為“無”:

ser = serial.Serial(**bco_port**, timeout=None, baudrate=115000, xonxoff=False, rtscts=False, dsrdtr=False) 

這是一個阻塞命令,所以你要等到收到末尾有換行符(\\ n或\\ r \\ n)的數據:line = ser.readline()

獲得數據后,它將盡快返回。

手冊

參數超時的可能值:... x set timeout to x seconds

readlines(sizehint = None,eol ='\\ n')讀取行列表,直到超時。 sizehint被忽略,僅用於與內置File對象的API兼容性。

請注意,此函數僅在超時時返回。

因此,您的readlines最多每2秒返回一次。 如Tim建議的那樣使用read()

可以在這里找到一個非常好的解決方案:

這是一個類,用作pyserial對象的包裝器。 它允許您讀取沒有100%CPU的行。 它不包含任何超時邏輯。 如果發生超時,則self.s.read(i)返回一個空字符串,您可能希望拋出異常以指示超時。

據作者說,它也應該很快:

下面的代碼給我790 kB / sec,而用pyserial的readline方法替換代碼只給我170kB /秒。

class ReadLine:
    def __init__(self, s):
        self.buf = bytearray()
        self.s = s

    def readline(self):
        i = self.buf.find(b"\n")
        if i >= 0:
            r = self.buf[:i+1]
            self.buf = self.buf[i+1:]
            return r
        while True:
            i = max(1, min(2048, self.s.in_waiting))
            data = self.s.read(i)
            i = data.find(b"\n")
            if i >= 0:
                r = self.buf + data[:i+1]
                self.buf[0:] = data[i+1:]
                return r
            else:
                self.buf.extend(data)

ser = serial.Serial('COM7', 9600)
rl = ReadLine(ser)

while True:

    print(rl.readline())

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM